Servlet 行为更改

Servlet 3.1 实现包含行为更改,这些更改可能导致为 Servlet 3.0 编写的应用程序在使用 Servlet 3.1 功能部件时行为不同或失败。

您可以在每个服务器实例的 Servlet 3.0 和 Servlet 3.1 功能部件实现之间进行选择,同时考虑行为更改。 如果只有 Servlet 3.1 功能部件包含所需行为,那么您必须使用 Servlet 3.1 功能部件。 如果 Servlet 3.1 功能部件中的行为更改对现有应用程序产生负面影响,那么使用 Servlet 3.0 功能部件将保留该应用程序的现有行为。 不能在同一服务器中同时使用 Servlet 3.0 和 Servlet 3.1 功能部件。 如果您同时配置这两个功能部件,那么系统不会装入任一 Servlet 功能部件。

引入行为更改出于以下原因:
  • Servlet 3.1 规范中的说明所需的更改。
  • 实现传递 Servlet 3.1 技术兼容性包 (TCK) 所需的更改。
  • 用于改进 servlet 实现的更改。

以编程方式添加的 servlet、过滤器和侦听器

Servlet 3.1 规范中的说明现在指出:如果未在 web.xml 文件或 web-fragment.xml 文件中声明 ServletContextListener 或未使用 @WebListener 注释 ServletContextListener,那么 ServletContextListener 以编程方式配置 servlet、过滤器或侦听器是非法操作。 因此,为执行这类程序配置而对 ServletContext 进行的任何调用会导致 UnsupportedOperationException。

异步处理启动后转发

在 Servlet 3.0 实现中,响应始终在 RequestDispatcher 接口的转发方法返回前关闭。 但是,因为 Servlet 3.1 规范中的说明,如果请求置于异步方式,那么 Servlet 3.1 实现不会在 RequestDispatcher 接口的转发方法返回前关闭或清仓响应。 此更改可能会影响现有 3.0 应用程序,这些应用程序会在从转发返回时添加响应输出,因为现在已发送此类响应数据,而在 Servlet 3.0中未发送此类响应数据。

URL 模式冲突

在 Servlet 3.0 中,即使一个 URL 模式被映射到多个 servlet,应用程序也能成功启动。 但是,由于 Servlet 3.1 规范中的一项说明,应用程序必须无法启动。 在 Liberty Servlet 3.1 实现中,会输出一条消息,应用程序无法启动:
SRVE9016E: Unable to insert mapping [{0}] for servlet named [{1}]. The URL pattern is already defined for servlet named [{2}].

Explanation: There is an application error. A servlet mapping URL pattern should not map to multiple servlets.

User action: Change the URL pattern for the servlet mapping.

ServletContext.getMinorVersion()

在 Servlet 3.0 功能部件实现中,此 API 返回 0

在 Servlet 3.1 功能部件中,此 API 现在返回 1

ServletContext.getServerInfo()

在 Servlet 3.0 功能部件实现中,此 API 返回 SMF WebContainer

在 Servlet 3.1 功能部件中,此 API 现在返回 IBM WebSphere Liberty/8.5.5.<x>,其中 <x> 是 WebSphere® Application Server 修订包号。

ServletResponse.reset()

如果响应未落实,那么您可使用 ServletResponse.reset() 清除所有缓存响应数据、状态码和响应标头。 如果正在使用 Servlet 3.1 功能部件,那么此方法还会清除先前调用的 ServletResonse.getWriter() 或 ServletResponse.getOutputStream() 的任何记录。

X-Powered-By 标头

在 Servlet 3.0 功能部件实现中,X-Powered-By 标头设置为 Servlet/3.0。 在 Servlet 3.1 功能部件实现中,X-Powered-By 标头设置为 Servlet/3.1

资源引用注入目标合并

在 Servlet 3.0 规范中,如果同名 web.xml 资源引用定义没有 <injection-target> 元素,那么 web-fragment.xml 文件中定义的资源引用的 <injection-target> 元素仅添加至父 web.xml 文件。 在 Servlet 3.1 规范中,已说明 web-fragment.xml 描述符中的所有<injection-target> 元素将添加至同名资源引用的 <injection-target> 元素的父 web.xml 描述符列表。 如果正在使用 Servlet 3.1 功能部件,那么此功能部件可能通过激活先前在 web.xml 文件中排除的注入目标来更改现有应用程序功能。

Web 描述符中对重复元素的容忍度

在 Servlet 3.1 规范中,已说明 web.xml 文件不能包含两个 <absolute-ordering> 元素。 部署带有多个 <absolute-ordering> 元素的应用程序将失败。 此外,web-fragment.xml 描述符不能包含两个 <ordering> 元素。 部署带有多个 <ordering> 元素的应用程序将失败。 以前此部署不会失败,但元素的功能可能无法确定。

metadata-complete 用例中的 Web 片段排序更改

如果 web.xml 描述符标记为 metadata-complete="true",那么 <absolute-ordering> 元素的处理会更改。 以前在 metadata-complete="true" 用例中,会使用所有 Web 片段归档。 使用 Servlet-3.1 功能部件时,metadata-complete 用例中的 <absolute-ordering> 元素被视为完整。 此更改导致处理时排除 <absolute-ordering> 元素中未列示的片段。

AsyncContext.dispatch()

如果您的请求调用 AsyncContext.dispatch() 且不带参数,则请求会被分派到最初的 URL. 如果在原始请求中包含一个查询字符串,并通过使用不同的查询字符串转发到另一个资源(调用 AsyncContext.dispatch()),返回给原始资源的请求参数值会随着规范级别的变化而变化。 通过 Servlet 3.0,请求将访问在原始请求的查询字符串上传递的参数。 通过 Servlet 3.1,它将访问在第二个资源的查询字符串上传递的参数。 请参阅以下示例:

Request for /FirstResource?param=One
First Resource:
    getParameter("param") returns "One"
           forward request to /SecondResource?param=Two
SecondResource
           getParameter(param) returns "Two"
           ac.start()
           ac.dispacth() dispatches to /FirstResource
First Resource
           Servlet-3.0 feature : getParamter("param") returns "One"
           Servlet-3.1 feature : getParameter("param") returns "Two"

This change was required by the Servlet 3.1 TCK.
不允许在 AsyncContext.dispatch () 或 AsyncContext.complete () 之后获取请求或响应对象,并导致以下异常:
java.lang.IllegalStateException: SRVE9015E: Cannot obtain the request or response object after an AsyncContext.dispatch() or AsyncContext.complete().
    at com.ibm.ws.webcontainer31.async.AsyncContext31Impl.getRequest(AsyncContext31Impl.java:72)
    [...]

SessionCookieConfig.setComment()

根据 Java™ Servlet 3.1 规范,如果在 ServletContext 完成初始化后调用该 API,则该 API 将返回 illegalStateException ,Servlet 3.1 功能也将遵循这一规定行为。 但是,在初始化上下文之后, Servlet 3.0 功能部件不会阻止使用此 API ,因此依赖于 Servlet 3.0 功能部件行为的应用程序将无法使用 Servlet 3.1 功能部件。

sendRedirect(java.lang.String location) API

sendRedirect(java.lang.String location) API 接受相对 URL;不过,Servlet 容器必须将相对 URL 转换为绝对 URL ,然后才能向客户端发送响应。 如果位置是相对位置,但没有前导 '/' (folder/default.jsp) ,那么容器会将其解释为相对于当前请求 URI。 如果位置是相对于前导 '/'的位置,那么容器会将其解释为相对于 servlet 容器根。

例如,如果应用程序提供的重定向位置是 folder/default.jsp ,没有前导 '/' ,而入站请求 URL 是 http://host:port/context_root/folderhttp://host:port/context_root/folder/ ,则请求会重定向到 http://host:port/context_root/folder/folder/default.jsp ,这是相对于当前请求 URI 而定的。

com.ibm.ws.webcontainer.redirectwithpathinfo 属性设置为 true 时,会在 Servlet 3.0 功能部件中发现此行为。 此属性在 Servlet 3.1 功能部件中被忽略,按描述所言,此行为是缺省行为。

缺省错误页

IBM® 扩展功能能够指定具有 Web 扩展的缺省错误页面,例如 ibm-web-ext.xml

作为 Servlet 3.0 及更高版本的功能,缺省错误页是对指定错误页功能的修改。 与常规(非缺省)错误页一样,缺省错误页是在 Web 模块描述符 (web.xml) 和 Web 片段描述符 (web-fragment.xml) 中指定的。

常规(非缺省)错误页指定 exception-type 或 error-code。 缺省错误页省略 exception-type 和 error-code。 如果 servlet 抛出异常或设置错误代码结果,并且没有与异常类型或错误代码相匹配的已配置错误页,那么系统使用缺省错误页。

Servlet 3.0 规范允许定义缺省错误页,Servlet 3.0 模式也支持此功能。 根据 Servlet 3.1 规范,缺省错误页不包含 exception-typeerror-code 元素。

错误页和缺省错误页的示例如下所示。

缺省错误页优先顺序规则
确定 web.xmlweb-fragment.xmlibm-web-ext.xml 文件中的缺省错误页的优先顺序时,有三个规则适用。
  • 规则 1:web.xmlweb-fragment.xml 文件。

    如果在 web.xml 文件中指定了缺省错误页,那么该错误页会覆盖(屏蔽)web-fragment.xml 文件中指定的任何缺省错误页。 而且,如果除此之外还有多个 web-fragment.xml 文件指定了缺省错误页,也不会发生任何错误。

  • 规则 2:web-fragment.xmlweb-fragment.xml

    如果未在 web.xml 文件中指定缺省错误页,并且两个或更多 web-fragment.xml 文件指定了不同缺省错误页,那么会发生错误。

  • 规则 3:ibm-web-ext.xmlweb.xmlweb-fragment.xml 文件。

    ibm-web-ext.xml 文件与 web.xmlweb-fragment.xml 文件之间的优先顺序规则依赖于 Web 容器功能部件级别。

如果 Web 容器功能部件级别为 3.0,那么 ibm-web-ext.xml 文件定义的缺省错误页优先于 web.xmlweb-fragment.xml 文件中定义的缺省错误页。
注: 当 Web 容器使用功能部件级别 3.0时,不能使用 Servlet 3.1 模式。 请参阅有关对 servlet 3.0 模式使用缺省错误页的规则。

如果 Web 容器功能部件级别为 3.1 或更高,那么 web.xmlweb-fragment.xml 文件指定的缺省错误页优先于 ibm-web-ext.xml 文件中指定的缺省错误页。

模式规则

确定缺省错误页是在 web.xml 文件中还是在 web-fragment.xml 文件中处理时,有两个规则适用。 这些规则取决于 Web 容器功能部件版本,正在使用的 Servlet 模式以及 Java 定制属性的设置。

产生这些规则是因为 IBM WebSphere Application Server Traditional V8.0在 V8.0 一般可用性发行版中不支持缺省错误页面。 APAR PM94199 在 service pack 中向 WebSphere Application Server 传统版添加了缺省错误页的支持。 APAR PI05845 在 WebSphere Application Server Liberty 的服务包中添加了对缺省错误页的支持。 由于这些更新是外部可视函数的更改,因此缺省情况下会禁用新函数,并且必须通过 Java 系统属性来启用新函数。

  • 规则 1:使用 Servlet 3.0 模式和使用 Web 容器功能部件 V3.0 的缺省错误页。

    如果 Web 容器功能部件版本为 3.0 ,并且在使用 Servlet 3.0 模式的 web.xmlweb-fragment.xml 文件中指定了缺省错误页面,那么仅当 com.ibm.ws.webcontainer.allowdefaulterrorpage Java 系统属性设置为 true时,才会处理缺省错误页面。 如果未设置 Java 系统属性,或者未设置为 true,那么将忽略缺省错误页面。 将使用通过 ibm-web-ext.xml 文件指定的缺省错误页。

  • 用例 2:使用 Web 容器功能部件 V3.1 的缺省错误页。

    当 Web 容器功能部件版本为 3.1 或更高时,将始终处理 web.xml 文件或 web-fragment.xml 文件中指定的缺省错误页面,而不考虑使用的 servlet 模式版本以及是否设置了 Java 定制属性。

    如果描述符使用 Servlet 3.1 模式,那么会出现这种情况,因为使用 Servlet 3.1 模式的描述符的处理需要 Web 容器功能部件 V3.1。

注意: 直到 Servlet 3.0之后才添加 Web 片段。 web-fragment.xml 文件没有来自 Servlet 2.5 的模式。
错误页和缺省错误页示例
ibm-web-ext.xml 文件中定义的缺省错误页:
<?xml version="1.0" encoding="UTF-8"?>
<web-ext xmlns="http://websphere.ibm.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
    version="1.0">

	<default-error-page uri="/ExtErrorPage.html"/>
</web-ext>
error-code 错误页元素,它是在 web.xml 文件或 web-fragment.xml 文件中定义的:
<error-page>
		<error-code>404</error-code>
			<location>/ErrorCodeErrorPage.html</location>
</error-page>
exception-type 错误页元素,它是在 web.xml 文件或 web-fragment.xml 文件中定义的:
<error-page>
		<exception-type>javax.servlet.ServletException</exception-type>
		<location>/ExceptionTypeErrorPage.html</location>
</error-page>
缺省错误页元素,它是在 web.xml 文件或 web-fragment.xml 文件中定义的:
<error-page>
		<location>/DefaultErrorPage.html</location>
</error-page>
模式示例
使用 Servlet 2.5 模式的 web.xml 文件的示例头:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
      version="2.5">
使用 Servlet 3.0 模式的 web.xml 文件的示例头:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">
使用 Servlet 3.1 模式的 web.xml 文件的示例头:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
使用 Servlet 3.0 模式的 web-fragment.xml 文件的示例头:
<?xml version="1.0" encoding="utf-8"?>
<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
      version="3.0">
使用 Servlet 3.1 模式的 web-fragment.xml 文件的示例头:
<?xml version="1.0" encoding="utf-8"?>
<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-fragment_3_1.xsd"
      version="3.1">