【问题标题】:Correct way to make datasources/resources a deploy-time setting使数据源/资源成为部署时设置的正确方法
【发布时间】:2011-01-21 14:04:45
【问题描述】:

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

  • 一个 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覆盖

我喜欢这种方法,因为该文件是 container 配置而不是战争的一部分,但它不是全局配置的一部分;它是特定于 webapp 的。

我想我对 glassfish 的期望更高一些,因为它应该有一个完整的网络管理界面,但我会很高兴有与上述相同的东西。

【问题讨论】:

  • 您是否需要能够同时访问两个数据源...从同一台服务器?
  • 实际上也许不是,但我想保持它们都配置。实际上,我们有可能同时需要实时服务器上的两个数据源。
  • 我也遇到了同样的问题,还没有找到好的解决方案。我目前使用不同的 GF 域来部署我的应用程序,但它不是最佳解决方案,因为每个域都是操作系统进程,至少需要 300 MB 并且很难管理多个域。

标签: deployment glassfish jndi war


【解决方案1】:

对于 GF v3,您可能想尝试利用 asadmin 的 deploy 子命令的 --deploymentplan 选项。在man page for the deploy subcommand 上讨论。

【讨论】:

  • 并不完美,因为它是部署时的事情,但看起来相当不错,因为它保持了分离(允许部署纯 EAR)。
【解决方案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。

【讨论】:

    【解决方案3】:

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

    作为Application Component Provider,您以标准方式(与容器无关)在web.xml 中声明应用程序所需的资源。

    在部署时,Application Deployer and Administrator 应该遵循 Application Component Provider 提供的说明来解决外部依赖项(除其他外),例如通过在应用程序服务器级别创建数据源并通过使用应用程序服务器特定的部署描述符(例如,GlassFish 的sun-web.xml)将其真实的JNDI 名称映射到应用程序使用的资源名称。显然,这是一个特定于容器的步骤,因此不在 Java EE 规范中。

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

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

    拥有一个管理界面并没有真正改变任何东西。如果我错过了什么,请随时告诉我。以防万一,不妨看看this previous answer

    【讨论】:

    • 我的问题是 sun-web.xml inside 并作为应用程序的一部分部署,但这不应该是因为它是特定于容器的。管理界面的唯一区别是我认为应该有一种方法可以将地图更改为基于每个 Web 应用程序的真实 JNDI 名称。
    • @Dreamon 遗憾的是,事情并非如此,更改绑定也不是很常见的用例。如果你想这样做,你将不得不重新包装你的战争。
    • 我原以为应用程序组件提供商应该提供一个 .war(可能是一个签名的、付费的、没有来源的 .war)并且部署它不应该涉及重新打包它。正如我上面提到的,Tomcat 可以做到这一点。拥有一个管理界面不会改变任何东西,除了我在那里寻找一个配置选项而不是类似于 Tomcat 的 XML 配置的东西。我很惊讶其他人不想对测试和生产数据库使用单一战争。
    • @Draemon 我了解,但在这种情况下您必须更改数据源配置。在这种情况下,也许@vkraemer 建议的部署计划是您的最佳选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    相关资源
    最近更新 更多