应该在server.xml还是context.xml中设置数据库连接属性
我正在尝试使用JNDI为Spring Web应用程序设置数据库连接属性。
我正在考虑两种方法如下:
方法1:
在你的Springconfiguration中你可能有这样的东西:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/facs"/>
然后在你的webapp /META-INF/context.xml文件中,你也应该有类似的东西:
<?xml version='1.0' encoding='utf-8'?> <!-- antiResourceLocking="true" --> <Context path="/podd-apn" reloadable="true" cachingAllowed="false" antiResourceLocking="true" > <Resource name="jdbc/facs" type="javax.sql.DataSource" username="${database.username}" password="${database.password}" driverClassName="org.postgresql.Driver" url="${database.url}" maxActive="8" maxIdle="4" global="jdbc/facs" /> </Context>
在你的web.xml中你应该像这样:
<!-- JNDI --> <resource-ref> <description>FACs Datasource</description> <res-ref-name>jdbc/facs</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
方法2:
像这样在Spring环境中设置:
<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/DatabaseName" expected-type="javax.sql.DataSource" />
你可以使用类似下面的方法在Tomcat的server.xml中声明JNDI资源:
<GlobalNamingResources> <Resource name="jdbc/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/>
并从Tomcat的web context.xml中引用JNDI资源,如下所示:
<ResourceLink name="jdbc/DatabaseName" global="jdbc/DatabaseName" type="javax.sql.DataSource"/>
我的问题是哪里是保持数据库属性的最佳位置? 它们应该放在server.xml还是context.xml中 ?
另外,如果我有2个数据库,我应该使用两个configuration?
另外,最好的做法是直接将它们放在server.xml或context.xml中? 还是需要通过Tomcat Manager GUI控制台进行configuration?
谢谢!
我更喜欢方法2(把所有东西(不仅在configuration中的一些属性),
但是不要将它们放在全局的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
的configuration仅适用于特定的应用程序。
我更喜欢第三种方法,从user1016403描述的 方法1和方法2 中取得最佳效果 。
方法3
- 将数据库属性保存在
server.xml
- 从Web应用程序
META-INF/context.xml
引用server.xml
数据库属性
方法3的好处
虽然第一点对于安全原因很有用,但第二点对于从Web应用程序引用服务器属性值是有用的,即使服务器属性值将会改变。
此外,将服务器上的资源定义与Web应用程序使用的资源定义分离开来,使得这样的configuration可以在具有各种复杂性的组织之间进行扩展,其中不同的团队在不同的层/层上工作:如果pipe理员共享相同的服务器pipe理员团队,每个资源的开发人员的JNDI名称。
方法3实施
定义JNDI名称jdbc/ApplicationContext_DatabaseName
。
在Tomcat的server.xml
声明jdbc/ApplicationContext_DatabaseName
的各种属性和值,如下所示:
<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/>
将web应用程序META-INF/context.xml
的jdbc/ApplicationContext_DatabaseName
属性与name
属性中指定的应用程序专用JNDI上下文java:comp/env/
。
<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资源,在Web应用程序的部署描述符中指定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
将不得不被编辑,并且需要部署; 不过这种情况很less见。
方法3变化
一个Web应用程序使用的许多数据源
只需将configuration添加到Tomcat的server.xml
:
<GlobalNamingResources> <Resource name="jdbc/ApplicationContext_DatabaseName1" ... /> <Resource name="jdbc/ApplicationContext_DatabaseName2" ... /> ... </GlobalNamingResources/>
通过应用程序专用JNDI上下文添加链接web应用程序META-INF/context.xml
在name
属性中指定java:comp/env/
<Context path="/ApplicationContext" ... > <ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... /> <ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... /> ... </Context>
最后,在Web应用程序的部署描述符中添加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" ... /> ...
许多Web应用程序在同一台服务器上使用的许多数据源
只需将configuration添加到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/>
其他configuration应该从以前的变化情况中推导出来。
许多数据源来自同一个服务器上的许多Web应用程序使用的数据库
在这种情况下,Tomcat的server.xml
configuration如下所示:
<GlobalNamingResources> <Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
最终出现在两个不同的Web应用程序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>
方法4
我不使用JNDI,而使用.properties
文件,并在程序初始化期间而不是在configuration时间上构build复杂的对象 。
您已经使用Spring,并且通过以下方式构buildDataSource
很容易:
<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>
我完全同意Ralph在$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允许这个(默认值和深度recursionreplace):
@Value('${db.user:testdb}') private String dbUserName; <property name='username' value='${db.user.${env}}'/>
要将.properties
文件外部化,我使用具有org.apache.catalina.loader.VirtualWebappLoader的现代化Tomcat 7:
<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="/srv/web/app/"/>
所以你的devops用本地的外部完整path填充app.properties
,这个path是每个应用程序分开的,并且把本地的app.properties
放到那个目录下。
也可以看看:
- 添加一个目录到tomcat classpath
- 我可以在Tomcat的每个应用程序基础上创build自定义类path吗?
- 从.war文件中外部化Tomcat webappconfiguration
- 如何在Tomcat的webapp上下文之外读取一个属性文件
- configurationTomcat以使用属性文件加载数据库连接信息
- 外部化Tomcatconfiguration
您还可以使用JNDI URL支持不同的应用程序configuration,以进行testing,集成testing,生产。
<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支持为Tomcat服务器启用JNDI URL支持。