聂永的博客

记录工作/学习的点点滴滴。

Servlet 3.0笔记之异步请求相关方法和AsyncContext转发等

在ServletRequest中增加的有关异步相关方法分为:
  1. startAsync(servletRequest, servletResponse) 传入指定的request和response对象,便于在AsyncContext中重复使用(这样被Filter、Servlet包装过的请求、相应对象才会在异步的环境下继续生效)。
  2. startAsync() 若request或者response被包装,将失去预期的效果。
  3. isAsyncSupported()isAsyncStarted()
    辅助性的方法,用于判断当前请求是否支持异步或者异步已经开始。
  4. getAsyncContext()
    需要在异步启动之后才能够访问,否则会报异常。
在AsyncContext中分发的方法有三个,不太容易区分:
  1. AsyncContext.dispatch()
    若当前AsyncContext由ServletRequest.startAsync(ServletRequest, ServletResponse)方法启动,返回的地址可以通过HttpServletRequest.getRequestURI()得到。
    否则,分发的地址则是当前URL request对象最后一次分发的地址。
    虽有些拗口,两者分发的地址大部分情况下一致;但尽量使用带有参数的异步上下文启动器。
    如本例中请求/asyncDispatch2Async?disUrl=self,执行dispatch()方法之后,自身会再次分发到自身,包括传递的参数。
  2. AsyncContext.dispatch(String path)
    等同于ServletRequest.getRequestDispatcher(String)算是一个快捷方法。
    可以转向一个同步或异步的servlet,或者JSP,或其它资源地址等。
  3. AsyncContext.dispatch(ServletContext context, String path)
    请求的地址将在给定的上下文里面(ServletContext),有有可能传入的上下文与当前站带你应用的上下文有所区别。
展示一个较为有趣、但没有多少实际意义的小示范:
/**
* 异步上下文的转向分发
*
* @author yongboy
* @date 2011-1-14
* @version 1.0
*/
@WebServlet(urlPatterns = { "/asyncDispatch2Async" }, asyncSupported = true)
public class AsyncContextDispatch2AsyncServlet extends HttpServlet {
private static final long serialVersionUID = 46172233331022236L;
private static final Log log = LogFactory
.getLog(AsyncContextDispatch2AsyncServlet.class);

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Cache-Control", "private");
response.setHeader("Pragma", "no-cache");
response.setHeader("Connection", "Keep-Alive");
response.setHeader("Proxy-Connection", "Keep-Alive");
response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();
out.println("

Start ...

");
out.flush();

if (!request.isAsyncSupported()) {
log.info("the servlet is not supported Async");
return;
}

request.startAsync(request, response);

if (request.isAsyncStarted()) {
AsyncContext asyncContext = request.getAsyncContext();
asyncContext.setTimeout(1L * 60L * 1000L);// 60sec

new CounterThread(asyncContext).start();
} else {
log.error("the ruquest is not AsyncStarted !");
}
}

private static class CounterThread extends Thread {
private AsyncContext asyncContext;

public CounterThread(AsyncContext asyncContext) {
this.asyncContext = asyncContext;
}

@Override
public void run() {
int interval = 1000 * 20; // 20sec

try {
log.info("now sleep 20s, just as do some big task ...");
Thread.sleep(interval);
log.info("now dispatch to another Async Servlet");

ServletRequest request = asyncContext.getRequest();

String disUrl = request.getParameter("disUrl");

if (StringUtils.isBlank(disUrl)) {
disUrl = "/demoAsyncLink";
}

if (disUrl.endsWith(".jsp")) {
request.setAttribute("dateStr", DateFormatUtils.format(
System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
}

log.info("disUrl is : " + disUrl);

// 将当前异步上下文所持有的request, response分发给Servlet容器
if (StringUtils.equals("self", disUrl)) {
// 将分发到自身,即当前异步请求地址
asyncContext.dispatch();
} else {
// 将分发到指定的路径
asyncContext.dispatch(disUrl);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
当前请求完成之后,将分发到下一个请求上面,若都是异步的Servlet,则很好的组成了异步Servlet请求链。
有趣的地方在于,异步上下文环境可以分发到下一个异步或同步的servlet、jsp、html等资源。若访问类似于如下地址,当前URL永远不会断开,又一个永动机,除非网络链接出错或者服务器关闭。
http://localhost/servlet3/asyncDispatch2Async?disUrl=self
一个视图:
image
上面的异步Servlet总是在不断的请求自我,成为了一个永动机;为disUrl传入要转发到的异步或同步的资源地址,组成一个链的模式,相当的简单轻松。

posted on 2011-01-17 21:07 nieyong 阅读(12103) 评论(0)  编辑  收藏 所属分类: Servlet3


只有注册用户登录后才能发表评论。


网站导航:
 

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

<2011年1月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

常用链接

留言簿(58)

随笔分类(130)

随笔档案(151)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜