【问题标题】:How to configure jndi DataSource in Tomcat 7如何在 Tomcat 7 中配置 jndi 数据源
【发布时间】:2015-02-06 14:35:07
【问题描述】:

我需要在 tomcat 7 中部署我们的 Web 应用程序。但是我的应用程序使用 JNDI 数据源。如何在 Tomcat 7 中创建 jndi 数据源

【问题讨论】:

    标签: tomcat7 jndi


    【解决方案1】:

    你试过Tomcat手册吗:http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html

    (提示:Google 字符串为“jndi 数据源 tomcat 7”)

    【讨论】:

    • 是的尝试但是将文件显示资源引用添加到 WEB-INF/web.xml 文件中。我需要这个而不修改 web.xml,因为我无权修改 web.xml
    • @Sunilshakya 为什么不呢?事实上,Tomcat 不需要资源引用,只需要 Context.xml 中的条目,但是在没有执行任务所需的权限的情况下被赋予此任务是不合理的。
    【解决方案2】:

    我可以在 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 驱动程序

    JDBC drivers 在 Servlet 容器中存在问题。长话短说,您应该将 JDBC 驱动程序与您的 Web 应用程序捆绑在其 WAR 文件中。

    相反,您希望在 Common 类加载器或可能在 Shared 类加载器上加载 JDBC 驱动程序。为了让 Common 类加载器自动检测您的 JDBC 驱动程序,请将其 JAR 文件放到 Tomcat 的 lib 文件夹中(或者如果使用如上所示的指定“基础”文件夹,请创建一个 @987654356 @ 文件夹,如上所示,并将驱动程序的 JAR 存放在那里)。

    【讨论】:

    • 亲爱的投票者,请在投票的同时留下批评意见。
    • Resource 定义应该放在 WAR 文件的 META-INF/Context.xml 条目中。 Tomcat 将从那里部署它。巨大的图片并不真正相关,只是浪费带宽。
    • @user207421 当您希望开发服务器上的设置与测试服务器上的设置不同,而生产服务器上的设置又不同时?将您的设置嵌入到您的 WAR 文件中会适得其反,并且必须依赖自动或手动编辑 WAR 文件是非常危险的。对于我们中的一些人来说,最好将这些设置保存在 WAR 文件之外,而不是在其中。但每一个他自己。你提到的和我讨论的,是设置这些设置的多种方法中的两种。如果您真的想在您的应用程序中硬编码这些设置,请完全跳过 JNDI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2016-01-02
    • 2012-05-30
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    相关资源
    最近更新 更多