Я предпочитаю третий подход, который использует лучшее из
подходов 1 и 2, описанных пользователем 1016403 .
Подход 3
- Сохраните свойства базы данных на
server.xml
- ссылаться на
server.xml
свойства базы данных из веб-приложенияMETA-INF/context.xml
Подход 3 преимущества
Хотя первый пункт полезен по соображениям безопасности, второй пункт полезен для ссылки на значение свойств сервера из веб-приложения, даже если значения свойств сервера изменятся.
Более того, разделение определений ресурсов на сервере от их использования веб-приложением делает такую конфигурацию масштабируемой в разных организациях с различной сложностью, где разные группы работают на разных уровнях / уровнях: команда администраторов сервера может работать без конфликтов с командой разработчиков, если администратор использует то же самое. Имя JNDI с указанием разработчика для каждого ресурса.
Реализация подхода 3
Определите имя JNDI jdbc/ApplicationContext_DatabaseName
.
Объявите jdbc/ApplicationContext_DatabaseName
различные свойства и значения в Tomcat, server.xml
используя что-то вроде этого:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName" auth="Container" type="javax.sql.DataSource"
username="dbUsername" password="dbPasswd"
url="jdbc:postgresql://localhost/dbname"
driverClassName="org.postgresql.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"/>
</GlobalNamingResources/>
Свяжите jdbc/ApplicationContext_DatabaseName
свойства из веб-приложения META-INF/context.xml
с помощью частного контекста JNDI приложения, java:comp/env/
указанного в name
атрибуте:
<Context path="/ApplicationContext" ... >
<!--
"global" attribute links to GlobalNamingResources in the ${catalina.base}/conf/server.xml (server administrator team)
"name" attribute is relative to the application-private JNDI context java:comp/env/ and is looked up from the java web application (application developer team)
-->
<ResourceLink global="jdbc/ApplicationContext_DatabaseName" name="jdbc/DatabaseName" type="javax.sql.DataSource"/>
</Context>
Наконец, чтобы использовать ресурс JNDI, укажите имя JNDI jdbc/DatabaseName
в дескрипторе развертывания веб-приложения:
<resource-ref>
<description>DatabaseName's Datasource</description>
<res-ref-name>jdbc/DatabaseName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
и в контексте Spring:
<jee:jndi-lookup id="DatabaseNameDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
Подход 3 недостатка
Если имя JNDI получает изменилось , то как server.xml
и META-INF/context.xml
должны быть отредактированы и развертывание будет необходимо; тем не менее такой сценарий встречается редко.
Подход 3 варианта
Множество источников данных, используемых одним веб-приложением
Просто добавьте конфигурации в Tomcat server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContext_DatabaseName2" ... />
...
</GlobalNamingResources/>
Добавить веб-приложение ссылки META-INF/context.xml
с помощью частного JNDI-контекста приложения, java:comp/env/
указанного в name
атрибуте:
<Context path="/ApplicationContext" ... >
<ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
<ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
...
</Context>
Наконец, добавьте использование ресурсов JNDI в дескриптор развертывания веб-приложения:
<resource-ref>
<description>DatabaseName1's Datasource</description>
<res-ref-name>jdbc/DatabaseName1</res-ref-name> ...
</resource-ref>
<resource-ref>
<description>DatabaseName2's Datasource</description>
<res-ref-name>jdbc/DatabaseName2</res-ref-name> ...
</resource-ref>
...
и в контексте Spring:
<jee:jndi-lookup id="DatabaseName1DataSource"
jndi-name="jdbc/DatabaseName1" ... />
<jee:jndi-lookup id="DatabaseName2DataSource"
jndi-name="jdbc/DatabaseName2" ... />
...
Множество источников данных, используемых многими веб-приложениями на одном сервере
Просто добавьте конфигурацию в Tomcat server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
...
</GlobalNamingResources/>
остальные конфигурации должны быть выведены из предыдущего варианта.
Многие источники данных в одной базе данных используются многими веб-приложениями на одном сервере.
В таком случае server.xml
конфигурации Tomcat, такие как:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
попадает в два разных веб-приложения, META-INF/context.xml
например:
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
и вроде:
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
поэтому кто-то может быть обеспокоен тем фактом, что одно name="jdbc/DatabaseName"
и то же просматривается, а затем используется двумя разными приложениями, развернутыми на одном сервере: это не проблема, потому что jdbc/DatabaseName
это частный контекст JNDI приложения java:comp/env/
, поэтому ApplicationContextX
при использованииjava:comp/env/
невозможно (по дизайну) найдите ресурс, на который есть ссылка global="jdbc/ApplicationContextY_DatabaseName"
.
Конечно, если вы чувствуете себя более расслабленным без этого беспокойства, вы можете использовать другую стратегию именования, например:
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... />
</Context>
и вроде:
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... />
</Context>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
Если бы ресурсы были пулами соединений, это дало бы вам два отдельных пула, по одному на каждое веб-приложение ? В то время как, если бы я связался из обоих веб-приложений с одним ресурсом, был бы только один пул соединений, верно? Есть ли причины предпочесть одно другому? (отдельные пулы соединений с БД по одному для каждого веб-приложения против одного пула соединений, общего для всех веб-приложений)? Благодарю.YOUR_APP.xml
файлЯ предпочитаю подход 2 (поместить все (а не только некоторые атрибуты в конфигурацию), но вместо того, чтобы размещать их в глобальном
server.xml
или глобальном,context.xml
вы должны поместить его в файл для конкретного приложения в вашем Tomcat.context.xml.default
YOUR_APP.xml
YOUR_APP.xml
Файл находится в$catalinaHome/conf/<engine>/<host>
(напримерconf/Catalina/localhost/YOUR_APP.xml
).Конфигурация
YOUR_APP.xml
для конкретного приложения доступна только для конкретного приложения.См. Руководство, опубликованное MuleSoft. И см. Официальную документацию, Справочник по конфигурации Tomcat , страницу Контейнера контекста.
Процитирую эту документацию:
источник
Подход 4
Вместо использования JNDI я работаю с
.properties
файлами и создаю сложный объект во время инициализации программы, а не во время настройки.Вы уже используете Spring, и его легко построить
DataSource
:<context:property-placeholder location="classpath:app.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@${db.host}:${db.port}:${db.user}"/> <property name="username" value="${db.user}"/> <property name="password" value="${db.pass}"/> </bean>
Я полностью согласен с Ральфом в использовании дескриптора развертывания,
$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
но вместо JNDI мне нравится простой файл ключ-значение!С Spring легко вводить указанные выше свойства в поля bean-компонентов:
@Value("${db.user}") String defaultSchema;
вместо JNDI:
@Inject ApplicationContext context; Enviroment env = context.getEnvironment(); String defaultSchema = env.getProperty("db.user");
Также обратите внимание, что EL позволяет это (значения по умолчанию и глубокая рекурсивная подстановка):
@Value('${db.user:testdb}') private String dbUserName; <property name='username' value='${db.user.${env}}'/>
Для экстернализации
.properties
файла я использую современный Tomcat 7 с org.apache.catalina.loader.VirtualWebappLoader :<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="/srv/web/app/"/>
Таким образом, ваши DevOps заполняются
virtualClasspath
локальными внешними полными путями, которые являются отдельными для каждого приложения и помещаются локальноapp.properties
в этот каталог.Смотрите также:
источник
Вы также можете использовать поддержку URL-адресов JNDI для различных конфигураций приложений для тестирования, тестирования интеграции и производства.
<Context> ... <Resource auth="Container" factory="com.benasmussen.jndi.url.URLFactory" name="url/MyUrl" type="java.net.URL" url="file:///your/path/to/file"/> ... </Context> <jee:jndi-lookup id="myUrl" jndi-name="java:comp/env/url/MyUrl" expected-type="java.net.URL" />
Ознакомьтесь с проектом GitHub Tomcat JNDI URL Support, чтобы включить поддержку URL JNDI для серверов Tomcat.
источник
шаг 1: context.xml
<Context path="/projectname"> <Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" logAbandoned="true" maxActive="100" `` maxIdle="30" maxWait="10000" name="refname" removeAbandoned="true" removeAbandonedTimeout="60" type="javax.sql.DataSource" url="jdbc:mysql://localhost:8080/dbname" username="root" password="root"/> </Context>
Шаг 2: web.xml
Шаг 3: создайте класс для подключения
Connection connection = null; Context context = (Context) new InitialContext().lookup("java:comp/env"); DataSource ds = (DataSource) context.lookup("refname"); connection = ds.getConnection();
Все установлено
источник