JSR-315发布了Servlet 3.0规范的公开预览版,同时在GlassFish代码分支上提供了参考实现。这次发布引发了人们对于专家组(ExpertGroup)为下一代Servlet API和整个JavaEE6平台做出的各种选择的争论。
Servlet API一直处于风口浪尖,从初期草稿开始,JSR315专家组致力于在类似便捷开发、插件性等领域完善和提高该规范,其***之一RajivMordani,这样说道:
便捷开发(EaseofDevelopment):在早期草案中,我们添加了一些注解,允许你像POJO一样写Servlet 。但是在专家组的若干次讨论和社区反馈之后,我们决定删除像@GET,@POST这样的方法层注解,保留doGet、doPos方法和扩展HttpServlet 类。但是,那些重命名以更有效使用的最顶层注解仍然存在。@WebServlet 用于声明一个Servlet ,@Servlet Filter声明过滤器,@WebServlet Context Listener定义Servlet Context Listener。除了这些注解,像@Resource这种自Servlet 2.5就一直支持的注解则保持不变。
可插入性:构建于Servlet 之上的Web框架在开发人员中很受欢迎,其中很多人提出了各种各样的问题。为了更好地支持框架便于开发人员编写web应用,我们在Servlet 3.0规范中添加一些方式以帮助开发人员根据自身情况使用和管理框架。
异步处理:这是我们在Servlet 3.0规范中变化***的部分。在早期草案中,我们暂停、重新开始、确定了我们定义的语义。但是,在这之后,专家组对于如何解决异步处理的各种用例进行了大量的讨论,规范中做出的修改现在也可以解决各种问题。
RoyVanRijn表达了他对于早期草案中出现的一些特性的担忧:
我更倾向于完全不使用针对GET/POST方法的注解,但是我发现JavaEE6规范提倡使用类似的注解,JSR-315的编写者“别无选择”(糟糕的借口)。我在本文中表达的观点已经发给了JSR组织,但至今没有回应。
我也找不到一名成员给出原因、解释、澄清等等。最近JavaEE6规范发布公开预览版,其中包含了对Servlet 3.0规范的引用,所以这会成为JavaEE6的一部分。但是我恳请他们花时间重新考虑关于注解的决定。
随着规范公开预览版的发布,来自Webtide的GregWilkins认为该规范非常糟糕,是不和谐的专家组和有缺陷的流程的产物。他的主要观点包括:
它代表了API设计上的一次思想实验,不关注实现的复杂性、试用可行性和社区反馈。
要求测试实现的请求被拒绝了。
没有公开的或者合理的机制来收集来自社区的需求和宝贵的社区咨询。
一些模糊的需求(比如包装的异步请求)在较晚时候包含进来,没有用例和用户需求。
写的非常糟糕,就像大多数JCP文档一样。
一些新的特性引起了安全隐患,并可能导致部署缓慢。
异步Servlet 的建议被改变了,与早期草案不同。最初的方法是JettyContinuations的结果,从2008年3月即可在Jetty-7pre-release中试用,已经在很多框架和应用中测试过,包括ometd、DWR、JSF和BlazeDS。
Greg总结说:
我相信在现在的预览版中有明显的错误,这些缺陷已经多的让人很容易就可以发现。当我从专家组收到关于这些问题的支持信息时,我无法确信规范***的合法身份,我可能因为过于严厉而无法得到帮助了。
Rajiv对Greg的答复中指出:
在GlassFish中有相关实现。
他从没看到过Greg的请求。
如果不喜欢新功能,可以禁止使用。
没有明显的证据表明部署会变慢。
异步Servlet 增加的方式更被社区所喜欢,他引用了专家组的邮件。
Rajiv也提到了来自RedHat的BillBurke写的一篇博文,其中他批评了Jetty6中的异步Servlet 实现。
随后,GregWilkins宣布他致力于Servlet 3.0异步Servlet 的一个实现,他在博客上列举了一些修正/扩展和与专家组的持续讨论。其中包括:
新的异步分发器类型(ASYNCDispatcherType),用于分发异步请求。
当请求分发时,isAsyncStarted()方法为false。
如果getReader()或者getOutputStream()已经被调用,则调用startAsync()或者startAsync(request.response)时会抛出IllegalStateException异常。这可以把异步处理器限制到简单的情况下。
如果通过startAsync(request,response)启动异步模式,在AsyncContext 上使用任何forward(...)方法都会有IllegalStateException异常。这避免了分发包装器的复杂,但允许异步处理器使用包装器。
forward(path)和forward(Context ,path)方法还没有实现。
代码可以从Jetty分支和Servlet -api分支中得到。
Grep谈到了异步Servlet 的事情:
虽然还需要更多测试,但是这个代码已经实现了基本的异步行为,不需要很复杂的重新分发请求或者前递方法。我相信这代表了3.0的合理折中方案。在我们从3.0的简单子集里获得经验之后,如果需要更多的特性,可以添加到3.1中。
【编辑推荐】