JNDI Resources HOW-TO(Tomcat 9)

本文介绍如何在Tomcat中配置JNDI资源,包括环境条目、资源引用等,涉及web.xml和context.xml配置,及如何创建自定义资源工厂。

1、介绍

Tomcat为在其下运行的每个Web应用程序提供了一个JNDI InitialContext实现实例,其方式与Java Enterprise Edition应用程序服务器提供的方式兼容。 Java EE标准提供了/WEB-INF/web.xml文件中的一组标准去参考/定义资源。

有关JNDI编程API以及Java Enterprise Edition(Java EE)服务器支持的功能的详细信息,请参见以下规范:

Java命名和目录接口(包含在JDK 1.4之后)Java EE平台规范(特别是有关命名的第5章)

2、web.xml配置

在Web应用程序的开发中,程序部署描述符(/WEB-INF/web.xml)可以使用以下元素来定义资源:

- 环境条目,一个单键值参数,可用于配置应用程序的运行方式。
- 资源引用,通常用于对象工厂,用于资源(如JDBC DataSource,JavaMail会话)或配置到Tomcat中的自定义对象工厂。
- 资源环境引用,在Servlet 2.4中添加的资源引用的新变体,更简单地配置不需要身份验证信息的资源。
提供Tomcat能够识别用于创建资源的适当资源工厂,并且不需要进一步的配置信息,Tomcat将使用/WEB-INF/web.xml中的信息创建资源。

Tomcat为web.xml中无法指定的JNDI资源提供了一些特定的Tomcat选项。这些包括closeMethod,当Web应用程序停止时,可以更快地清理JNDI资源,并单击控制是否为每个JNDI查找创建了一个新的资源实例。要使用这些配置选项,必须在Web应用程序的元素或$ CATALINA_BASE / conf / server.xml的元素中指定资源。

3、context.xml配置

如果Tomcat无法识别特定的资源配置或需要其他配置信息,则在Tomcat可以创建资源之前,就必须指定附加的Tomcat特定配置。 Tomcat特定的资源配置被输入到可以在$ CATALINA_BASE / conf / server.xml中指定的元素中,或最好是每个Web应用自身的XML文件(META-INF / context.xml)中。

使用元素中的以下元素执行Tomcat特定资源配置:

- 为通过JNDI InitialContext(相当于在Web应用程序部署描述符中包含一个元素)暴露给Web应用程序的标量环境条目配置名称和值。
<资源> - 配置应用程序可用的资源的名称和数据类型(相当于在Web应用程序部署描述符中包含一个元素)。
- 添加到全局JNDI上下文中定义的资源的链接。使用资源链接为Web应用程序访问元素的子元素中定义的资源。
- 添加一个资源工厂,用于实例化可在java:comp / UserTransaction的UserTransaction对象实例。
任何数量的这些元素可以嵌套在元素内,并且将仅与特定的Web应用程序相关联。

如果在元素中定义了资源,那么在/WEB-INF/web.xml中不需要定义该资源。但是,建议将条目保存在/WEB-INF/web.xml中以记录Web应用程序的资源需求。

在包含元素的Web应用程序部署描述符(/WEB-INF/web.xml)中定义相同的资源名称以及作为元素的一部分的元素中Web应用程序,部署描述符中的值只有在相应的元素允许(通过将override属性设置为“true”)的情况下才会优先。

4、Global配置

Tomcat为整个服务器维护一个单独的全局资源命名空间。 他们是包含配置元素的$ CATALINA_BASE / conf / server.xml文件。 您可以通过使用将这些资源公开到Web应用程序,以将其包含在每个Web应用程序的context中。

如果已使用定义资源,则不需要在/WEB-INF/web.xml中定义该资源。 但是,建议将条目保存在/WEB-INF/web.xml中以记录Web应用程序的资源需求。

5、使用资源

InitialContext是Web应用程序的最初部署,并可用于Web应用程序组件(用于只读访问)。 所有配置的条目和资源都配置在JNDI命名空间的java:comp / env中,因此对资源配置(在本例中为JDBC DataSource)的典型访问,如下所示:

// Obtain our environment naming context
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");

// Look up our data source
DataSource ds = (DataSource)
  envCtx.lookup("jdbc/EmployeeDB");

// Allocate and use a connection from the pool
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();

6、Tomcat标准资源配置

Tomcat包括一系列标准资源配置,可以为您的Web应用程序提供服务,同时又可以通过元素为您提供配置灵活性,而无需修改Web应用程序或部署描述符。 下面的每个小节都详细说明了标准资源工厂的配置和用法。

有关如何使用Tomcat创建,安装,配置和使用自己的自定义资源工厂类的信息,请参阅添加自定义资源工厂。

注 - 在标准资源工厂中,只有“JDBC数据源”和“User Transaction”被要求在其他平台上可用,同时还仅当平台实现Java企业版(Java EE)规范时才可以。 所有其他标准资源配置,以及您自己编写的自定义资源工厂,都是特定于Tomcat的,不能假定在其他容器上可用。

6.1、通用JavaBean资源

6.1.0、介绍

该资源配置可用于创建符合JavaBeans标准命名约定的任何Java类对象(即它具有无参构造函数,并具有符合setFoo()命名格式的属性设置器。资源配置将创建新对象,如果工厂的单例属性设置为false。则每次执行lookup(),则创建JavaBeans的适当类的新实例。

使用该设施所需的步骤如下所述。

6.1.1、创建JavaBean类创建JavaBean类。

该类将在资源配合执行lookup时被实例化。 对于这个例子,假设你创建一个类com.mycompany.MyBean,它看起来像这样:

package com.mycompany;

public class MyBean {
  private String foo = "Default Foo";

  public String getFoo() {
    return (this.foo);
  }

  public void setFoo(String foo) {
    this.foo = foo;
  }

  private int bar = 0;

  public int getBar() {
    return (this.bar);
  }

  public void setBar(int bar) {
    this.bar = bar;
  }
}

6.1.2、声明资源需求

接下来,修改您的Web应用程序部署描述符(/WEB-INF/web.xml)以声明将要请求此bean的新实例的JNDI名称。 最简单的方法是使用元素,如下所示:

<resource-env-ref>
  <description>
    Object factory for MyBean instances.
  </description>
  <resource-env-ref-name>
    bean/MyBeanFactory
  </resource-env-ref-name>
  <resource-env-ref-type>
    com.mycompany.MyBean
  </resource-env-ref-type>
</resource-env-ref>

警告 - 确保遵从DTD对Web应用程序部署描述符所要求的元素规范! 有关详细信息,请参阅Servlet规范。

6.1.3、编写应用程序对此资源的使用

此资源环境引用的典型用法可能如下所示:

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory");

writer.println("foo = " + bean.getFoo() + ", bar = " +
               bean.getBar());

6.1.4、配置Tomcat的资源配置。

要配置Tomcat的资源工厂,可参考下述例子,请将此类元素添加到此Web应用程序的元素中。

<Context ...>
  ...
  <Resource name="bean/MyBeanFactory" auth="Container"
            type="com.mycompany.MyBean"
            factory="org.apache.naming.factory.BeanFactory"
            bar="23"/>
  ...
</Context>

请注意,资源名称(这里,bean / MyBeanFactory必须与Web应用程序部署描述符中指定的值相匹配)。我们还初始化bar属性的值,这将导致在返回新bean之前调用setBar(23) 因为我们没有初始化foo属性(尽管我们可以拥有),bean将包含其构造函数设置的任何默认值。

某些bean具有不能自动从字符串值转换的类型的属性。 使用Tomcat BeanFactory设置这些属性将失败,并显示NamingException。 为了这些bean能够从字符串值设置属性,Tomcat BeanFactory可以使用这样的方法: 使用forceString属性完成配置。假设我们的bean看起来像这样:

package com.mycompany;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class MyBean2 {

  private InetAddress local = null;

  public InetAddress getLocal() {
    return local;
  }

  public void setLocal(InetAddress ip) {
    local = ip;
  }

  public void setLocal(String localHost) {
    try {
      local = InetAddress.getByName(localHost);
    } catch (UnknownHostException ex) {
    }
  }

  private InetAddress remote = null;

  public InetAddress getRemote() {
    return remote;
  }

  public void setRemote(InetAddress ip) {
    remote = ip;
  }

  public void host(String remoteHost) {
    try {
      remote = InetAddress.getByName(remoteHost);
    } catch (UnknownHostException ex) {
    }
  }

}

该bean具有两个属性,均为InetAddress类型。 第一个属性local有一个附加的setter需要一个字符串参数。 默认情况下,Tomcat BeanFactory将尝试使用与属性类型相同的参数类型的自动检测的设置器,然后抛出NamingException,因为它不能将给定的字符串属性值转换为InetAddress。 我们可以通过如下方式告诉Tomcat BeanFactory使用其他setter:

<Context ...>
  ...
  <Resource name="bean/MyBeanFactory" auth="Container"
            type="com.mycompany.MyBean2"
            factory="org.apache.naming.factory.BeanFactory"
            forceString="local"
            local="localhost"/>
  ...
</Context>

bean属性remote也可以从一个字符串设置,但是一个必须使用非JavaBean标准的方法名称host。 要设置本地和远程使用以下配置:

<Context ...>
  ...
  <Resource name="bean/MyBeanFactory" auth="Container"
            type="com.mycompany.MyBean2"
            factory="org.apache.naming.factory.BeanFactory"
            forceString="local,remote=host"
            local="localhost"
            remote="tomcat.apache.org"/>
  ...
</Context>

多个属性描述可以通过使用逗号作为分隔符连接在forceString中。 每个属性描述只包括属性名称,这个属性名称是BeanFactory调用setter的方法。 或者它由name = method组成,在这种情况下,名为name的属性通过调用method方法设置。 对于类型为String或原始基本类型的属性,或者使用相关原始数据类型包装类的属性,在使用forceString是不必需的。 将自动检测正确的设置器并应用参数转换。

6.2、用户数据库资源

6.2.0、介绍

UserDatabase资源通常被配置为用户数据库领域使用的全局资源。 Tomcat包括一个UserDatabaseFactory,用于创建由XML文件(通常是tomcat-users.xml)支持的UserDatabase资源。

下面介绍设置全局UserDatabase资源所需的步骤。

6.2.1、创建/编辑XML文件

XML文件通常位于
CATALINABASE/conf/tomcatusers.xmlXML CATALINA_BASE/conf中。 典型的XML将如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>

6.2.2、发布你的资源

接下来,修改$ CATALINA_BASE / conf / server.xml以根据您的XML文件创建UserDatabase资源。 它应该看起来像这样:

<Resource name="UserDatabase"
          auth="Container"
          type="org.apache.catalina.UserDatabase"
          description="User database that can be updated and saved"
          factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          pathname="conf/tomcat-users.xml"
          readonly="false" />

pathname属性可以是URL,绝对路径或相对路径。 如果相对,它是相对于$ CATALINA_BASE。

readonly属性是可选的,如果不提供,则默认为true。 如果XML是可写的,那么当Tomcat启动时它将被写入。 警告:当文件写入时,它将继承Tomcat正在运行的用户的默认文件权限。 确保这些适合于维护安装的安全性。

6.3、JavaMail会话

6.3.1、介绍

在许多Web应用程序中,发送电子邮件是系统功能的必需部分。 Java Mail API使此过程相对简单,但需要客户端应用程序必须注意的许多配置详细信息(包括用于消息发送的SMTP主机的名称)。

Tomcat包括一个标准资源配置工厂类,它将为您创建已经配置为连接到SMTP服务器的javax.mail.Session会话实例。这样,应用程序完全可以与电子邮件服务器配置环境中的变化完全隔离 - 只需在需要时,即可查询并接收预配置的会话。

所需步骤如下。

6.3.1、声明您的资源要求

您应该做的第一件事是修改Web应用程序部署描述符(/WEB-INF/web.xml)以声明将在其下查找预先配置的会话的JNDI名称。按照惯例,所有这些名称都应该解析为邮件SubContext(相对于作为所有提供资源工厂的根目录的标准java:comp/env命名上下文),典型的web.xml条目可能如下所示:

<resource-ref>
  <description>
    Resource reference to a factory for javax.mail.Session
    instances that may be used for sending electronic mail
    messages, preconfigured to connect to the appropriate
    SMTP server.
  </description>
  <res-ref-name>
    mail/Session
  </res-ref-name>
  <res-type>
    javax.mail.Session
  </res-type>
  <res-auth>
    Container
  </res-auth>
</resource-ref>

WARNING - Be sure you respect the element ordering that is required by the DTD for web application deployment descriptors! See the Servlet Specification for details.

6.3.2、Code Your Application’s Use Of This Resource

A typical use of this resource reference might look like this:

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
Session session = (Session) envCtx.lookup("mail/Session");

Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(request.getParameter("from")));
InternetAddress to[] = new InternetAddress[1];
to[0] = new InternetAddress(request.getParameter("to"));
message.setRecipients(Message.RecipientType.TO, to);
message.setSubject(request.getParameter("subject"));
message.setContent(request.getParameter("content"), "text/plain");
Transport.send(message);

6.3.3、配置Tomcat的资源工厂

要配置Tomcat的资源工厂,请将此类元素添加到此Web应用程序的元素中。

<Context ...>
  ...
  <Resource name="mail/Session" auth="Container"
            type="javax.mail.Session"
            mail.smtp.host="localhost"/>
  ...
</Context>

请注意,资源名称(这里,mail / Session)必须与Web应用程序部署描述符中指定的值相匹配。自定义mail.smtp.host参数的值,以指向为您的网络提供SMTP服务的服务器。

额外的资源属性和值将被转换为属性和值,并作为java.util.Properties集合的一部分传递给javax.mail.Session.getInstance(java.util.Properties)。除了JavaMail规范附录A中定义的属性外,个别提供商还可以支持其他属性。

如果资源配置了password属性和mail.smtp.user或mail.user属性,那么Tomcat的资源工厂将配置并将javax.mail.Authenticator添加到邮件会话。

6.34、安装JavaMail库

下载JavaMail API。
https://javaee.github.io/javamail/#Download_JavaMail_Release

将分发包解包,并将mail.jar放入
CATALINAHOME/lib便Tomcatjar CATALINA_HOME / lib和Web应用程序的lib文件夹中将导致错误,因此请确保仅在$ CATALINA_HOME / lib位置。

6.3.5、重启Tomcat

对于Tomcat可见的其他JAR,需要重新启动Tomcat实例。

应用示例

Tomcat中包含的/ examples应用程序包含一个利用这个资源工厂的例子。它通过“JSP示例”链接访问。实际发送邮件消息的servlet的源代码位于/WEB-INF/classes/SendMailServlet.java中。

警告 - 默认配置假定在localhost上的端口25上存在SMTP服务器列表。如果不是这种情况,请编辑此Web应用程序的元素,并将mail.smtp.host参数的参数值修改为网络上SMTP服务器的主机名。

6.4、JDBC Data Sources

6.4.0、介绍

许多Web应用程序需要通过JDBC驱动程序访问数据库,以支持该应用程序所需的功能。 Java EE平台规范要求Java EE应用程序服务器为此提供一个DataSource实现(即JDBC连接的连接池)。 Tomcat提供完全相同的支持,因此您使用此服务在Tomcat上开发的基于数据库的应用程序将在任何Java EE服务器上运行不变。

有关JDBC的信息,请参考以下内容:

http://www.oracle.com/technetwork/java/javase/jdbc/index.html - 有关Java数据库连接的信息的主页。
http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame.html - JDBC 2.1 API规范。
http://java.sun.com/products/jdbc/jdbc20.stdext.pdf - JDBC 2.0标准扩展API(包括javax.sql.DataSource API)。此包现在称为“JDBC可选包”。
http://www.oracle.com/technetwork/java/javaee/overview/index.htm - Java EE平台规范(涵盖所有Java EE平台必须向应用程序提供的JDBC功能)。
注 - Tomcat中的默认数据源支持基于Commons项目中的DBCP连接池。但是,如下所述,可以通过编写自己的自定义资源工厂来使用实现javax.sql.DataSource的任何其他连接池。

6.4.1、安装JDBC驱动程序

使用JDBC数据源JNDI资源工厂要求您为Tomcat内部类和Web应用程序提供适当的JDBC驱动程序。通过将驱动程序的JAR文件安装到$ CATALINA_HOME/lib目录中,这样可以使驱动程序对资源工厂和应用程序都可用。

6.4.2、声明您的资源要求

接下来,修改Web应用程序部署描述符(/WEB-INF/web.xml)以声明将在其下查找预配置的数据源的JNDI名称。按照惯例,所有这些名称都应该解析为jdbc子上下文(相对于作为所有提供的资源工厂的根的标准java:comp/env命名Context),典型的web.xml条目可能如下所示:

<resource-ref>
  <description>
    Resource reference to a factory for java.sql.Connection
    instances that may be used for talking to a particular
    database that is configured in the <Context>
    configuration for the web application.
  </description>
  <res-ref-name>
    jdbc/EmployeeDB
  </res-ref-name>
  <res-type>
    javax.sql.DataSource
  </res-type>
  <res-auth>
    Container
  </res-auth>
</resource-ref>

6.4.3、使用此配置的代码

典型用法如下:

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)
  envCtx.lookup("jdbc/EmployeeDB");

Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();

请注意,应用程序使用与Web应用程序部署描述符中声明的相同的资源引用名称。 这与如下所述的Web应用程序的元素中配置的资源工厂进行匹配。

6.4.4、配置Tomcat的资源工厂

要配置Tomcat的资源工厂,请将这样的元素添加到Web应用程序的元素中。

<Context ...>
  ...
  <Resource name="jdbc/EmployeeDB"
            auth="Container"
            type="javax.sql.DataSource"
            username="dbusername"
            password="dbpassword"
            driverClassName="org.hsql.jdbcDriver"
            url="jdbc:HypersonicSQL:database"
            maxTotal="8"
            maxIdle="4"/>
  ...
</Context>

请注意,资源名称(这里,jdbc / EmployeeDB)必须与Web应用程序部署描述符中指定的值相匹配。

此示例假定您正在使用HypersonicSQL数据库JDBC驱动程序。自定义driverClassName和driverName参数以匹配实际数据库的JDBC驱动程序和连接URL。

Tomcat的标准数据源资源工厂
(org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory)的配置属性如下所示:

driverClassName - 要使用的JDBC驱动程序的完全限定的Java类名称。
用户名 - 要传递给我们的JDBC驱动程序的数据库用户名。
密码 - 要传递给我们的JDBC驱动程序的数据库密码。
url - 要传递给我们的JDBC驱动程序的连接URL。 (为了向后兼容,属性driverName也被识别。)
initialSize - 池初始化期间将在池中创建的初始连接数。默认值:0
maxTotal - 可以同时从此池分配的最大连接数。默认值:8
minIdle - 同时在该池中闲置的最小连接数。默认值:0
maxIdle - 可以同时在该池中闲置的最大连接数。默认值:8
maxWaitMillis - 在引发异常之前,池将要等待的最大毫秒数(当没有可用的连接时)。默认值:-1(无限)
一些附加属性处理连接验证:

validationQuery - 池可用于在连接返回到应用程序之前验证连接的SQL查询。如果指定,则该查询必须是返回至少一行的SQL SELECT语句。
validationQueryTimeout - 验证查询返回的超时(以秒为单位)。默认值:-1(无限)
testOnBorrow - true或false:每次从池中借用时,是否应使用验证查询验证连接。默认值:true
testOnReturn - true或false:每次返回到池时,是否应使用验证查询验证连接。默认值:false
可选的evictor线程负责通过删除长时间空闲的任何连接来缩小池。驱逐者不尊重minid。注意,如果只希望池根据配置的maxIdle属性来缩小,则不需要激活evictor线程。

驱逐器默认情况下禁用,可以使用以下属性进行配置:

timeBetweenEvictionRunsMillis - 驱逐器的连续运行之间的毫秒数。默认值:-1(禁用)
numTestsPerEvictionRun - 在驱逐者的每次运行期间由驱逐者检查空闲的连接数。默认值:3
minEvictableIdleTimeMillis - 以毫秒为单位的空闲时间,可以由驱逐器从池中删除连接。默认值:30 * 60 * 1000(30分钟)
testWhileIdle - true或false:在池中闲置时,使用验证查询是否应该由evictor线程验证连接。默认值:false
另一个可选功能是删除废弃的连接。如果应用程序不将其返回到池中很长时间,则称连接被放弃。池可以自动关闭这些连接,并将其从池中删除。这是泄漏连接的应用程序的解决方法。

放弃功能默认情况下禁用,可以使用以下属性进行配置:

removeAbandoned - true或false:是否从池中删除放弃的连接。默认值:false
removeAbandonedTimeout - 假定借用连接被放弃的秒数。默认值:300
logAbandoned - true或false:是否记录放弃语句或连接的应用程序代码的堆栈跟踪。这增加了严重的开销。默认值:false
最后有各种属性可以进一步微调池的行为:

defaultAutoCommit - true或false:此池创建的连接的默认自动提交状态。默认值:true
defaultReadOnly - true或false:由此池创建的连接的默认只读状态。默认值:false
defaultTransactionIsolation - 设置默认事务隔离级别。可以是NONE,READ_COMMITTED,READ_UNCOMMITTED,REPEATABLE_READ,SERIALIZABLE之一。默认值:没有默认设置
poolPreparedStatements - true或false:是否池PreparedStatementsCallableStatements。默认值:false
maxOpenPreparedStatements - 可以同时从语句池分配的最大打开语句数。默认值:-1(无限制)
defaultCatalog - 默认目录的名称。默认值:未设置
connectionInitSqls - 创建连接后运行一次的SQL语句列表。用分号(;)分隔多个语句。默认值:无声明
connectionProperties - 传递给的驱动程序特定属性的列表

6.5、添加自定义资源匹配工厂

如果没有一个标准资源工厂满足您的需求,您可以编写自己的工厂并将其集成到Tomcat中,然后在Web应用程序的元素中配置该工厂的使用。在下面的例子中,我们将创建一个工厂,它只知道如何从上面的Generic JavaBean Resources示例中创建com.mycompany.MyBean bean。

6.5.1、写一个资源工厂类

您必须编写一个实现JNDI服务提供者javax.naming.spi.ObjectFactory接口的类。每当您的Web应用程序在绑定到此工厂的上下文条目上调用lookup()(假设工厂配置为singleton =“false”)时,将调用getObjectInstance()方法,并具有以下参数:

Object obj - 包含可用于创建对象的位置或引用信息的(可能为null)的对象。对于Tomcat,这将始终是一个类型为javax.naming.Reference的对象,它包含此工厂类的类名以及用于创建对象的配置属性(来自Web应用程序的)被归还。
Name name - 此工厂相对于nameCtx绑定的名称,如果未指定名称,则为null。
context nameCtx - 指定name参数的上下文,如果name与默认的初始上下文相关,则为null。
Hashtable环境 - 创建此对象时使用的(可能为null)的环境。这通常在Tomcat对象工厂中被忽略。
要创建一个知道如何生成MyBean实例的资源工厂,可以创建一个类:

package com.mycompany;

import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;

public class MyBeanFactory implements ObjectFactory {

  public Object getObjectInstance(Object obj,
      Name name2, Context nameCtx, Hashtable environment)
      throws NamingException {

      // Acquire an instance of our specified bean class
      MyBean bean = new MyBean();

      // Customize the bean properties from our attributes
      Reference ref = (Reference) obj;
      Enumeration addrs = ref.getAll();
      while (addrs.hasMoreElements()) {
          RefAddr addr = (RefAddr) addrs.nextElement();
          String name = addr.getType();
          String value = (String) addr.getContent();
          if (name.equals("foo")) {
              bean.setFoo(value);
          } else if (name.equals("bar")) {
              try {
                  bean.setBar(Integer.parseInt(value));
              } catch (NumberFormatException e) {
                  throw new NamingException("Invalid 'bar' value " + value);
              }
          }
      }

      // Return the customized instance
      return (bean);

  }

}

在这个例子中,我们无条件地创建了一个com.mycompany.MyBean类的新实例,并根据配置这个工厂的元素中包含的参数来填充它的属性(见下文)。您应该注意,任何名为factory的参数都应该被跳过 - 该参数用于指定工厂类本身的名称(在本例中为com.mycompany.MyBeanFactory),而不是要配置的bean的属性。

有关ObjectFactory的更多信息,请参阅JNDI服务提供程序接口(SPI)规范。

您将需要根据包含
CATALINAHOME/libJARbean CATALINA_HOME / lib下,或者在$ CATALINA_HOME / lib中的JAR文件中。这样,所需的类文件对于Catalina内部资源和Web应用程序都是可见的。

6.5.2、声明您的资源要求

接下来,修改您的Web应用程序部署描述符(/WEB-INF/web.xml)以声明将要请求此bean的新实例的JNDI名称。最简单的方法是使用元素,如下所示:

<resource-env-ref>
  <description>
    Object factory for MyBean instances.
  </description>
  <resource-env-ref-name>
    bean/MyBeanFactory
  </resource-env-ref-name>
  <resource-env-ref-type>
    com.mycompany.MyBean
  </resource-env-ref-type>
</resource-env-ref>

警告 - 确保遵从DTD对Web应用程序部署描述符所要求的元素排序! 有关详细信息,请参阅Servlet规范。

6.5.3、编写您的应用程序对此资源的使用

此资源环境引用的典型用法可能如下所示:

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory");

writer.println("foo = " + bean.getFoo() + ", bar = " +
               bean.getBar());

6.5.4、配置Tomcat的资源工厂

要配置Tomcat的资源工厂,请将此类元素添加到此Web应用程序的元素中。

<Context ...>
  ...
  <Resource name="bean/MyBeanFactory" auth="Container"
            type="com.mycompany.MyBean"
            factory="com.mycompany.MyBeanFactory"
            singleton="false"
            bar="23"/>
  ...
</Context>

请注意,资源名称(这里,bean/MyBeanFactory必须与Web应用程序部署描述符中指定的值相匹配)。我们还初始化bar属性的值,这将导致在返回新bean之前调用setBar(23) 因为我们没有初始化foo属性(尽管我们可以拥有),bean将包含其构造函数设置的任何默认值。

您还将注意到,从应用程序开发人员的角度来看,资源环境引用的声明和用于请求新实例的编程与通用JavaBean资源示例中使用的方法相同。 这说明了使用JNDI资源来封装功能的一个优点 - 只要维护兼容的API,您就可以更改底层实现,而无需使用资源修改应用程序。


关注我的技术公众号,查看更多优质技术文章推送

微信扫一扫下方二维码即可关注:

关注我的技术公众号,查看更多优质技术文章推送

<Context path="/ZY_23106122" docBase="D:\tomcat\apache-tomcat-10.1.46\webapps\ZY_23106122" reloadable="true" />将这个添加到<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html --> <Server port="8005" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" /> --> <!-- OpenSSL support using Tomcat Native --> <Listener className="org.apache.catalina.core.AprLifecycleListener" /> <!-- OpenSSL support using FFM API from Java 22 --> <!-- <Listener className="org.apache.catalina.core.OpenSSLLifecycleListener" /> --> <!-- Prevent memory leaks due to use of particular java/javax APIs--> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html --> <GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html --> <Service name="Catalina"> <!--The connectors can use a shared executor, you can define one or more named thread pools--> <!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/> --> <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : HTTP Connector: /docs/config/http.html AJP Connector: /docs/config/ajp.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxParameterCount="1000" /> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxParameterCount="1000" /> --> <!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This connector uses the NIO implementation. The default SSLImplementation will depend on the presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. Either JSSE or OpenSSL style configuration may be used regardless of the SSLImplementation selected. JSSE style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" maxParameterCount="1000" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" certificateKeystorePassword="changeit" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an AJP 1.3 Connector on port 8009 --> <!-- <Connector protocol="AJP/1.3" address="::1" port="8009" redirectPort="8443" maxParameterCount="1000" /> --> <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> --> <Engine name="Catalina" defaultHost="localhost"> <!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --> <!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> --> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server> 生成全部完整conf/server.xml的配置
最新发布
10-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hailushijie

您的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值