附录A 变更历史
本文档是由Java社区进程SM (JCP)开发的Java Servlet 3.0 Servlet规范最终版本。
A.1 自Servlet3.0以后的变更
1. 章节2.3.3.3,“异步处理”,和AsyncContext的javadoc。
a. 阐明了AsyncListener.onStartAsync的行为。
b. 修复示例代码中的错误和注释。
c. 阐明了异步请求完成或分派之后的AsyncContext.getRequest和AsyncContext.getResponse的行为。
2. 添加章节2.3.3.5,“升级处理”,和新的类ProtocolHandler和WebConnection。
3. 章节3.2,“文件上传”,阐明了什么时候处理multi-part/form-data。
4. 章节3.7添加了异步IO、“非阻塞IO”、和章节5.7,“响应对象的生命周期”。
5. 章节5.1,“缓冲”,和ServletResponse的javadoc。阐明了ServletResponse.reset的行为。
6. 章节6.2.1,“过滤器生命周期”(4)。需要过滤器和Servlet在同一个线程中处理。
7. 章节9.4,“Forward方法”,阐明了当请求进入异步模式时response的行为。
8. 章节15.3.1,“EJB™调用中的安全身份传播”,明确提到Servlet.init和Servlet.destroy。
9. 在ServletRequestWrapper、ServletResponseWrapper和HandlesTypes中添加了泛型。
10. HttpServletResponse.sendRedirect的javadoc:支持的网络路径引用。
11. 添加新的方法ServletRequest.getContentLengthLong和ServletResponse.setContentLengthLong。
A.2 自Servlet 3.0 ProposedFinal Draft以后的变更
1. 重构一些异步API — 把addAsyncListener移动到AsyncContext 且重命名为addListener。把setAsyncTimeout移动到AsyncContext且重命名为setTimeout。
2. 阐明了异步处理中并发访问请求和响应的一些语义。
3. 更新了资源引用元素的可插拔性规则。
4. 添加了新的注解 —@ServletSecurity (和用于字段的相关注解) 来定义安全,而不重用@RolesAllowed、@PermitAll、@DenyAll
A.3 自Servlet 3.0 Public Review以后的变更
1. 更新了isAsyncStarted返回false,一旦分派到了容器或从异步处理器(async handler)中调用complete 完成了。
2. 添加了fragment的顺序支持。
3. 添加了文件上传支持。
4. 添加了从JAR文件中加载静态资源和JSP的支持,其包含在绑定在WEB-INF/lib目录中的JAR文件的META-INF/resources目录中。
5. 根据规范的PublicReview的反馈变更了注解名称。
6. 添加了编程式登录/退出支持。
7. 添加了安全相关的通用注解支持 — @RolesAllowed、@PermitAll、@DenyAll。
8. 阐明了欢迎文件。
A.4 自Servlet 3.0 EDR以后的变更
1. suspend / resume API在规范中不再存在。它们已经被startAsync和现在有forward和complete的AsyncContext的所替代。
2. 注解名字已经改变为仅有顶层注解。声明servlet方法的方法级注解不再被使用。
3. 描述了从fragment和注解装配web.xml的规则。
A.5 自Servlet 2.5 MR6以后的变更
1. 添加了注解和webfragment的支持
2. 添加了对suspend /resume的支持以允许在servlet中支持异步。
3. 添加了在初始化时从ServletContext初始化servlet和filter的支持。
4. 添加了HttpOnly cookie的支持并允许配置cookie。
5. 添加了简便方法到ServletRequest,以获取Response和ServletContext。
A.6 自Servlet 2.5 MR 5以后的变更
A.6.1 阐明SRV 8.4“Forward方法”
更改本节的最后一个句子,之前是:
“在RequestDispatcher的forward方法返回之前,响应内容必须被发送和提交,且由Servlet容器关闭。”
改为:
“在RequestDispatcher接口的forward方法无异常返回之前,响应的内容必须被发送和提交,且由Servlet容器关闭。如果RequestDispatcher.forward()的目标发生错误,异常信息会传回所有调用它经过的过滤器和servlet,且最终传回给容器。”
A.6.2 更新部署描述符“http-methodvalues allowed”
部署描述符中的http-method元素方面目前比http规范有更严格的限制。以下对描述符做出的改变,允许一组由HTTP规范定义的方法名。http-methodType模式的值从
<xsd:pattern value="[\p{L}-[\p{Cc}\p{Z}]]+"/>
改变为HTTP规范列出的允许的HTTP方法名的接近的匹配。
<xsd:patternvalue="[!-~-[\(\)<>@,;:"/\[\]?=\{\}\\\p{Z}]]+"/>
A.6.3 阐明 SRV 7.7.1 “多线程问题”
更改的段落之前是:
“在同一时间多个Servlet执行请求的线程可能都有到同一会话的活跃访问。开发人员负责以合适的方式同步访问会话资源。”
改为:
“在同一时间多个Servlet执行请求的线程可能都有到同一会话的活跃访问。容器必须确保,以一种线程安全的方式维护表示会话属性的内部数据结构。开发人员负责线程安全的访问属性对象本身。这样将防止并发访问HttpSession对象内的属性集合,消除了应用程序导致破坏集合的机会。”
A.7 自Servlet 2.5 MR 2以后的变更
A.7.1 更新JavaEE容器注解的要求
添加了15.5节“注解和资源注入”的描述列表所需的JavaEE容器注解EJBs、PreDestroy、PeristenceContext、PersistenceContexts、PersistenceUnit、和PersistenceUnits。
A.7.2 更新Java企业版的要求
更新注解到最终JavaEE注解名。也更新了web.xml的“full”属性为“metadata-complete”。
A.7.3 阐明HttpServletRequest.getRequestURL()
阐明了API文档中的javax.servlet.http.HttpServletRequest.getRequestURL()。
新增了斜体文本:
如果请求已使用RequestDispatcher.forward(ServletRequest, ServletResponse)转发,重新构建的URL中的服务器路径必须反映出得到的RequestDispatcher所使用的路径,且不是客户端指定的服务器路径。由于该方法返回一个StringBuffer,而不是一个String,你可以容易的修改此URL,例如,添加查询参数。
A.7.4 从HttpSession.getId()移除IllegalStateException
Session过期后HttpSessionBindingListener调用valueUnbound事件,不幸地是,HttpSession.getId()方法经常在该场景下使用,且抛出一个IllegalStateException。Servlet EG同意从API中移除此异常以防止这些类型的异常。
A.7.5 ServletContext.getContextPath()
getContextPath()方法被添加到ServletContext的API中。描述如下:
public java.lang.String getContextPath()
返回web应用的上下文路径(context path)。上下文路径是请求URI的一部分,用于选择请求的上下文。上下文路径总位于请求URI的最前边。路径开始于“/”字符,但不结束于“/”字符。对于Servlet位于默认(ROOT)上下文的情况,该方法返回“”。
这是可能的,Servlet容器可以使用多个上下文路径匹配一个上下文。在这种情况下,getContextPath()将返回请求使用的实际的上下文路径,且它可以不同于该方法返回的路径。该方法返回的上下文路径将被视为最佳的或首选的应用上下文路径。
返回:web应用的上下文路径。
更新了HttpServletRequest.getContextPath(),阐明它与ServletContext.getContextPath()的关系。解释如下。
这是可能的,Servlet容器可以使用多个上下文路径匹配一个上下文。在这种情况下,getContextPath()将返回请求使用的实际的上下文路径,且它可以不同于ServletContext.getContextPath()方法返回的路径。ServletContext.getContextPath()方法返回的上下文路径将被视为最佳的或首选的应用上下文路径。
A.7.6 web应用中的web.xml的要求
添加了10.13节,“包含web.xml部署描述符”,移除了对JavaEE兼容的web应用的要求。该节如下:
如果web应用不包含任何servlet、过滤器、或监听器组件,那么web应用不需要web.xml文件。换句话说,只包含静态文件或JSP页面的应用程序并不需要一个web.xml的存在。
A.8 自Servlet 2.4以后的变更
A.8.1 Session解释
阐明7.3节“Session范围”以便更好地支持在多个上下文中使用session ID。这样做是为了支持Portlet规范(JSR 168)。在7.3节最后添加了如下段落:
“此外,一个上下文的会话在请求进入那个上下文时必须是可恢复的,不管是直接访问它们关联的上下文还是在请求目标分派时创建的会话。”
修改了9.3节,“Include方法”,替换如下文本:
“不能设置header或调用响应的任何影响header的方法。任何试图这样做必须被忽略。”
为以下:
“不能设置header或调用响应的任何影响header的方法,除HttpServletRequest.getSession()和HttpServletRequest.getSession(boolean)方法之外。任何试图设置header必须被忽略,且任何调用HttpServletRequest.getSession()或HttpServletRequest.getSession(boolean)将需要添加Cookie响应头且如果响应已经提交,则必须抛出IllegalStateException异常。”
A.8.2 过滤所有分派
修改了6.2.5节,“过滤器和RequestDispatcher”,通过在此节最后添加如下文本来阐明一种映射过滤器到所有servlet分派的方法:
最后,如下代码使用特殊的servlet名字 “*”:
<filter-mapping>
<filter-name>All Dispatch Filter</filter-name>
<servlet-name>*</servlet-name>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
在按名字或按路径获取的所有请求分派器的forward()调用时该代码将导致All Dispatch Filter被调用。
A.8.3 多次出现的Servlet映射
之前版本的Servlet schema允许每个servlet-mapping只有一个url-pattern或servelt名称。对于servlet映射到的多个URL,这导致整个映射项不必要的重复。
部署描述符servlet-mappingType更新为:
代码示例 A-2 servlet-mappingType描述符
<xsd:complexType name="servlet-mappingType">
<xsd:sequence>
<xsd:element name="servlet-name" type="j2ee:servlet-nameType" />
<xsd:element name="url-pattern" type="j2ee:url-patternType"
minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" />
</xsd:complexType>
A.8.4 多次出现Filter映射
之前版本的Servlet schema仅允许一个filter-mapping只有一个url-pattern或servelt-name。对于filter映射到的多个URL,这导致整个映射项不必要的重复。
部署描述符schema filter-mappingType更新为:
代码示例 A-3 更新的filter-mappingTypeschema
<xsd:complexType name="filter-mappingType">
<xsd:sequence>
<xsd:element name="filter-name" type="j2ee:filter-nameType" />
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="url-pattern" type="j2ee:url-patternType" />
<xsd:element name="servlet-name"
type="j2ee:servlet-nameType" />
</xsd:choice>
<xsd:element name="dispatcher" type="j2ee:dispatcherType"
minOccurs="0" maxOccurs="4" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" />
</xsd:complexType>
此改变允许在一个映射中定义多个模式和servlet名字,下面的例子可以看出:
代码示例 A-4 Filter映射例子
<filter-mapping>
<filter-name>Demo Filter</filter-name>
<url-pattern>/foo/*</url-pattern>
<url-pattern>/bar/*</url-pattern>
<servlet-name>Logger</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
更新了6.2.4节,“在Web应用中配置过滤器”,使用以下文本来阐明多个映射的情况:
“如果一个过滤器映射同时包含了<servlet-name> 和 <url-pattern>,容器必须展开过滤器映射为多个过滤器映射(一个过滤器映射对应每个<servlet-name>和<url-pattern>),保持<servlet-name>和<url-pattern>元素的顺序。”
也提供了一个例子来阐明什么时候有多个映射的情况。
A.8.5 授权约束支持其他的HTTP方法
之前版本的Servlet 2.4 schema限制HTTP方法为GET、POST、PUT、DELETE、HEAD、OPTIONS、和TRACE。http-methodType schema 从
代码示例A-5 Servlet 2.4 http-methodType schema
<xsd:complexType name="http-methodType">
...
<xsd:simpleContent>
<xsd:restriction base="j2ee:string">
<xsd:enumeration value="GET" />
<xsd:enumeration value="POST" />
<xsd:enumeration value="PUT" />
<xsd:enumeration value="DELETE" />
<xsd:enumeration value="HEAD" />
<xsd:enumeration value="OPTIONS" />
<xsd:enumeration value="TRACE" />
</xsd:restriction>
</xsd:simpleContent>
</xsd:complexType>
改变为:
代码示例 A-6 Servlet 2.5 http-methodType schema
<xsd:simpleType name="http-methodType">
<xsd:annotation>
<xsd:documentation>
A HTTP method type as defined in HTTP 1.1 section 2.2.
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:pattern value="[\p{L}-[\p{Cc}\p{Z}]]+"/>
</xsd:restriction>
</xsd:simpleType>
http-method元素现在需要被当作是HTTP 1.1规范第2.2节描述的那样。
A.8.6 最低J2SE要求
Servlet 2.5 容器现在需要的最低Java版本是J2SE5.0。
1.2节,“什么是Servlet容器?” 进行了更新来反映此要求。
A.8.7 注解和资源注入
兼容Java EE技术的容器需要在Servlet、Filter和Listener上进行注解和资源注入。15.5节,“注解和资源注入”进一步描述了注解和资源注入的细节。
A.8.8 移除了SRV.9.9(“错误处理”)要求
10.9.1节,“请求属性”定义了如下要求:
如果错误处理位于一个servlet或JSP页面:
[...]
响应的setStatus方法被禁用,且如果调用则被忽略。
[...]
JSP 2.1 EG提出了删除上述要求,以允许JSP错误页面更新响应状态。
A.8.9 阐明HttpServletRequest.isRequestedSessionIdValid()
API阐明了更好的描述客户端没有指定一个session id时会发生什么。API文档进行了更新指定什么时候返回false。API文档当前的描述:
如果客户端没有指定任何session ID,返回false。
A.8.10 阐明SRV.5.5 (“结束响应对象”)
第5.6节,“结束响应对象”的行为,响应的内容长度通过response.setHeader("Content-Length", "0")设置为0,则任何随后的setHeader()调用被忽略。
第5.6节,“结束响应对象”进行了更新以允许所有header被设置,通过改变:
“响应的setContentLength方法指定了内容量,且已经写入到响应”
为如下:
“响应的setContentLength方法指定了内容量大于零,且已经写入到响应”
A.8.11 阐明ServletRequest.setCharacterEncoding()
API进行了更新以描述如果此方法在getReader()方法调用之后调用的行为。如果getReader()已调用则此方法将无任何效果。
A.8.12 Java企业版要求
第15章,“其他规范相关的要求”详细介绍了JavaEE容器的所有要求。先前的要求被穿插在每个章节中。
A.8.13 新增了Servlet 2.4MR 更新的变更历史
添加了自Servlet 2.4 Maintenance Review的变更。这些变更包括语法和排版的修正。
A.8.14 阐明同步访问Session对象
第7.7.1节,“线程问题”进行了更新以阐明将同步地访问session对象。
A.9 自Servlet 2.3以后的变更
■ 响应添加了可选的“X-Powered-By”header (5.2)
■ 明确“重叠的约束 (12.8.1, 12.8.2)
■ 添加明确在web应用部署时的处理顺序章节 (9.12)
■ 明确安全模型也应用到过滤器 (12.2)
■ 当FORM验证失败且因为HTTP/1.1中没有合适的状态码时,状态码从401改变为200 (12.5.3)
■ 明确包装对象 (6.2.2)
■ 明确覆盖平台类 (9.7.2)
■ 明确欢迎文件 (9.10)
■ 明确国际化 — setLocale、setContentType和setCharacterEncoding之间的关系 (5.4, 14.2.22)
■ 明确ServletRequestListener和ServletRequestAttributeListener描述(14.2.18, 14.2.20)
■ 添加HttpSessionActivationListener和HttpSessionBindingListener到表10-1
■ 把单词“auth constraint”改为“authorization constraint” (12.8)
■ 添加“Since”标签到javadoc中新添加的方法 (14.2.16, 14.2.22)
■ 修复schema中的<session-timeout>数据类型为xsdIntegerType (13.3)
■ 阐明什么时候监听器抛出未处理的异常(10.6)
■ 阐明“共享库” (9.7.1)
■ 阐明容器的扩展机制 (9.7.1, 第三段)
■ 移除HttpSession.logout方法。便携的身份验证机制将在此规范的下一个版本中解决,且logout也将在该范围进行讨论 (12.10)
■ 现在建议,而不是要求,请求和响应对象的引用不应该传递给其他线程的对象— 基于JSR-168的要求。当应用创建的线程使用容器管理的对象时添加警告(2.3.3.3)
■ 现在建议,分派应该发生在原始请求所在的同一个JVM的同一个线程中 —基于JSR-168的要求 (8.2)
■ 阐明“wrap” (6.2.2)
■ 阐明处理用于映射的路径参数(11.1)
■ 在HTTPServlet.doGet为中添加了关于“HTTP chunk”的描述 (15.1.2)
■ J2SE 1.3是构建servlet容器的基础Java平台的最低版本 (1.2)
■ 阐明ServletResponse.setBufferSize方法 (5.1)
■ 阐明ServletRequest.getServerName和getServerPort (14.2.16.1)
■ 阐明国际化 (5.4, 14.2.22)
■ 阐明欢迎文件的重定向 (9.10)
■ 阐明ServletContextListener.contextInitialized (14.2.12.1)
■ 阐明HttpServletRequest.getRequestedSessionId — 明确它返回客户端指定的session ID (15.1.3.2)
■ 阐明用于扩展的类加载器 —在同一个JVM中用于所有web应用的类加载器必须是同一个 (9.7.1)
■ 阐明什么时候ServletRequestListener抛出一个未处理的异常的情况(10.6, 14.2.20)
■ 阐明ServletRequestListener的作用域 (14.2.20)
■ 添加了关于什么时候容器有一个缓存机制的情况的描述(1.2)
■ JavaEE容器需要使用schema验证部署描述符 (13.2)
■ <web-app>下的子元素可以是任意顺序 (13.2)
■ 容器的拒绝web应用的一个例子被移除,由于和SRV.11.1矛盾 (9.5)
■ url-patternType从j2ee:string改变为xsd:string (13)
■ 部署描述符中的<web-app>下的子元素可以是任意顺序 (13.2)
■ 当部署描述符文件包含一个非法字符或多个<session-config>、<jsp-config>或<login-config>元素时,容器必须使用一个描述性错误消息通知开发人员(13)
■ 移除了部署描述的可扩展性 (13)
■ 添加SRV.1.6章节 — 描述了此规范与之前版本的兼容性问题 (1.6)
■ 在RequestDispatcher.forward 中添加了新的属性 (8.4.2)
■ 在ServletRequest接口和ServletRequestWrapper中新的方法 (14.2.16.1)
■ 作废了SingleThreadModel接口 (2.2.1, 2.3.3.1, 14.2.24)
■ 方法ServletRequestEvent.getRequest改为ServletRequestEvent.getServletRequest (14.2.19.2)
■ 阐明“request”访问WEB-INF目录 (9.5)
■ 阐明ServletRequest.setAttribute行为— 在“如果传入的value是null”的情况下把“value”改为“object” (14.2.16.1)
■ 修正了此规范与HttpServletRequest.getServletPath之间的不一致— 返回值以“/”开始 (15.1.3.2)
■ 修正了此规范与HttpServletRequest.getPathInfo之间的不一致— 返回值以“/”开始 (15.1.3.2)
■ 修正了此规范与HttpServletRequest.getPathTranslated 之间的不一致— 添加什么时候容器不能翻译路径的情况(15.1.3.2)
■ 允许HttpServletRequest.getAuthType不仅返回预定义的四个身份认证方案,也可以返回容器特定的方案(15.1.3.2)
■ HttpSessionListener.sessionDestroyed行为改变为在session失效之前触发 (15.1.14.1)
■ 修正错误状态码403为403 (9.5,9.6)
■ 元素“taglib”应该是“jsp-config” (13.2)
■ 修正JSP规范版本号为2.0
■ 修正错误的排版(5.5, 6.2.5, 12.8.3, 12.9)
■ 现在需要HTTP/1.1 (1.2)
■ <web-resource-collection>中的<url-pattern>是必须的 (13.4)
■ 阐明分布式环境中的IllegalArgumentException (7.7.2)
■ 阐明错误页面处理 (9.9.1, 9.9.2, 9.9.3, 6.2.5)
■ 阐明安全约束,尤其在重叠约束的情况(12.8)
■ 阐明什么时候<session-timeout>不指定的情况 (13.4)
■ 阐明什么时候资源是永久性的不可用的情况 (2.3.3.2)
■ 在枚举列表中添加缺失的getParameterMap() (4.1)
■ 阐明当访问/WEB-INF/resource时的状态码 (9.5)
■ 阐明当访问/META-INF/resource时的状态码 (9.5)
■ 在部署描述符中把xsd:string改为j2ee:string (13.4)
■ 部署描述符的可扩展性 (SRV.13)
■ 部署描述符的XML Schema定义 (SRV.13)
■ 请求监听器 (SRV.10和API改变)
新的API:ServletRequestListener、ServletRequestAttributeListener和相关的事件类
■ 在Request Dispatcher的情况下能够使用Filter (6.2.5)
■ 必需的类加载器扩展机制 (9.7.1)
■ Listener异常处理(10.6)
■ 阐明 Listener顺序 vs. servlet init()/destroy() (ServletContextListener javadoc 改变)
■ Servlet映射到WEB-INF/ 响应处理 (9.5)
■ Request dispatcher / 路径匹配规则 (8.1)
■ 欢迎文件可以是servlet (9.10)
■ 国际化增强(5.4, 14,2,22, 15.1.5)
■ 添加了SC_FOUND(302) (15.1.5)
■ 在getRequestDispatcher()中的“相对路径”必须相当于当前servlet (8.1)
■ XML例子中的Bug修复(13.7.2)
■ 阐明getResource访问“仅到资源”(3.5)
■ 阐明getServerName()和getServerPort() 中的SERVER_NAME和SERVER_PORT (14.2.16)
■ 阐明:“run-as”身份必须应用到所有来自servlet包括init()和destroy()的调用(12.7)
■ 添加了登录/退出的描述和方法(12.10, 15.1.7)