即将面世的JEE 提供用Java开发Web应用程序的新的Servlet 和JavaServer Pages (JSP) 技术本文展示了这两种技术的新特性并在适当的地方提供每个特性的示例代码本文假设读者熟悉以前的 Servlet 和JSP 版本给出的例子已用Tomcat (包含在Java Web Services Developer Pack 中)进行了测试
Servlet和JSP毫无疑问是两种应用最广的JEE技术Servlet技术是用Java进行Web应用编程的基础也是JSP的基础但是servlet编程可能会非常麻烦特别是当你不得不发送一个没多少代码的长HTML页面时更是如此每个HTML标记必须嵌入到字符串中用PrintWriter对象的显示方式发送是一种工作单调乏味而烦人的工作使用servlet的另一个缺点是每一处改变都需要servlet程序员介入
Sun公司了解到这一问题之后便开发了JSP作为解决方案在JSP中程序员和页面设计员的分工变得容易多了并且当JSP页面更改时会自动进行编译不过请注意JSP是servlet技术的一个扩展而不是废弃servlet在实际应用当中servlet和JSP页面一起使用
Servlet 的新特性
Servlet 提供了几个新类且不支持javaxservletSingleThreadModel接口这一版本只支持HTTP 所以Servlet 应用程序不适用于HTTP 客户程序版增加了请求监听器和请求属性监听器并能在一个应用程序中将servlet用作欢迎页面另外Servlet 还提供了更好的ServletRequest和RequestDispatcher对象并更好地支持国际化此外现在是根据模式而不是文档类型定义(documenttype definitionDTD)文件来验证部署描述符是否有效这就意味着支持部署描述符的可扩展性
下面具体说明Servlet 的新特性请求监听器和请求属性监听器Servlet 增加了servlet上下文相关监听器和会话相关监听器Servlet 增加了新的javaxservletServletRequestListener和javaxservletServletRequestAttributeListener两种接口它们会通知你与Request对象有关的事件如果你对每个Request对象的初始化和撤消感兴趣你可以实施ServletRequestListener接口这个接口有两个方法requestInitialized()和requestDestroyed()当需要一个Request对象时servlet容器便调用requestInitialized方法当不再需要Request对象时servlet容器便调用requestDestroyed方法
这两个方法都从servlet容器接收一个javaxservletServletRequestEvent对象可以从ServletRequestEvent实例获得servlet上下文和servlet请求
第二个监听器接口ServletRequestAttributeListener处理Request对象属性的添加更改和删除该接口有以下方法
attributeAdded向Request对象添加新属性时由servlet容器调用
attributeRemoved从Request对象中删除属性时由servlet容器调用
attributeReplacedRequest对象中现有属性值被替换时由servlet容器调用
这三个方法从servlet容器获得javaxservletServletRequestAttributeEvent类的一个实例ServletRequestAttributeEvent类扩展了ServletRequestEvent类并添加了两个新方法getName和getValuegetName方法返回触发事件的属性的名称getValue返回属性的值
代码清单 给出这两个新的监听器的示例类当servlet容器调用方法时二者都显示方法名监听器经过编译后它们的类文件必须被部署到WEBINF/classes目录下ServletRequest中的新方法在Servlet 中javaxservletServletRequest接口增加了个新方法
getRemotePort返回发送请求的客户机或最后一个代理服务器的Internet Protocol(IP)源端口
getLocalName返回从中接收请求的IP接口的主机名
getLocalAddr返回从中接收请求的接口的IP地址
getLocalPort返回从中接收请求的接口的IP端口号
请注意在Servlet 中getServerName和getServerPort方法返回的值就是现在getLocalName和getLocalPort返回的值在版中getServerName和getServerPort已重新定义欲了解更多的信息请查看API文档
将一个JSP页面中的代码示例如下
outprintln(<br>Remote Port : +
requestgetRemotePort());
outprintln(<br>Local Name : +
requestgetLocalName());
outprintln(<br>Local Addr : +
requestgetLocalAddr());
outprintln(<br>Local Port : +
requestgetLocalPort());
该代码生成这样的内容
Remote Port :
Local Name : localhost
Local Addr :
Local Port :
请求调度程序的新特性使用请求调度程序可将当前请求传递给一个新的资源或从当前页面引入另一个资源Servlet 增加了一些属性它们将被添加到传递给另一个资源的一个Request对象上
javaxservletforwardrequest_uri
javaxntext_path
javaxservletforwardservlet_path
javaxservletforwardpath_info
javaxservletforwardquery_string
如果一个Request对象未被传递则这些属性的值为null另一方面在所传递来对象的资源中这些属性将具有非null值当某一个资源必须只能通过另一个资源调用而不能直接调用时这些属性值很有用
举个例子在一个叫做myApp的Context(上下文)中有一个名为ModernServlet的servlet ModernServlet被传递给TargetServlet 在TargetServlet中显示代码清单中的代码
myApp的部署描述符包含以下和元素
<servlet>
<servletname>Modern</servletname>
<servletclass>ModernServlet
</servletclass>
</servlet>
<servletmapping>
<servletname>Modern</servletname>
<urlpattern>/Modern</urlpattern>
</servletmapping>
<servlet>
<servletname>Target</servletname>
<servletclass>TargetServlet
</servletclass>
</servlet>
<servletmapping>
<servletname>Target</servletname>
<urlpattern>/Target</urlpattern>
</servletmapping>
下面是调用ModernServlet时控制台显示的结果
javaxservletforwardrequest_uri : /myApp/Modern
javaxntext_path : /myApp
javaxservletforwardservlet_path : /Modern
javaxservletforwardpath_info : null
javaxservletforwardquery_string : null
将过滤器用于请求调度程序Servlet 在部署描述符中添加了一个新的元素以便servlet程序员决定是否将过滤器(filters)应用于请求调度程序元素的值可以是REQUEST(默认值)FORWARDINCLUDE和ERROR
REQUEST如果请求直接来自客户机则使用过滤器
FORWARD如果请求正由请求调度程序进行处理表示与或相匹配的Web组件使用传递调用则使用过滤器
INCLUDE只有在请求正由请求调度程序进行处理表示与或相匹配的Web组件使用包含(include)调用时才使用过滤器
ERROR只有在请求正由错误页面机制处理为一个与元素相匹配的错误资源时才使用过滤器
Servlet 只支持HTTP 客户机Servlet 既支持HTTP 又支持HTTP 而Servlet 与Servlet 不同它只支持HTTP 客户机作为过渡HTTP/状态码(暂时建议)仍然存在而且仍然由javaxservlethttpHttpServletResponse接口中的SC_MOVED_TEMPORARILY表示HTTP 具有Found的状态码它由HttpServletResponse接口中的静态SC_FOUND表示
Servlet用作欢迎页面在Servlet 中你可以在部署描述符中使用元素列出欢迎文件当收到一个不完整的URL时将显示的文件但是在Servlet 中在元素中只能使用HTML文件或JSP文件在Servlet 中如今可以将一个servlet用作欢迎页面下例为一个叫做Modern的servlet它的类为ModernServletclass并已被映射到path /Modern
<servlet>
<servletname>Modern</servletname>
<servletclass>ModernServlet
</servletclass>
</servlet>
<servletmapping>
<servletname>Modern</servletname>
<urlpattern>/Modern</urlpattern>
</servletmapping>
<welcomefilelist>
<welcomefile>Modern</welcomefile>
</welcomefilelist>
此时若用户键入诸//domain/context/(不带资源文件)的URL时就会调用ModernServlet
对国际化的新支持在Servlet 中没有办法直接告诉客户浏览器应当使用什么字符编码要实现这一目的你必须把一个javautilLocale对象传递给javaxservletServletResponse接口的setLocale方法如下所示
responsesetLocale(locale);
这意味着你必须首先创建一个Locale对象
另外一种办法是在Servlet