本章概述
Tomcat 为每个在其上运行的 Web 应用都提供了一个 JNDI 的 InitialContext 实现实例,它与Java 企业版应用服务器所提供的对应类完全兼容。Java EE 标准在 /WEB-INF/web.xml 文件中提供了一系列标准元素,用来引用或定义资源。
可通过下列规范了解如何编写针对 JNDI 的 API 以及 Java 企业版(Java EE)服务器所支持的功能,这也是 Tomcat 针对其所提供的服务而仿效的功能。
Java 命名与目录接口(包括在 JDK 1.4 或更前的版本)
Java EE 平台规范,查看其中的第5章:Naming(命名)
web.xml 配置
可在 Web 应用的部署描述符文件(/WEB-INF/web.xml)中使用下列元素来定义资源:
<env-entry> 应用的环境项。一个可用于配置应用运行方式的单值参数。
<resource-ref> 资源引用,通常是引用保存某种资源的对象工厂,比如 JDBC DataSource 或 JavaMail Session 这样的资源;或者引用配置在 Tomcat 中的自定义对象工厂中的资源。
<resource-env-ref> 资源环境引用。Servlet 2.4 所添加的一种新 resource-ref,它简化了不需要认证消息的资源的配置。
有了这些,Tomcat 就能利用适宜的资源工厂来创建资源,再也不需要其他配置信息了。Tomcat 将使用 /WEB-INF/web.xml 中的信息来创建资源。
另外,Tomcat 还提供了一些用于 JNDI 的特殊选项,它们没有指定在 web.xml 中。比如,其中包括的 closeMethod 能在 Web 应用停止时,迅速清除 JNDI 资源;singleton 控制是否会在每次 JNDI 查找时创建资源的新实例。要想使用这些配置选项,资源必须指定在 Web 应用的 <Context> 元素内,或者位于 $CATALINA_BASE/conf/server.xml 的 <GlobalNamingResources> 元素中。
context.xml 配置
如果 Tomcat 无法确定合适的资源工厂,并且/或者需要额外的配置信息,就必须在 Tomcat 创建资源之前指定好额外的具体配置。Tomcat 特定资源配置应位于 <Context> 元素内,它可以指定在 $CATALINA_BASE/conf/server.xml,或者,最好放在每个 Web 应用的上下文 XML 文件中(META-INF/context.xml)。
要想完成 Tomcat 的特定资源配置,需要使用 <Context> 元素中的下列元素:
<Resource>
定义应用所能用到的资源名称和数据类型(等同于 Web 应用部署描述符文件中包含了一个<resource-ref>
元素)。<Server>
元素中子元素<Transaction>
添加一个资源工厂,用于对从java:comp/UserTransaction
获得的 UserTransaction 接口进行实例化。
以上这些元素内嵌于 <Context> 元素中,而且是与特定应用相关联的。
如果资源已经定义在 <Context> 元素中,那就不必再在部署描述符文件中定义它了。但建议在部署描述符文件中保留相关项,以便记录应用资源需求。
加入同样一个资源名称既被定义在 Web 应用部署描述符文件的 <env-entry> 元素中,又被定义在 Web 应用的 <Context> 元素的 <Environment> 元素内,那么只有当相应的 <Environment> 元素允许时(将其中的 override 属性设为 true),部署描述符文件中的值才会优先对待。
全局配置
Tomcat 为整个服务器维护着一个全局资源的独立命名空间。这些全局资源配置在 $CATALINA_BASE/conf/server.xml 的 <GlobalNamingResources> 元素内。可以使用 <ResourceLink>将这些资源暴露给 Web 应用,以便在每一应用上下文中将其包含进来。
如果资源已经定义在 <Context> 元素中,那就不必再在部署描述符文件中定义它了。但建议在部署描述符文件中保留相关项,以便记录应用资源需求。
使用资源
当 Web 应用最初部署时,就配置 InitialContext,使其可被 Web 应用的各组件所使用(只读访问)。JNDI 命名空间的 java:comp/env 部分中包含着所有的配置项与资源,所以访问资源(在下例中,就是一个 JDBC 数据源)应按如下形式进行:
// 获取环境命名上下文 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();
Tomcat 标准资源工厂
Tomcat 包含一系列资源工厂,能为 Web 应用提供各种服务,而且无需修改 Web 应用或部署描述符文件即能灵活配置(通过 <Context> 元素)。下面所列出的每一小节都详细介绍了标准资源工厂的配置与用途。
要想了解如何创建、安装、配置和使用你自己的自定义资源工厂类,请参看添加自定义资源工厂。
注意:在标准资源工厂中,只有“JDBC DataSource”和“User Transaction”工厂可适用于其他平台,而且这些平台必须实现了 Java EE 规范。而其他所有标准资源工厂,以及你自己编写的自定义资源工厂,则都是 Tomcat 所专属的,不适用于其他容器。
一般 JavaBean 资源
简介
该资源工厂能创建出任何符合标准 JavaBean 命名规范1的 Java 类的对象。如果工厂的 singleton 属性被设为 false,那么每当对该项进行 lookup 时,资源工厂将会创建出适合的 bean 类的新实例。
1. 标准的 JavaBean 命名规范,比如:构造函数没有任何参数,属性设置器遵守 setFoo() 命名模式,等等。
使用该功能所需的步骤将在下文介绍。
创建 JavaBean 类
创建一个 JavaBean 类,在每次查找资源工厂时,就创建它的实例。比如,假设你创建了一个名叫 com.mycompany.MyBean 的 JavaBean 类,如下所示:
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; } }
声明资源需求
接下来,修改 Web 应用部署描述符文件(/WEB-INF/web.xml),声明 JNDI 名称,并据此请求该 Bean 类的新实例。最简单的方法是使用 <resource-env-ref> 元素,如下所示:
<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>
警告:一定要遵从 Web 应用部署描述符文件中 DTD 所需要的元素顺序。关于这点,可参看Servlet 规范中的解释。
使用资源
资源引用的典型用例如下所示:
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());
配置 Tomcat 资源工厂
为了配置 Tomcat 资源工厂,为 Web 应用的 <Context>元素添加下列元素:
<Context ...> ... <Resource name="bean/MyBeanFactory" auth="Container" type="com.mycompany.MyBean" factory="org.apache.naming.factory.BeanFactory" bar="23"/> ... </Context>
注意这里的资源名称,这里 bean/MyBeanFactory 必须跟部署描述符文件中所指定的值完全一样。这里还初始化了 bar 属性值,从而当返回新的 bean 时,setBar(23) 就会被调用。由于我们没有初始化 foo 属性(虽然我们完全可以这么做),所以 bean 依然采用构造函数中设置的默认值。
假设我们的 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 会使用自动侦测到的 setter 方法,并将其参数类型作为属性类型,然后抛出一个 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 也可以从字符串中设置,但必须使用非标准方法 host。如下设置 local 和 remote:
<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 中。每一属性描述要么只包含属性名,要么由 name = method 的结构所组成。对于前者的情况,BeanFactory 会直接调用属性名的 setter 方法;而对于后者,则通过调用方法 method 来设置属性名 name。对于 String 或基本类型,或者相应的基本包装器类的属性,不必使用 forceString。会自动侦测正确的 setter 并实施参数类型转换。
UserDatabase 资源
简介
UserDatabase 资源通常被配置成通过 UserDataBase Realm 所使用的全局资源。Tomcat 包含一个 UserDatabaseFactoory,能够创建基于 XML 文件(通常是 tomcat-users.xml)的 UserDatabase 资源。
建立全局的 UserDataBase 资源的步骤如下。
创建/编辑 XML 文件
XML 文件通常位于 $CATALINA_BASE/conf/tomcat-users.xml,但也可以放在文件系统中的任何位置。我们建议把该文件放在 $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>
声明资源
接下来,修改 $CATALINA_BASE/conf/server.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 可以采用绝对路径或相对路径。相对路径意味着是相对于 $CATALINA_BASE。
readonly 属性是可选属性,如果不采用,则默认为 true。如果该 XML 文件可写,那么当 Tomcat 开启时,就会被修改。警告:当该文件被修改后,它会继承 Tomcat 目前运行用户的默认文件权限。所以要确保这样做是否能保持应用的安全性。
配置 Realm
配置 UserDatabase Realm 以便使用该资源,详情可参看 第6章节Realm 配置文档
由于篇幅太长,下一章节继续讲解
感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程