Java中实现Comet风格的Web应用 (四)

2014-11-24 01:34:34 · 作者: · 浏览: 2

  request.setAttribute("org.apache.tomcat.comet", Boolean.TRUE);

  request.setAttribute("org.apache.tomcat.comet.timeout", TIMEOUT);

  messageSender.setConnection(response);

  Weatherman weatherman = new Weatherman(95118, 32408);

  new Thread(weatherman).start();

  }

  public void end(HttpServletRequest request, HttpServletResponse response)

  throws IOException, ServletException {

  synchronized (request) {

  request.removeAttribute("org.apache.tomcat.comet");

  Continuation continuation = ContinuationSupport.getContinuation

  (request, request);

  if (continuation.isPending()) {

  continuation.resume();

  }

  }

  }

  public void error(HttpServletRequest request, HttpServletResponse response)

  throws IOException, ServletException {

  end(request, response);

  }

  public boolean read(HttpServletRequest request, HttpServletResponse response)

  throws IOException, ServletException {

  throw new UnsupportedOperationException();

  }

  @Override

  protected void service(HttpServletRequest request, HttpServletResponse response)

  throws IOException, ServletException {

  synchronized (request) {

  Continuation continuation = ContinuationSupport.getContinuation

  (request, request);

  if (!continuation.isPending()) {

  begin(request, response);

  }

  Integer timeout = (Integer) request.getAttribute

  ("org.apache.tomcat.comet.timeout");

  boolean resumed = continuation.suspend(timeout == null   10000 :

  timeout.intValue());

  if (!resumed) {

  error(request, response);

  }

  }

  }

  public void setTimeout(HttpServletRequest request, HttpServletResponse response,

  int timeout) throws IOException, ServletException,

  UnsupportedOperationException {

  request.setAttribute("org.apache.tomcat.comet.timeout", new Integer(timeout));

  }

  }

  这里最需要注意的是,该结构与Tomcat 版本的代码非常类似。begin、read、end 和error 方法都与Tomcat 中相同的事件匹配。该Servlet 的service 方法被覆盖为在请求第一次进入时创建一个continuation 并暂停该请求,直到超时时间已到,或者发生导致它重新开始的事件。上面没有显示init 和destroy 方法,因为它们与Tomcat 版本是一样的。该servlet 使用与Tomcat 相同的MessageSender。因此不需要修改。注意begin 方法如何创建Weatherman 实例。对这个类的使用与Tomcat 版本中也是完全相同的。甚至客户机代码也是一样的。只有servlet 有更改。虽然servlet 的变化比较大,但是与Tomcat 中的事件模型仍是一一对应的。

  希望这足以鼓舞人心。虽然完全相同的代码不能同时在Tomcat 和Jetty 中运行,但是它是非常相似的。当然,JavaEE 吸引人的一点是可移植性。大多数在Tomcat 中运行的代码,无需修改就可以在Jetty 中运行,反之亦然。因此,毫不奇怪,下一个版本的Java Servlet 规范包括异步请求处理(即Comet 背后的底层技术)的标准化。 我们来看看这个规范:Servlet 3.0 规范。

  Servlet 3.0 规范

  在此,我们不深究Servlet 3.0 规范的全部细节,只看看Comet servlet 如果在Servlet 3.0 容器中运行,可能会是什么样子。注意 “可能” 二字。该规范已经发布公共预览版,但在撰写本文之际,还没有最终版。因此,清单7 显示的是遵从公共预览规范的一个实现。

  清单7. Servlet 3.0 Comet

  @WebServlet(asyncSupported=true, asyncTimeout=5000)

  public class WeatherServlet extends HttpServlet {

  private MessageSender messageSender;

  // init and destroy are the same as other

  @Override

  protected void doGet(HttpServletRequest request, HttpServletResponse response)

  throws ServletException, IOException {

  AsyncContext async = request.startAsync(request, response);

  messageSender.setConnection(async);

  Weatherman weatherman = new Weatherman(95118, 32444);

  async.start(weatherman);;

  }

  }

  值得高兴的是,这个版本要简单得多。平心而论,如果不遵从Tomcat 的事件模型,在Jetty 中可以有类似的实现。这种事件模型似乎比较合理,很容易在Tomcat 以外的容器(例如Jetty)中实现,只是没有相关的标准。

  回头看看清单7,注意它的标注声明它支持异步处理,并设置了超时时间。startAsync 方法是HttpServletRequest 上的一个新方法,它返回新的javax.servlet.AsyncContext 类的一个实例。注意,MessageSender 现在传递AsynContext 的引用,而不是