我有一个需要两个设置的网络应用程序:
我非常希望能够将一个.war部署到各种不同的容器(jetty,tomcat,gf3 minimum),并在容器内的应用程序级别配置这些设置。
我的代码执行此操作:
InitialContext ctx = new InitialContext();
Context envCtx = (javax.naming.Context) ctx.lookup("java:comp/env");
token = (String)envCtx.lookup("token");
ds = (DataSource)envCtx.lookup("jdbc/datasource")
我们假设我使用了glassfish管理界面来创建两个jdbc资源:jdbc / test-datasource和jdbc / live-datasource,它们连接到同一模式的不同副本,不同的服务器,不同的凭据等。说我想要将它部署到glassfish并将其指向测试数据源,我可能在sun-web.xml中有这个:
...
<resource-ref>
<res-ref-name>jdbc/datasource</res-ref-name>
<jndi-name>jdbc/test-datasource</jndi-name>
</resource-ref>
...
但
我甚至试图做正确的事吗?其他容器能让这更容易吗?我特别感兴趣的是jetty 7如何处理这个问题,因为我将它用于开发。
编辑 Tomcat有一个合理的方法:
使用以下内容创建$TOMCAT_HOME/conf/Catalina/localhost/webapp.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context antiResourceLocking="false" privileged="true">
<!-- String resource -->
<Environment name="token" value="value of token" type="java.lang.String" override="false" />
<!-- Linking to a global resource -->
<ResourceLink name="jdbc/datasource1" global="jdbc/test" type="javax.sql.DataSource" />
<!-- Derby -->
<Resource name="jdbc/datasource2"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.apache.derby.jdbc.EmbeddedDataSource"
url="jdbc:derby:test;create=true"
/>
<!-- H2 -->
<Resource name="jdbc/datasource3"
type="javax.sql.DataSource"
auth="Container"
driverClassName="org.h2.jdbcx.JdbcDataSource"
url="jdbc:h2:~/test"
username="sa"
password=""
/>
</Context>
请注意,override="false"
意味着相反。这意味着web.xml
无法覆盖此设置 。
我喜欢这种方法,因为该文件是容器配置的一部分,而不是战争,但它不是全局配置的一部分;它是特定于webapp的。
我想我会期待更多来自glassfish,因为它应该有一个完整的网络管理界面,但我会很高兴与上述相同的东西。
答案 0 :(得分:2)
对于GF v3,您可能希望尝试利用asadmin的deploy子命令的--deploymentplan选项。它在man page for the deploy subcommand上讨论。
答案 1 :(得分:2)
从Tomcat迁移到Glassfish 3时,我们遇到了这个问题。这对我们有用。
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod
import java.sql.Connection;
import javax.sql.DataSource;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* @param resourceName the resource name of the connection pool (eg jdbc/dbdev)
* @return Connection a pooled connection from the data source
* associated with resourceName
* @throws NamingException will be thrown if resource name is not found
*/
public Connection getDatabaseConnection(String resourceName)
throws NamingException, SQLException {
Context initContext = new InitialContext();
DataSource pooledDataSource = (DataSource) initContext.lookup(resourceName);
return pooledDataSource.getConnection();
}
请注意,这是不通常的两步过程,包括使用命名上下文“java:comp / env”进行查找。我不知道这是否适用于除GF3之外的应用程序容器,但在GF3中,使用上述方法时无需向web.xml添加资源描述符。
答案 2 :(得分:0)
我不确定真正理解这个问题/问题。
作为Application Component Provider,您可以在web.xml
中以标准方式(容器不可知)声明应用程序所需的资源。
在部署时,Application Deployer and Administrator应遵循应用程序组件提供程序提供的指令来解析外部依赖性(以及其他内容),例如通过在应用程序中创建数据源服务器级别,并通过使用特定于应用程序服务器的部署描述符(例如,GlassFish的sun-web.xml
)将其真实JNDI名称映射到应用程序使用的资源名称。显然,这是一个容器特定的步骤,因此不受Java EE规范的约束。
现在,如果要更改应用程序正在使用的数据库,则必须:
拥有管理界面并没有真正改变任何东西。如果我错过了什么,请不要犹豫,让我知道。为了以防万一,也许看看this previous answer。