3

我有一个需要两个设置的网络应用程序:

  • 一个 JDBC 数据源
  • 字符串标记

我非常希望能够将一个 .war 部署到各种不同的容器(jetty、tomcat、gf3 最低)并在容器内的应用程序级别配置这些设置。

我的代码是这样做的:

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>
...

  • sun-web.xml 进入的战争,对吧?
  • 肯定有办法通过管理界面做到这一点

我什至在尝试做正确的事吗?其他容器是否使这更容易?我对 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 的期望更高一些,因为它应该有一个完整的 Web 管理界面,但我会很高兴有与上述相同的东西。

4

3 回答 3

2

从 Tomcat 迁移到 Glassfish 3 时,我们遇到了这个问题。这对我们有用。

  • 在 Glassfish 管理控制台中,为 DEV/TEST/PROD/等配置数据源(JDBC 连接池和资源)。
  • 在属性文件中记录您的部署时间参数(在我们的例子中是数据库连接信息)。例如:
# Database connection properties
dev=jdbc/dbdev
test=jdbc/dbtest
prod=jdbc/dbprod
  • 每个 Web 应用程序都可以加载相同的数据库属性文件。
  • 如下查找 JDBC 资源。

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。

于 2010-09-09T19:45:33.837 回答
2

对于 GF v3,您可能想尝试利用 asadmin 的 deploy 子命令的 --deploymentplan 选项。deploy 子命令的手册页对此进行了讨论。

于 2010-03-16T21:55:59.900 回答
0

我不确定是否真正理解问题/问题。

作为应用程序组件提供者,您以标准方式(与容器无关)在web.xml.

在部署时,应用程序部署者和管理员应该遵循应用程序组件提供者提供的说明来解决外部依赖关系(以及其他事情),例如通过在应用程序服务器级别创建数据源并将其真实 JNDI 名称映射到资源应用程序通过使用应用程序服务器特定的部署描述符(例如,sun-web.xml用于 GlassFish)而使用的名称。显然,这是一个特定于容器的步骤,因此 Java EE 规范没有涵盖。

现在,如果您想更改应用程序正在使用的数据库,您必须:

  • 更改应用程序服务器部署描述符中的映射 - 或 -
  • 修改现有数据源的配置,使其指向另一个数据库。

拥有一个管理界面并没有真正改变任何东西。如果我错过了什么,请随时告诉我。以防万一,也许看看这个先前的答案

于 2010-03-04T20:50:47.063 回答