Servlet配置详解
1 定义头和根元素
部署描述符文件就像所有 XML 文件一 样 ,必 须 以一个 XML 头开 始。 这 个 头 声明可以使用的 XML 版本并 给 出文件的字符 编码 。
DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本(如2.2或2.3)并指定管理此文件其余部分内容的语法的DTD(Document Type Definition,文档类型定义)。
所有部署描述符文件的顶层(根)元素为web-app。请注意,XML元素不像HTML,他们是大小写敏感的。因此,web-App和WEB-APP都是不合法的,web-app必须用小写。
2 部署描述符文件内的元素次序
XML 元素不 仅 是大小写敏感的,而且它 们还对 出 现 在其他元素中的次序敏感。例如, XML 头 必 须 是文件中的第一 项 , DOCTYPE 声明必 须 是第二 项 ,而 web- app 元素必 须 是第三 项 。在 web-app 元素内,元素的次序也很重要。服 务 器不一定 强 制要求 这种 次序,但它 们 允 许 ( 实际 上有些服 务 器就是 这样 做的)完全拒 绝执 行含有次序不正确的元素的 Web 应 用。 这 表示使用非 标 准元素次序的 web.xml 文件是不可移植的。
下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如,此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意,所有这些元素都是可选的。因此,可以省略掉某一元素,但不能把它放于不正确的位置。
l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。
l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。
l description description元素给出与此有关的说明性文本。
l context-param context-param元素声明应用范围内的初始化参数。
l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。
l filter-mapping 一旦命名了一个过滤器,就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。
l listener servlet API的版本2.3增加了对事件监听程序的支持,事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。
l servlet 在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。
l servlet-mapping 服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName。但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素。
l session-config 如果某个会话在一定时间内未被访问,服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值,或者可利用session-config元素制定缺省超时值。
l mime-mapping 如果Web应用具有想到特殊的文件,希望能保证给他们分配特定的MIME类型,则mime-mapping元素提供这种保证。
l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时,使用哪个文件。
l error-page error-page元素使得在返回特定HTTP状态代码时,或者特定类型的异常被抛出时,能够制定将要显示的页面。
l taglib taglib元素对标记库描述符文件(Tag Libraryu Descriptor file)指定别名。此功能使你能够更改TLD文件的位置,而不用编辑使用这些文件的JSP页面。
l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。
l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。
l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用
l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。
l security-role security-role元素给出安全角色的一个列表,这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。
l env-entry env-entry元素声明Web应用的环境项。
l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。
l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。
3 分配名称和定制的UL
在 web.xml 中完成的一个最常 见 的任 务 是 对 servlet 或 JSP 页 面 给 出名称和定制的 URL 。 用 servlet 元素分配名称,使用 servlet-mapping 元素将定制的 URL 与 刚 分配的名称相 关联 。
3.1 分配名称
为 了提供初始化参数, 对 servlet 或 JSP 页 面定 义 一个定制 URL 或分配一个安全角色,必 须 首先 给 servlet 或 JSP 页 面一个名称。可通 过 servlet 元素分配一个名称。最常 见 的格式包括 servlet-name 和 servlet-class 子元素(在 web-app 元素内),如下所示:<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
这
表示位于
WEB-INF/classes/moreservlets/TestServlet
的
servlet
已
经
得到了注册名
Test
。
给
servlet
一个名称具有两个主要的含
义
。首先,初始化参数、定制的
URL
模式以及其他定制通
过
此注册名而不是
类
名引用此
servlet
。其次
,
可在
URL
而不是
类
名中使用此名称。因此,利用
刚
才
给
出的定
义
,
URL
http://host/webAppPrefix/servlet/Test
可用于
http://host/webAppPrefix/servlet/moreservlets.TestServlet
的
场
所。
请记 住: XML 元素不 仅 是大小写敏感的,而且定 义 它 们 的次序也很重要。例如, web-app 元素内所有 servlet 元素必 须 位于所有 servlet- mapping 元素(下一小 节 介 绍 )之前,而且 还 要位于 5.6 节 和 5.11 节讨论 的与 过滤 器或文档相 关 的元素(如果有的 话 )之前。 类 似地, servlet 的 servlet-name 子元素也必 须 出 现 在 servlet-class 之前。 5.2 节 " 部署描述符文件内的元素次序 " 将 详细 介 绍这种 必需的次序。
例如,程序清 单 5-1 给 出了一个名 为 TestServlet 的 简单 servlet ,它 驻 留在 moreservlets 程序包中。因 为 此 servlet 是扎根在一个名 为 deployDemo 的目 录 中的 Web 应 用的 组 成部分,所以 TestServlet.class 放在 deployDemo/WEB- INF/classes/moreservlets 中。程序清 单 5-2 给 出将放置在 deployDemo/WEB-INF/ 内的 web.xml 文件的一部分。此 web.xml 文件使用 servlet-name 和 servlet-class 元素将名称 Test 与 TestServlet.class 相 关联 。 图 5-1 和 图 5-2 分 别显 示利用缺省 URL 和注册名 调 用 TestServlet 时 的 结 果。
程序清单5-1 TestServlet.java
package moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet used to illustrate servlet naming
* and custom URLs.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String uri = request.getRequestURI();
out.println(ServletUtilities.headWithTitle("Test Servlet") +
"<BODY BGCOLOR=/"#FDF5E6/">/n" +
"<H2>URI: " + uri + "</H2>/n" +
"</BODY></HTML>");
}
}
程序清单5-2 web.xml(说明servlet名称的摘录)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- … -->
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
<!-- … -->
</web-app>
3.2 定义定制的URL
大多数服
务
器具有一个缺省的
serlvet URL
:
http://host/webAppPrefix/servlet/packageName.ServletName。虽然在开发中使用这个URL很方便,但是我们常常会希望另一个URL用于部署。例如,可能会需要一个出现在Web应用顶层的URL(如,http: //host/webAppPrefix/Anyname),并且在此URL中没有servlet项。位于顶层的URL简化了相对URL的使用。此外,对许多开发人员来说,顶层URL看上去比更长更麻烦的缺省URL更简短。
事实上,有时需要使用定制的URL。比如,你可能想关闭缺省URL映射,以便更好地强制实施安全限制或防止用户意外地访问无初始化参数的servlet。如果你禁止了缺省的URL,那么你怎样访问servlet呢?这时只有使用定制的URL了。
为 了分配一个定制的 URL ,可使用 servlet-mapping 元素及其 servlet-name 和 url-pattern 子元素。 Servlet- name 元素提供了一个任意名称,可利用此名称引用相 应 的 servlet ; url-pattern 描述了相 对 于 Web 应 用的根目 录 的 URL 。 url- pattern 元素的 值 必 须 以斜杠( / )起始。下面 给 出一个 简单 的 web.xml 摘 录 ,它允 许 使用 URL http://host/webAppPrefix/UrlTest 而不是 http://host/webAppPrefix/servlet/Test 或
http: //host/webAppPrefix/servlet/moreservlets.TestServlet 。 请 注意,仍然需要 XML 头 、 DOCTYPE 声明以及 web-app 封 闭 元素。此外,可回 忆 一下, XML 元素出 现 地次序不是随意的。特 别 是,需要把所有 servlet 元素放在所有 servlet-mapping 元素之前。
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/UrlTest</url-pattern>
</servlet-mapping>
URL
模式
还
可以包含通配符。例如,下面的小程序指示服
务
器
发
送所有以
Web
应
用的
URL
前
缀开
始,以
..asp
结
束的
请
求到名
为
BashMS
的
servlet
。
<servlet>
<servlet-name>BashMS</servlet-name>
<servlet-class>msUtils.ASPTranslator</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name>BashMS</servlet-name>
<url-pattern>/*.asp</url-pattern>
</servlet-mapping>
3.3 命名JSP页面
因 为 JSP 页 面要 转换 成 sevlet ,自然希望就像命名 servlet 一 样 命名 JSP 页 面。 毕 竟, JSP 页 面可能会从初始化参数、安全 设 置或定制的 URL 中受益,正如普通的 serlvet 那 样 。 虽 然 JSP 页 面的后台 实际 上是 servlet 这 句 话 是正确的,但 存在一个 关键 的猜疑:即,你不知道 JSP 页 面的 实际类 名(因 为 系 统 自己挑 选这 个名字)。因此, 为 了命名 JSP 页 面,可将 jsp-file 元素替 换为 servlet-calss 元素,如下所示:<servlet>
<servlet-name>Test</servlet-name>
<jsp-file>/TestPage.jsp</jsp-file>
</servlet>
命名JSP页面的原因与命名servlet的原因完全相同:即为了提供一个与定制设置(如,初始化参数和安全设置)一起使用的名称,并且,以便能更改激活 JSP页面的URL(比方说,以便多个URL通过相同页面得以处理,或者从URL中去掉.jsp扩展名)。但是,在设置初始化参数时,应该注意,JSP页面是利用jspInit方法,而不是init方法读取初始化参数的。
例如,程序清 单 5-3 给 出一个名 为 TestPage.jsp 的 简单 JSP 页 面,它的工作只是打印出用来激活它的 URL 的本地部分。 TestPage.jsp 放置在 deployDemo 应 用的 顶层 。程序清 单 5-4 给 出了用来分配一个注册名 PageName ,然后将此注册名与 http://host/webAppPrefix/UrlTest2/anything 形式的 URL 相 关联 的 web.xml 文件(即, deployDemo/WEB-INF/web.xml )的一部分。程序清 单 5-3 TestPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>
JSP Test Page
</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>URI: <%= request.getRequestURI() %></H2>
</BODY>
</HTML>
程序清
单
5-4 web.xml
(
说
明
JSP
页
命名的摘
录
)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/TestPage.jsp</jsp-file>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> PageName </servlet-name>
<url-pattern>/UrlTest2/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
4 禁止激活器servlet
对servlet或JSP页面建立定制URL的一个原因是,这样做可以注册从 init(servlet)或jspInit(JSP页面)方法中读取得初始化参数。但是,初始化参数只在是利用定制URL模式或注册名访问 servlet或JSP页面时可以使用,用缺省URLhttp://host/webAppPrefix/servlet/ServletName访问时不能使用。因此,你可能会希望关闭缺省URL,这样就不会有人意外地调用初始化servlet了。这个过程有时称为禁止激活器servlet,因为多数服务器具有一个用缺省的servlet URL注册的标准servlet,并激活缺省的URL应用的实际servlet。
有两 种 禁止此缺省 URL 的主要方法:1. 在 每 个 Web 应 用中重新映射 /servlet/ 模式。
2.全局关闭激活器servlet。
重要的是应该注意到,虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激活servlet所做的工作更多,但重新映射可以用一种完全可移植的方式来完成。相反,全局禁止激活器servlet完全是针对具体机器的,事实上有的服务器(如ServletExec)没有这样的选择。下面的讨论对每个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的详细内容。
4.1 重新映射/servlet/URL模式
在一个特定的Web应用中禁止以http://host/webAppPrefix/servlet/开始的URL的处理非常简单。所需做的事情就是建立一个错误消息servlet,并使用前一节讨论的url-pattern元素将所有匹配请求转向该 servlet。只要简单地使用:
<url-pattern>/servlet/*</url-pattern>
作为servlet-mapping元素中的模式即可。
例如,程序清单5-5给出了将SorryServlet servlet(程序清单5-6)与所有以http://host/webAppPrefix/servlet/开头的URL相关联的部署描述符文件的一部分。
程序清 单 5-5 web.xml ( 说 明 JSP 页 命名的摘 录 )
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<servlet>
<servlet-name>Sorry</servlet-name>
<servlet-class>moreservlets.SorryServlet</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> Sorry </servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
程序清
单
5-6 SorryServlet.javapackage moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet used to give error messages to
* users who try to access default servlet URLs
* (i.e., http://host/webAppPrefix/servlet/ServletName)
* in Web applications that have disabled this
* behavior.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class SorryServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Invoker Servlet Disabled.";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=/"#FDF5E6/">/n" +
"<H2>" + title + "</H2>/n" +
"Sorry, access to servlets by means of/n" +
"URLs that begin with/n" +
"http://host/webAppPrefix/servlet//n" +
"has been disabled./n" +
"</BODY></HTML>");
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
4.2 全局禁止激活器:Tomcat
Tomcat 4
中用来
关闭
缺省
URL
的方法与
Tomcat 3
中所用的很不相同。下面介
绍这
两
种
方法:
1.禁止激活器: Tomcat 4
Tomcat 4
用与前面相同的方法
关闭
激活器
servlet
,即利用
web.xml
中的
url-mapping
元素
进
行
关闭
。不同之
处
在于
Tomcat
使用了放在
install_dir/conf
中的一个服
务
器
专
用的全局
web.xml
文件,而前面使用的是存放在
每
个
Web
应
用的
WEB-INF
目
录
中的
标
准
web.xml
文件。
因此, 为 了在 Tomcat 4 中 关闭 激活器 servlet ,只需在 install_dir/conf/web.xml 中 简单 地注 释 出 /servlet/* URL 映射 项 即可,如下所示:
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
再次提醒,
应该
注意
这
个
项
是位于存放在
install_dir/conf
的
Tomcat
专
用的
web.xml
文件中的,此文件不是存放在
每
个
Web
应
用的
WEB-INF
目
录
中的
标
准
web.xml
。
2.禁止激活器:Tomcat3
在
Apache Tomcat
的版本
3
中,通
过
在
install_dir/conf/server.xml
中注
释
出
InvokerInterceptor
项
全局禁止缺省
servlet URL
。例如,下面是禁止使用缺省
servlet URL
的
server.xml
文件的一部分。
<!--
<RequsetInterceptor
className="org.apache.tomcat.request.InvokerInterceptor"
debug="0" prefix="/servlet/" />
-->
5 初始化和预装载servlet与JSP页面
这 里 讨论 控制 servlet 和 JSP 页 面的启 动 行 为 的方法。特 别 是, 说 明了怎 样 分配初始化参数以及怎 样 更改服 务 器生存期中装 载 servlet 和 JSP 页 面的 时 刻。
5.1 分配servlet初始化参数
利用 init-param 元素向 servlet 提供初始化参数, init-param 元素具有 param-name 和 param-value 子元素。例如,在下面的例子中,如果 initServlet servlet 是利用它的注册名( InitTest ) 访问 的,它将能 够 从其方法中 调 用 getServletConfig().getInitParameter("param1") 获 得 "Value 1" , 调 用 getServletConfig().getInitParameter("param2") 获 得 "2" 。<servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
在
涉
及初始化参数
时
,有几点需要注意:
- 返回值。GetInitParameter的返回值总是一个String。因此,在前一个例子中,可对param2使用Integer.parseInt获得一个int。
- JSP中的初始化。JSP页面使用jspInit而不是init。JSP页面还需要使用jsp-file元素代替servlet-class。
- 缺省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式访问Servlet时可以使用。因此,在这个例子中,param1和 param2初始化参数将能够在使用URL http://host/webAppPrefix/servlet/InitTest时可用,但在使用URL http://host/webAppPrefix/servlet/myPackage.InitServlet时不能使用。
程序清 单 5-7 InitServlet.java
package moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet used to illustrate servlet
* initialization parameters.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class InitServlet extends HttpServlet {
private String firstName, emailAddress;
public void init() {
ServletConfig config = getServletConfig();
firstName = config.getInitParameter("firstName");
emailAddress = config.getInitParameter("emailAddress");
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String uri = request.getRequestURI();
out.println(ServletUtilities.headWithTitle("Init Servlet") +
"<BODY BGCOLOR=/"#FDF5E6/">/n" +
"<H2>Init Parameters:</H2>/n" +
"<UL>/n" +
"<LI>First name: " + firstName + "/n" +
"<LI>Email address: " + emailAddress + "/n" +
"</UL>/n" +
"</BODY></HTML>");
}
}
程序清
单
5-8 web.xml
(
说
明初始化参数的摘
录
)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>firstName</param-name>
<param-value>Larry</param-value>
</init-param>
<init-param>
<param-name>emailAddress</param-name>
<param-value>Ellison@Microsoft.com</param-value>
</init-param>
</servlet>
<!-- ... -->
</web-app>
5.2 分配JSP初始化参数
给 JSP 页 面提供初始化参数在三个方面不同于 给 servlet 提供初始化参数。1 )使用 jsp-file 而不是 servlet-class 。因此, WEB-INF/web.xml 文件的 servlet 元素如下所示:
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/RealPage.jsp</jsp-file>
<init-param>
<param-name>...</param-name>
<param-value>...</param-value>
</init-param>
...
</servlet>
2)
几乎
总
是分配一个明确的
URL
模式。
对
servlet
,一般相
应
地使用以
http://host/webAppPrefix/servlet/
开
始的缺省
URL
。只需
记
住,使用注册名而不是原名称即可。
这对
于
JSP
页
面在技
术
上也是合法的。例如,在上面
给
出的例子中,可用
URL
http://host/webAppPrefix/servlet/PageName
访问
RealPage.jsp
的
对
初始化参数具有
访问权
的版本。但在用于
JSP
页
面
时
,
许
多用
户
似乎不喜
欢应
用常
规
的
servlet
的
URL
。此外,如果
JSP
页
面位于服
务
器
为
其提供了目
录
清
单
的目
录
中(如,一个既没有
index.html
也没有
index.jsp
文件的目
录
),
则
用
户
可能会
连
接到此
JSP
页
面,
单击
它,从而意外地激活未初始化的
页
面。因此,好的
办
法是使用
url-pattern
(
5.3
节
)将
JSP
页
面的原
URL
与注册的
servlet
名相
关联
。
这样
,客
户
机可使用
JSP
页
面的普通名称,但仍然激活定制的版本。例如,
给
定来自
项
目
1
的
servlet
定
义
,可使用下面的
servlet-mapping
定
义
:
<servlet-mapping>
<servlet-name>PageName</servlet-name>
<url-pattern>/RealPage.jsp</url-pattern>
</servlet-mapping>
3
)
JSP
页
使用
jspInit
而不是
init
。自
动
从
JSP
页
面建立的
servlet
或
许
已
经
使用了
inti
方法。因此,使用
JSP
声明提供一个
init
方法是不合法的,必
须
制定
jspInit
方法。
为 了 说 明初始化 JSP 页 面的 过 程,程序清 单 5-9 给 出了一个名 为 InitPage.jsp 的 JSP 页 面,它包含一个 jspInit 方法且放置于 deployDemo Web 应 用 层 次 结 构的 顶层 。一般, http://host/deployDemo/InitPage.jsp 形式的 URL 将激活此 页 面的不具有初始化参数 访问权 的版本,从而将 对 firstName 和 emailAddress 变 量 显 示 null 。但是, web.xml 文件(程序清 单 5-10 )分配了一个注册名,然后将 该 注册名与 URL 模式 /InitPage.jsp 相 关联 。
程序清 单 5-9 InitPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>JSP Init Test</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>Init Parameters:</H2>
<UL>
<LI>First name: <%= firstName %>
<LI>Email address: <%= emailAddress %>
</UL>
</BODY></HTML>
<%!
private String firstName, emailAddress;
public void jspInit() {
ServletConfig config = getServletConfig();
firstName = config.getInitParameter("firstName");
emailAddress = config.getInitParameter("emailAddress");
}
%>
程序清
单
5-10 web.xml
(
说
明
JSP
页
面的
init
参数的摘
录
)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<servlet>
<servlet-name>InitPage</servlet-name>
<jsp-file>/InitPage.jsp</jsp-file>
<init-param>
<param-name>firstName</param-name>
<param-value>Bill</param-value>
</init-param>
<init-param>
<param-name>emailAddress</param-name>
<param-value>gates@oracle.com</param-value>
</init-param>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> InitPage</servlet-name>
<url-pattern>/InitPage.jsp</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
5.3 提供应用范围内的初始化参数
一般, 对单 个地 servlet 或 JSP 页 面分配初始化参数。指定的 servlet 或 JSP 页 面利用 ServletConfig 的 getInitParameter 方法 读 取 这 些参数。但是,在某些情形下,希望提供可由任意 servlet 或 JSP 页 面借助 ServletContext 的 getInitParameter 方法 读 取的系 统 范 围 内的初始化参数。可利用 context-param 元素声明 这 些系 统 范 围 内的初始化 值 。 context-param 元素 应该 包含 param-name 、 param-value 以及可 选 的 description 子元素,如下所示:
<context-param>
<param-name>support-email</param-name>
<param-value>blackhole@mycompany.com</param-value>
</context-param>
可回
忆
一下,
为
了保
证
可移植性,
web.xml
内的元素必
须
以正确的次序声明。但
这
里
应该
注意,
context-param
元素必
须
出
现
任意与文档有
关
的元素(
icon
、
display-name
或
description
)之后及
filter
、
filter-mapping
、
listener
或
servlet
元素之前。
5.4 在服务器启动时装载servlet
假如
servlet
或
JSP
页
面有一个要花很
长时间执
行的
init
(
servlet
)或
jspInit
(
JSP
)方法。例如,假如
init
或
jspInit
方法从某个数据
库
或
ResourceBundle
查
找
产
量。
这种
情况下,在第一个客
户
机
请
求
时
装
载
servlet
的缺省行
为
将
对
第
一个客
户
机
产
生
较长时间
的延
迟
。因此,可利用
servlet
的
load-on- startup
元素
规
定服
务
器在第一次启
动时
装
载
servlet
。下面是一个例子。
<servlet>
<servlet-name> … </servlet-name>
<servlet-class> … </servlet-class> <!-- Or jsp-file -->
<load-on-startup/>
</servlet>
可以
为
此元素体提供一个整数而不是使用一个空的
load-on-startup
。想法是服
务
器
应该
在装
载较
大数目的
servlet
或
JSP
页
面之前装
载较
少数目的
servlet
或
JSP
页
面。例如,下面的
servlet
项
(放置在
Web
应
用的
WEB-INF
目
录
下的
web.xml
文件中的
web-app
元素内)将指示服
务
器首先装
载
和初始化
SearchServlet
,然后装
载
和初始化由位于
Web
应
用的
result
目
录
中的
index.jsp
文件
产
生的
servlet
。
<servlet>
<servlet-name>Search</servlet-name>
<servlet-class>myPackage.SearchServlet</servlet-class> <!-- Or jsp-file -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Results</servlet-name>
<servlet-class>/results/index.jsp</servlet-class> <!-- Or jsp-file -->
<load-on-startup>2</load-on-startup>
</servlet>
6 声明过滤器
servlet 版本 2.3 引入了 过滤 器的概念。 虽 然所有支持 servlet API 版本 2.3 的服 务 器都支持 过滤 器,但 为 了使用与 过滤 器有 关 的元素,必 须 在 web.xml 中使用版本 2.3 的 DTD 。
过滤 器可截取和修改 进 入一个 servlet 或 JSP 页 面的 请 求或从一个 servlet 或 JSP 页 面 发 出的相 应 。在 执 行一个 servlet 或 JSP 页 面之前,必 须执 行第一个相 关 的 过滤 器的 doFilter 方法。在 该过滤 器 对 其 FilterChain 对 象 调 用 doFilter 时 , 执 行 链 中的下一个 过滤 器。如果没有其他 过滤 器 , servlet 或 JSP 页 面被 执 行。 过滤 器具有 对 到来的 ServletRequest 对 象的全部 访问权 ,因此,它 们 可以 查 看客 户 机名、 查 找到来的 cookie 等。 为 了 访问 servlet 或 JSP 页 面的 输 出, 过滤 器可将响 应对 象包裹在一个替身 对 象( stand-in object )中,比方 说 把 输 出累加到一个 缓 冲区。在 调 用 FilterChain 对 象的 doFilter 方法之后, 过滤 器可 检查缓 冲区,如有必要,就 对 它 进 行修改,然后 传 送到客 户 机。
例如,程序清 单 5-11 帝国 难 以了一个 简单 的 过滤 器,只要 访问 相 关 的 servlet 或 JSP 页 面,它就截取 请 求并在 标 准 输 出上打印一个 报 告( 开发过 程中在桌面系 统 上运行 时 ,大多数服 务 器都可以使用 这 个 过滤 器)。
程序清 单 5-11 ReportFilter.java
package moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Simple filter that prints a report on the standard output
* whenever the associated servlet or JSP page is accessed.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class ReportFilter implements Filter {
public void doFilter(ServletRequest request,ServletResponse response,
FilterChain chain)
throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest)request;
System.out.println(req.getRemoteHost() +" tried to access " +req.getRequestURL() +" on " + new Date() + ".");
chain.doFilter(request,response);
}
public void init(FilterConfig config)
throws ServletException {
}
public void destroy() {}
}
一旦建立了一个
过滤
器,可以在
web.xml
中利用
filter
元素以及
filter-name
(任意名称)、
file-class
(完全限定的
类
名)和(可
选
的)
init-params
子元素声明它。
请
注意,元素在
web.xml
的
web-app
元素中出
现
的次序不是任意的;允
许
服
务
器(但不是必需的)
强
制所需的次序,并且
实际
中有些服
务
器也是
这样
做的。但
这
里要注意,所有
filter
元素必
须
出
现
在任意
filter-mapping
元素之前,
filter-mapping
元素又必
须
出
现
在所
有
servlet
或
servlet-mapping
元素之前。
例如, 给 定上述的 ReportFilter 类 ,可在 web.xml 中作出下面的 filter 声明。它把名称 Reporter 与 实际 的 类 ReportFilter (位于 moreservlets 程序包中)相 关联 。
<filter>
<filter-name>Reporter</filter-name>
<filter-class>moresevlets.ReportFilter</filter-class>
</filter>
一旦命名了一个
过滤
器,可利用
filter-mapping
元素把它与一个或多个
servlet
或
JSP
页
面相
关联
。
关
于此
项
工作有两
种选择
。
首先,可使用 filter-name 和 servlet-name 子元素把此 过滤 器与一个特定的 servlet 名(此 servlet 名必 须 稍后在相同的 web.xml 文件中使用 servlet 元素声明) 关联 。例如,下面的程序片断指示系 统 只要利用一个定制的 URL 访问 名 为 SomeServletName 的 servlet 或 JSP 页 面,就运行名 为 Reporter 的 过滤 器。
<filter-mapping>
<filter-name>Reporter</filter-name>
<servlet-name>SomeServletName</servlet-name>
</filter-mapping>
其次,可利用
filter-name
和
url-pattern
子元素将
过滤
器与一
组
servlet
、
JSP
页
面或静
态
内容相
关联
。例如,相面的程序片段指示系
统
只要
访问
Web
应
用中的任意
URL
,就运行名
为
Reporter
的
过滤
器。
<filter-mapping>
<filter-name>Reporter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
例如,程序清
单
5-12
给
出了将
ReportFilter
过滤
器与名
为
PageName
的
servlet
相
关联
的
web.xml
文件的一部分。名字
PageName
依次又与一个名
为
TestPage.jsp
的
JSP
页
面以及以模式
http: //host/webAppPrefix/UrlTest2/
开头
的
URL
相
关联
。
TestPage.jsp
的源代
码
已
经
JSP
页
面命名的
谈论
在前面的
3
节
"
分配名称和定制的
URL"
中
给
出。事
实
上,程
序清
单
5- 12
中的
servlet
和
servlet-name
项
从
该节
原封不
动
地拿
过
来的。
给
定
这
些
web.xml
项
,可看到下面的
标
准
输
出形式的
调试报
告(
换
行是
为
了容易
阅读
)。
audit.irs.gov tried to access
http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html
on Tue Dec 25 13:12:29 EDT 2001.
程序清 单 5-12 Web.xml ( 说 明 filter 用法的摘 录 )
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>Reporter</filter-name>
<filter-class>moresevlets.ReportFilter</filter-class>
</filter>
<!-- ... -->
<filter-mapping>
<filter-name>Reporter</filter-name>
<servlet-name>PageName</servlet-name>
</filter-mapping>
<!-- ... -->
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/RealPage.jsp</jsp-file>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> PageName </servlet-name>
<url-pattern>/UrlTest2/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
7 指定欢迎页
假如用 户 提供了一个像 http: //host/webAppPrefix/directoryName/ 这样 的包含一个目 录 名但没有包含文件名的 URL ,会 发 生什 么 事情呢?用 户 能得到一个目 录 表?一个 错误 ? 还 是 标 准文件的内容?如果得到 标 准文件内容,是 index.html 、 index.jsp 、 default.html 、 default.htm 或 别 的什 么东 西呢?
Welcome-file-list 元素及其 辅 助的 welcome-file 元素解决了 这 个模糊的 问题 。例如,下面的 web.xml 项 指出,如果一个 URL 给 出一个目 录 名但未 给 出文件名,服 务 器 应该 首先 试 用 index.jsp ,然后再 试 用 index.html 。如果两者都没有找到, 则结 果有 赖 于所用的服 务 器(如一个目 录 列表)。
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
虽
然
许
多服
务
器缺省遵循
这种
行
为
,但不一定必
须这样
。因此,明确地使用
welcom-file-list
保
证
可移植性是一
种
良好的
习惯
。
8 指定处理错误的页面
现 在我了解到,你在 开发 servlet 和 JSP 页 面 时 从不会犯 错误 ,而且你的所有 页 面是那 样 的清晰,一般的程序 员 都不会被它 们 的搞糊涂。但是,是人 总 会犯 错误 的,用 户 可能会提供不合 规 定的参数,使用不正确的 URL 或者不能提供必需的表 单 字段 值 。除此之外,其它 开发 人 员 可能不那 么细 心,他 们应该 有些工具来克服自己的不足。
error-page 元素就是用来克服 这 些 问题 的。它有两个可能的子元素,分 别 是: error-code 和 exception- type 。第一个子元素 error-code 指出在 给 定的 HTTP 错误 代 码 出 现时 使用的 URL 。第二个子元素 excpetion-type 指出在出 现 某个 给 定的 Java 异常但未捕捉到 时 使用的 URL 。 error-code 和 exception-type 都利用 location 元素指出相 应 的 URL 。此 URL 必 须 以 / 开 始。 location 所指出的位置 处 的 页 面可通 过查 找 HttpServletRequest 对 象的两个 专门 的属性来 访问关 于 错误 的 信息, 这 两个属性分 别 是: javax.servlet.error.status_code 和 javax.servlet.error.message 。
可回 忆 一下,在 web.xml 内以正确的次序声明 web-app 的子元素很重要。 这 里只要 记 住, error-page 出 现 在 web.xml 文件的末尾附近, servlet 、 servlet-name 和 welcome-file-list 之后即可。
8.1 error-code元素
为 了更好地了解 error-code 元素的 值 ,可考 虑 一下如果不正确地 输 入文件名,大多数站点会作出什 么 反映。 这样 做一般会出 现 一个 404 错误 信息,它表示不能找到 该 文件,但几乎没提供更多有用的信息。另一方面,可以 试 一下在 www.microsoft.com 、 www.ibm.com 处 或者特 别 是在 www.bea.com 处输 出未知的文件名。 这 是会得出有用的消息, 这 些消息提供可 选择 的位置,以便 查 找感 兴 趣的 页 面。提供 这样 有用的 错误页 面 对 于 Web 应 用来 说 是很有价 值 得。事 实 上 rm-error-page 子元素)。由 form-login-page 给 出的 HTML 表 单 必 须 具有一个 j_security_check 的 ACTION 属性、一个名 为 j_username 的用 户 名文本字段以及一个名 为 j_password 的口令字段。例如,程序清 单 5-19 指示服 务 器使用基于表 单 的 验证 。 Web 应 用的 顶层 目 录 中的一个名 为 login.jsp 的 页 面将收集用 户 名和 口令,并且失 败 的登 陆 将由相同目 录 中名 为 login-error.jsp 的 页 面 报 告。
程序清 单 5-19 web.xml ( 说 明 login-config 的摘 录 )
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<security-constraint> ... </security-constraint>
<login-config>
<auth-method> FORM </auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- ... -->
</web-app>
9.2 限制对Web资源的访问
现 在,可以指示服 务 器使用何 种验证 方法了。 " 了不起, " 你 说 道, " 除非我能指定一个来收到保 护 的 URL ,否 则 没有多大用 处 。 " 没 错 。指出 这 些 URL 并 说 明他 们应该 得到何 种 保 护 正是 security-constriaint 元素的用途。此元素在 web.xml 中 应该 出 现 在 login-config 的 紧 前面。它包含是个可能的子元素,分 别 是: web-resource-collection 、 auth-constraint 、 user-data-constraint 和 display-name 。下面各小 节对 它 们进 行介 绍 。1. web-resource-collection
此元素确定 应该 保 护 的 资 源。所有 security-constraint 元素都必 须 包含至少一个 web-resource-collection 项 。此元素由一个 给 出任意 标识 名称的 web-resource-name 元素、一个确定 应该 保 护 的 URL 的 url-pattern 元素、一个指出此保 护 所适用的 HTTP 命令( GET 、 POST 等,缺省 为 所有方法)的 http-method 元素和一个提供 资 料的可 选 description 元素 组 成。例如,下面的 Web-resource-collection 项 (在 security-constratint 元素内)指出 Web 应 用的 proprietary 目 录 中所有文档 应该 受到保 护 。
<security-constraint>
<web-resource-coolection>
<web-resource-name>Proprietary</web-resource-name>
<url-pattern>/propritary/*</url-pattern>
</web-resource-coolection>
<!-- ... -->
</security-constraint>
重要的是
应该
注意到,
url-pattern
仅
适用于直接
访问这
些
资
源的客
户
机。特
别
是,它不适合于通
过
MVC
体系
结
构利用
RequestDispatcher
来
访问
的
页
面,或者不适合于利用
类
似
jsp:forward
的手段来
访问
的
页
面。
这种
不匀称如果利
用得当的
话
很有好
处
。例如,
servlet
可利用
MVC
体系
结
构
查
找数据,把它放到
bean
中,
发
送
请
求到从
bean
中提取数据的
JSP
页
面并
显
示它。我
们
希望保
证
决不直接
访问
受保
护
的
JSP
页
面,而只是通
过
建立
该页
面将使用的
bean
的
servlet
来
访问
它。
url-pattern
和
auth-contraint
元素可通
过
声明不允
许
任何用
户
直接
访问
JSP
页
面来提供
这种
保
证
。但是,
这种
不匀称的行
为
可能
让开发
人
员
放松警惕,使他
们
偶然
对应
受保
护
的
资
源提供不受限制的
访问
。
2. auth-constraint
尽管 web-resource-collention 元素 质 出了哪些 URL 应该 受到保 护 ,但是 auth-constraint 元素却指出哪些用 户应该 具有受保 护资 源的 访问权 。此元素 应该 包含一个或多个 标识 具有 访问权 限的用 户类别 role- name 元素,以及包含(可 选 )一个描述角色的 description 元素。例如,下面 web.xml 中的 security-constraint 元素部 门规 定只有指定 为 Administrator 或 Big Kahuna (或两者)的用 户 具有指定 资 源的 访问权 。
<security-constraint>
<web-resource-coolection> ... </web-resource-coolection>
<auth-constraint>
<role-name>administrator</role-name>
<role-name>kahuna</role-name>
</auth-constraint>
</security-constraint>
重要的是
认识
到,到此
为
止,
这
个
过
程的可移植部分
结
束了。服
务
器怎
样
确定哪些用
户处
于任何角色以及它怎
样
存放用
户
的口令,完全有
赖
于具体的系
统
。
例如, Tomcat 使用 install_dir/conf/tomcat-users.xml 将用 户 名与角色名和口令相 关联 ,正如下面例子中所示,它指出用 户 joe (口令 bigshot )和 jane (口令 enaj )属于 administrator 和 kahuna 角色。
<tomcat-users>
<user name="joe" password="bigshot" roles="administrator,kahuna" />
<user name="jane" password="enaj" roles="kahuna" />
</tomcat-users>
l user-data-constraint
这
个可
选
的元素指出在
访问
相
关资
源
时
使用任何
传输层
保
护
。它必
须
包含一个
transport-guarantee
子元素(合法
值为
NONE
、
INTEGRAL
或
CONFIDENTIAL
),并且可
选
地包含一个
description
元素。
transport-guarantee
为
NONE
值
将
对
所用的通
讯协议
不加限制。
INTEGRAL
值
表示数据必
须
以一
种
防止截取它的人
阅读
它的方式
传
送。
虽
然原理上(并且在未来的
HTTP
版本中),在
INTEGRAL
和
CONFIDENTIAL
之
间
可能会有差
别
,但在当前
实
践中,他
们
都只是
简单
地要求用
SSL
。例如,下面指示服
务
器只允
许对
相
关资
源做
HTTPS
连
接:
<security-constraint>
<!-- ... -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
l display-name
security-constraint
的
这
个很少使用的子元素
给
予可能由
GUI
工具使用的安全
约
束
项
一个名称。
9.3 分配角色名
迄今 为 止, 讨论 已 经 集中到完全由容器(服 务 器) 处 理的安全 问题 之上了。但 servlet 以及 JSP 页 面也能 够处 理它 们 自己的安全 问题 。例如,容器可能允 许 用 户 从 bigwig 或 bigcheese 角色 访问 一个 显 示主管人 员额 外 紧贴 的 页 面,但只允 许 bigwig 用 户 修改此 页 面的参数。完成 这种 更 细 致的控制的一 种 常 见 方法是 调 用 HttpServletRequset 的 isUserInRole 方法,并据此修改 访问 。
Servlet 的 security-role-ref 子元素提供出 现 在服 务 器 专 用口令文件中的安全角色名的一个 别 名。例如,假如 编 写了一个 调 用 request.isUserInRole ( "boss" )的 servlet ,但后来 该 servlet 被用在了一个其口令文件 调 用角色 manager 而不是 boss 的服 务 器中。下面的程序段使 该 servlet 能 够 使用 这 两个名称中的任何一个。
<servlet>
<!-- ... -->
<security-role-ref>
<role-name>boss</role-name> <!-- New alias -->
<role-link>manager</role-link> <!-- Real name -->
</security-role-ref>
</servlet>
也可以在
web-app
内利用
security-role
元素提供将出
现
在
role-name
元素中的所有安全角色的一个全局列表。分
别
地生命角色使高
级
IDE
容易
处
理安全信息。
10 控制会话超时
如果某个会 话 在一定的 时间 内未被 访问 ,服 务 器可把它扔掉以 节约 内存。可利用 HttpSession 的 setMaxInactiveInterval 方法直接 设 置个 别 会 话对 象的超 时值 。如果不采用 这种 方法, 则 缺省的超 时值 由具体的服 务 器决定。但可利用 session-config 和 session- timeout 元素来 给 出一个适用于所有服 务 器的明确的超 时值 。超 时值 的 单 位 为 分 钟 ,因此,下面的例子 设 置缺省会 话 超 时值为 三个小 时 ( 180 分 钟 )。
<session-config>
<session-timeout>180</session-timeout>
</session-config>
11 Web应用的文档化
越来越多的 开发环 境 开 始提供 servlet 和 JSP 的直接支持。例子有 Borland Jbuilder Enterprise Edition 、 Macromedia UltraDev 、 Allaire JRun Studio (写此文 时 ,已被 Macromedia 收 购 )以及 IBM VisuaAge for Java 等。
大量的 web.xml 元素不 仅 是 为 服 务 器 设计 的,而且 还 是 为 可 视开发环 境 设计 的。它 们 包括 icon 、 display-name 和 discription 等。
可回 忆 一下,在 web.xml 内以适当地次序声明 web-app 子元素很重要。不 过 , 这 里只要 记 住 icon 、 display-name 和 description 是 web.xml 的 web-app 元素内的前三个合法元素即可。
1. icon
icon 元素指出 GUI 工具可用来代表 Web 应 用的一个和两个 图 像文件。可利用 small-icon 元素指定一幅 16 x 16 的 GIF 或 JPEG 图 像,用 large-icon 元素指定一幅 32 x 32 的 图 像。下面 举 一个例子:<icon>
<small-icon>/images/small-book.gif</small-icon>
<large-icon>/images/tome.jpg</large-icon>
</icon>
2. display-name
display-name 元素提供 GUI 工具可能会用来 标记 此 Web 应 用的一个名称。下面是个例子。<display-name>Rare Books</display-name>
3. description
description 元素提供解 释 性文本,如下所示:<description>
This Web application represents the store developed for
rare-books.com, an online bookstore specializing in rare
and limited-edition books.
</description>
12 关联文件与MIME类型
服 务 器一般都具有一 种让 Web 站点管理 员 将文件 扩 展名与媒体相 关联 的方法。例如,将会自 动给 予名 为 mom.jpg 的文件一个 image/jpeg 的 MIME 类 型。但是,假如你的 Web 应 用具有几个不 寻 常的文件,你希望保 证 它 们 在 发 送到客 户 机 时 分配 为 某 种 MIME 类 型。 mime-mapping 元素(具有 extension 和 mime-type 子元素)可提供 这种 保 证 。例如,下面的代 码 指示服 务 器将 application/x-fubar 的 MIME 类 型分配 给 所有以 .foo 结 尾的文件。
<mime-mapping>
<extension>foo</extension>
<mime-type>application/x-fubar</mime-type>
</mime-mapping>
或
许
,你的
Web
应
用希望重
载
(
override
)
标
准的映射。例如,下面的代
码
将告
诉
服
务
器在
发
送到客
户
机
时
指定
.ps
文件作
为纯
文本(
text/plain
)而不是作
为
PostScript
(
application/postscript
)。
<mime-mapping>
<extension>ps</extension>
<mime-type>application/postscript</mime-type>
</mime-mapping>
13 定位TLD
JSP taglib 元素具有一个必要的 uri 属性,它 给 出一个 TLD ( Tag Library Descriptor )文件相 对 于 Web 应 用的根的位置。 TLD 文件的 实际 名称在 发 布新的 标签库 版本 时 可能会改 变 ,但我 们 希望避免更改所有 现 有 JSP 页 面。此外,可能 还 希望使用保持 taglib 元素的 简练 性的一个 简 短的 uri 。 这 就是部署描述符文件的 taglib 元素派用 场 的所在了。 Taglib 包含两个子元素: taglib-uri 和 taglib-location 。 taglib-uri 元素 应该 与用于 JSP taglib 元素的 uri 属性的 东 西相匹配。 Taglib-location 元素 给 出 TLD 文件的 实际 位置。例如,假如你将文件 chart-tags- 1.3beta.tld 放在 WebApp/WEB-INF/tlds 中。 现 在,假如 web.xml 在 web-app 元素内包含下列内容。
<taglib>
<taglib-uri>/charts.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/chart-tags-1.3beta.tld
</taglib-location>
</taglib>
给
出
这
个
说
明后,
JSP
页
面可通
过
下面的
简
化形式使用
标签库
。
<%@ taglib uri="/charts.tld" prefix="somePrefix" %>
14 指定应用事件监听程序
应 用事件 监 听器 程序是建立或修改 servlet 环 境或会 话对 象 时 通知的 类 。它 们 是 servlet 规 范的版本 2.3 中的新内容。 这 里只 简单 地 说 明用来向 Web 应 用注册一个 监 听程序的 web.xml 的用法。
注册一个 监 听程序 涉 及在 web.xml 的 web-app 元素内放置一个 listener 元素。在 listener 元素内, listener-class 元素列出 监 听程序的完整的限定 类 名,如下所示:
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
虽 然 listener 元素的 结 构很 简单 ,但 请 不要忘 记 ,必 须 正确地 给 出 web-app 元素内的子元素的次序。 listener 元素位于所有的 servlet 元素之前以及所有 filter-mapping 元素之后。此外,因 为应 用生存期 监 听程序是 serlvet 规 范的 2.3 版本中的新内容,所以必 须 使用 web.xml DTD 的 2.3 版本,而不是 2.2 版本。
例如,程序清 单 5-20 给 出一个名 为 ContextReporter 的 简单 的 监 听程序,只要 Web 应 用的 Servlet-Context 建立(如装 载 Web 应 用)或消除 (如服 务 器 关闭 ) 时 ,它就在 标 准 输 出上 显 示一条消息。程序清 单 5-21 给 出此 监 听程序注册所需要的 web.xml 文件的一部分。
程序清 单 5-20 ContextReporterjava
package moreservlets;
import javax.servlet.*;
import java.util.*;
/** Simple listener that prints a report on the standard output
* when the ServletContext is created or destroyed.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class ContextReporter implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
System.out.println("Context created on " +new Date() + ".");
}
public void contextDestroyed(ServletContextEvent event) {
System.out.println("Context destroyed on " +new Date() + ".");
}
}
程序清
单
5-21 web.xml
(声明一个
监
听程序的摘
录
)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- ... -->
<filter-mapping> … </filter-mapping>
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
<servlet> ... </servlet>
<!-- ... -->
</web-app>
15 J2EE元素
本 节 描述用作 J2EE 环 境 组 成部分的 Web 应 用的 web.xml 元素。 这 里将提供一个 简 明的介 绍 , 详细 内容可以参 阅 http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf 的 Java 2 Plantform Enterprise Edition 版本 1.3 规 范的第 5 章。
1. distributable
distributable 元素指出, Web 应 用是以 这样 的方式 编 程的:即,支持集群的服 务 器可安全地在多个服 务 器上分布 Web 应 用。例如,一个可分布的 应 用必 须 只使用 Serializable 对 象作 为 其 HttpSession 对 象的属性,而且必 须 避免用 实 例 变 量(字段)来 实现 持 续 性。 distributable 元素直接出 现 在 discription 元素之后,并且不包含子元素或数据,它只是一个如下的 标 志。<distributable />
2. resource-env-ref
resource -env-ref 元素声明一个与某个 资 源有 关 的管理 对 象。此元素由一个可 选 的 description 元素、一个 resource-env-ref- name 元素(一个相 对 于 java:comp/env 环 境的 JNDI 名)以及一个 resource-env-type 元素(指定 资 源 类 型的完全限定的 类 ),如下所示:<resource-env-ref>
<resource-env-ref-name>jms/StockQueue</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
</resource-env-ref>
3. env-entry
env -entry 元素声明 Web 应 用的 环 境 项 。它由一个可 选 的 description 元素、一个 env-entry-name 元素(一个相 对 于 java: comp/env 环 境 JNDI 名)、一个 env-entry-value 元素( 项值 )以及一个 env-entry-type 元素( java.lang 程序包中一个 类 型的完全限定 类 名, java.lang.Boolean 、 java.lang.String 等) 组 成。下面是一个例子:<env-entry>
<env-entry-name>minAmout</env-entry-name>
<env-entry-value>100.00</env-entry-value>
<env-entry-type>minAmout</env-entry-type>
</env-entry>