Servlet3规范提出异步请求,绝对是一巨大历史进步。之前各自应用服务器厂商纷纷推出自己的异步请求实现(或者称comet,或者服务器推送支持,或者长连接),诸如Tomcat6中的NIO连接协议支持,Jetty的continuations编程架构,SUN、IBM、BEA等自不用说,商业版的服务器对Comet的支持,自然走在开源应用服务器前面,各自为王,没有一个统一的编程模型,怎一个乱字了得。相关的comet框架也不少,诸如pushlet、DWR、cometd;最近很热HTML5也不甘寂寞,推出WebSocket,只是离现实较远。
总体来说,在JAVA世界,很乱!缺乏规范,没有统一的编程模型,会严重依赖特定服务器,或特定容器。
好在Servlet3具有了异步请求规范,各个应用服务器厂商只需要自行实现即可,这样编写符合规范的异步Servlet代码,不用担心移植了。
现在编写支持comet风格servlet,很简单:
在注解处标记上 asyncSupported = true;
final AsyncContext ac = request.startAsync();
这里设定简单应用环境:一个非常受欢迎博客系统,多人订阅,终端用户仅仅需要访问订阅页面,当后台有新的博客文章提交时,服务器会马上主动推送到客户端,新的内容自动显示在用户的屏幕上。整个过程中,用户仅仅需要打开一次页面(即订阅一次),后台当有新的内容时会主动展示用户浏览器上,不需要刷新什么。下面的示范使用到了iFrame,有关Comet Stream,会在以后展开。有关理论不会在本篇深入讨论,也会在以后讨论。
这个系统需要一个博文内容功能:
新的博文后台处理部分代码:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
MicBlog blog = new MicBlog();
blog.setAuthor("发布者");
blog.setId(System.currentTimeMillis());
blog.setContent(iso2UTF8(request.getParameter("content")));
blog.setPubDate(new Date());
// 放到博文队列里面去
NewBlogListener.BLOG_QUEUE.add(blog);
request.setAttribute("message", "博文发布成功!");
request.getRequestDispatcher("/WEB-INF/pages/write.jsp").forward(
request, response);
}
private static String iso2UTF8(String str){
try {
return new String(str.getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}