我在context.xml中有一个DataSource配置。是否有可能不对该文件中的数据库参数进行硬编码?例如,使用外部属性文件,并从中加载参数?
像这样的东西:
context.xml中:
<Resource
name="jdbc/myDS" auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="${db.url}"
username="${db.user}"
password="${db.pwd}"
maxActive="2"
maxIdle="2"
maxWait="-1"/>
db.properties:
db.url=jdbc:oracle:thin:@server:1521:sid
db.user=test
db.pwd=test
答案 0 :(得分:9)
如上所述here,您可以通过以下方式执行此操作。
1.下载tomcat库以获取接口定义,例如通过定义maven依赖:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-coyote</artifactId>
<version>7.0.47</version>
</dependency>
2.接下来的步骤是按以下方式创建com.mycompany.MyPropertyDecoder:
import org.apache.tomcat.util.IntrospectionUtils;
public class MyPropertyDecoder implements IntrospectionUtils.PropertySource {
@Override
public String getProperty(String arg0) {
//TODO read properties here
return null;
}
}
3.将MyPropertyDecoder.class输入 tomcat7 / lib 文件夹
4.定义org.apache.tomcat.util.digester。 tomcat7 / conf / catalina.properties 中的PROPERTY_SOURCE属性如下:
org.apache.tomcat.util.digester.PROPERTY_SOURCE=com.mycompany.MyPropertyDecoder
5.使用properties vars
更新您的context.xml<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="${db.password}"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mysql?autoReconnect=true"
...
6.将 application.properties 文件放在项目/容器中的某个位置
7.确保 MyPropertyDecoder 正确读取 application.properties
8.Enjoy!
PS还有针对tc Server描述的类似方法。
答案 1 :(得分:4)
使用context deploy descriptors很容易,它看起来像:
<Context docBase="${basedir}/src/main/webapp"
reloadable="true">
<!-- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html -->
<Resources className="org.apache.naming.resources.VirtualDirContext"
extraResourcePaths="/WEB-INF/classes=${basedir}/target/classes,/WEB-INF/lib=${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="${basedir}/target/classes;${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
<JarScanner scanAllDirectories="true"/>
<Parameter name="min" value="dev"/>
<Environment name="app.devel.ldap" value="USER" type="java.lang.String" override="true"/>
<Environment name="app.devel.permitAll" value="true" type="java.lang.String" override="true"/>
</Context>
有几个地方可以放置此配置,因为我认为最佳选择是$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
在上面的XML Context
中可以包含自定义Loader
org.apache.catalina.loader.VirtualWebappLoader(在现代Tomcat 7中可用,您可以为您的{{添加每个应用程序独立的类路径 1}}}个文件),.properties
(通过Parameter
访问)和FilterConfig.getServletContext().getInitParameter(name)
(通过Environment
访问)
见讨论:
更新 Tomcat 8 change syntax for new InitialContext().lookup("java:comp/env").lookup("name")
和<Resources>
元素,相应部分现在如下所示:
<Loader>
答案 2 :(得分:2)
当然,这是可能的。您必须向web.xml
注册ServletContextListener,如下所示:
<!-- at the beginning of web.xml -->
<listener>
<listener-class>com.mycompany.servlets.ApplicationListener</listener-class>
</listener>
com.mycompany.servlets.ApplicationListener
的来源:
package com.mycompany.servlets;
public class ApplicationListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// this method is invoked once when web-application is deployed (started)
// reading properties file
FileInputStream fis = null;
Properties properties = new Properties();
try {
fis = new FileInputStream("path/to/db.properties")
properties.load(fis);
} catch(IOException ex) {
throw new RuntimeException(ex);
} finally {
try {
if(fis != null) {
fis.close();
}
} catch(IOException e) {
throw new RuntimeException(e);
}
}
// creating data source instance
SomeDataSourceImpl dataSource = new SomeDataSourceImpl();
dataSource.setJdbcUrl(properties.getProperty("db.url"));
dataSource.setUser(properties.getProperty("db.user"));
dataSource.setPassword(properties.getProperty("db.pwd"));
// storing reference to dataSource in ServletContext attributes map
// there is only one instance of ServletContext per web-application, which can be accessed from almost anywhere in web application(servlets, filters, listeners etc)
final ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute("some-data-source-alias", dataSource);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
// this method is invoked once when web-application is undeployed (stopped) - here one can (should) implement resource cleanup etc
}
}
然后,在Web应用程序代码中的某个位置访问dataSource
:
ServletContext servletContext = ...; // as mentioned above, it should be accessible from almost anywhere
DataSource dataSource = (DataSource) servletContext.getAttribute("some-data-source-alias");
// use dataSource
SomeDataSourceImpl
是javax.sql.DataSource的一些具体实现。如果您没有使用特定的DataSource
(如ComboPooledDataSource用于连接池)并且不知道如何获取它,请告知我 - 我将发布如何绕过它。
some-data-source-alias
- String
属性映射中DataSource
个实例的ServletContext
别名(密钥)。好的做法是使用类似com.mycompany.mywebapp.dataSource
的包名前面添加别名。
希望这会有所帮助......
答案 3 :(得分:0)
如果这是Tomcat 7,您可以在org.apache.tomcat.util.IntrospectionUtils.PropertySource
中编写自己的context.xml
实现读取变量,如“$ {...}”。您需要将系统属性org.apache.tomcat.util.digester.PROPERTY_SOURCE
设置为指向PropertySource
实施。