【发布时间】:2015-02-06 14:35:07
【问题描述】:
我需要在 tomcat 7 中部署我们的 Web 应用程序。但是我的应用程序使用 JNDI 数据源。如何在 Tomcat 7 中创建 jndi 数据源
【问题讨论】:
我需要在 tomcat 7 中部署我们的 Web 应用程序。但是我的应用程序使用 JNDI 数据源。如何在 Tomcat 7 中创建 jndi 数据源
【问题讨论】:
你试过Tomcat手册吗:http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html
(提示:Google 字符串为“jndi 数据源 tomcat 7”)
【讨论】:
我可以在 Tomcat 9 中展示我是如何做到的。这在 Tomcat 7 中可能有效,也可能无效。仅供参考,maintenance-mode 中的 Tomcat 7 seems to be。
在我的情况下,我想将数据库访问信息等设置存储在我的网络应用程序的WAR 文件外部。这为我的每个开发、测试和生产服务器提供了灵活性,让我可以将自己的设置驻留在其文件系统中。我的客户运行我的应用程序也是如此。无需编辑 WAR 文件,或生成个性化的 WAR 文件,如果这些设置保存在外部,单独存在于每个服务器上。并且当设置更改或新版本的 WAR 文件到来时,无需重新编辑 WAR 文件。
在 Tomcat “home” 文件夹或 Tomcat “base” 文件夹(如果您已指定)中,进入 conf 文件夹以创建 Catalina 文件夹。 “Catalina”是 Tomcat 引擎的名称。嵌套在一个名为localhost 的新文件夹中,这是您的主机名。在其中创建一个 XML 文件,命名为您的上下文的名称。
我发现app-name-goes-here.xml 方法是将这些设置存储在我的网络应用程序的WAR 文件外部的简单位置,而不必与 Tomcat 自己的文件混淆。这种方法在 Tomcat 配置参考的The Context Container 页面的 Defining a context 部分中以“在单个文件中”开头的中间项目符号中进行了相当模糊的记录。
例如,这是我名为 TickTock 的应用程序的屏幕截图,它使用了 Tomcat 文件夹之外的“基本”文件夹。
在该 XML 文件中,您可以定义诸如“DEV”与“PROD”标志或feature toggle 等环境变量之类的内容,以及要实例化的 JDBC DataSource 单例等资源。这些项目由 Tomcat 自己实现的类似LDAP 的服务器管理,该服务器可以通过JNDI 访问。
这是我的ticktock.xml 文件的一个近乎真实的示例。
注意每个属性的前几个属性;这些是标准的,由 Servlet 规范定义并记录在此处用于environment entries,此处用于resource entries。
注意Resource 元素是如何具有附加属性的。这些是特定的特定资源。在这种情况下,特定资源是this Postgres JDBC driver。
<Context>
<!-- Domain: DEV, TEST, PROD -->
<Environment
name = "work.basil.ticktock.deployment-mode"
description = "Signals whether to run this web-app with development, testing, or production settings."
type = "java.lang.String"
value = "DEV"
override = "false"
/>
<Resource
name = "jdbc/ticktockdb"
description = "Database used by the TickTock app."
type = "javax.sql.DataSource"
auth = "Container"
singleton = "true"
driverClassName = "org.postgresql.Driver"
url = "jdbc:postgresql://127.0.0.1:5432/ticktockdb"
username = "TickTockApp"
password = "pw"
maxTotal = "20"
maxIdle = "10"
maxWaitMillis = "-1"
/>
</Context>
如何获取此环境条目或此资源条目的对象?
首先,获取一个 JNDI“上下文”,从中可以访问这些条目。
Context ctx = new InitialContext ();
对于任何NamingException,您还需要陷阱,但我将省略该代码。
您可以使用这个简单的代码转储所有环境条目。我在这里使用 lambda 语法,但您也可以使用经典的 Java 语法。
// Read all properties.
System.out.println ( "INFO - Dumping bindings for environment variables." );
ctx.listBindings ( "java:comp/env" ).asIterator ().forEachRemaining (
( Binding binding ) -> {
String msg = binding.getName () + " : " + binding.getObject ();
System.out.println ( msg );
this.add ( new Paragraph ( msg ) );
} );
或者获取一个特定的。
String deployMode = ( String ) ctx.lookup( "java:comp/env/work.basil.ticktock.deployment-mode" );
要获得DataSource 对象,我们必须转换JNDI 返回的Object。
DataSource ds = ( DataSource ) ctx.lookup( "java:/comp/env/jdbc/ticktockdb" );
这就是我们所需要的!
您将看到其他关于提供另一层间接层的 Servlet 或 Tomcat 功能的附加配置的其他讨论,因此您的代码中的命名不需要与 LDAP 或 JNDI 访问的其他服务器中的名称相匹配。虽然我不确定,但我相信如果我们的 web 应用程序项目不需要额外的间接层,如果我们指定整个 JNDI 查找字符串,我们的环境或资源请求将直接从命名服务器提供,如此处所示,从java:/comp/env 开始,而不仅仅是结尾部分jdbc/ticktockdb。如果有人想澄清这一点,请发表评论或编辑此答案。
JDBC drivers 在 Servlet 容器中存在问题。长话短说,您应该不将 JDBC 驱动程序与您的 Web 应用程序捆绑在其 WAR 文件中。
相反,您希望在 Common 类加载器或可能在 Shared 类加载器上加载 JDBC 驱动程序。为了让 Common 类加载器自动检测您的 JDBC 驱动程序,请将其 JAR 文件放到 Tomcat 的 lib 文件夹中(或者如果使用如上所示的指定“基础”文件夹,请创建一个 @987654356 @ 文件夹,如上所示,并将驱动程序的 JAR 存放在那里)。
【讨论】:
Resource 定义应该放在 WAR 文件的 META-INF/Context.xml 条目中。 Tomcat 将从那里部署它。巨大的图片并不真正相关,只是浪费带宽。