应该在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

  1. 将数据库属性保存在server.xml
  2. 从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.xmljdbc/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.xmlMETA-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.xmlname属性中指定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.xmlconfiguration如下所示:

 <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支持。