2011年11月18日星期五

JavaEE_011:JavaEE6 新特性之三:Servlet3.0(3)

特性三:支持异步的Servlet和Filter
Servlet3.0之前不支持异步,也就是说从发送请求给Servlet,到得到响应,用户必须等待Servlet线程结束。
如果Servlet中某个调用比较耗时的话,其中占用的资源会一直得不到释放,如果并发用户数很高的话,可能会引起性能问题。
Servlet3.0支持异步,这样如果Servlet中某个操作比较耗时和耗资源的话,我们可以将其元注释为异步调用。
Servlet线程会启动另外一个线程来异步执行该方法,Servlet线程则返回至容器。
然后,等异步线程处理完毕之后,再生成响应。
也就是说,响应部分可以交给异步线程来实现,因为它也有指向ServletRequest和ServletResponse对象的引用。
在Servlet3.0中,除了Servlet,Filter也支持异步。

1. 配置方式
(1)使用web.xml配置,适用于Servlet和Filter,这里以Servlet为例。
<servlet>
<servlet-name>DemoServlet</servlet-name>
<servlet-class>footmark.servlet.Demo Servlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
(2)使用元注释配置,,适用于Servlet和Filter,这里以Filter为例。
@WebFilter(urlPatterns = "/demo",asyncSupported = true)
public class DemoFilter implements Filter{...}

2. 异步Servlet例子
@WebServlet(urlPatterns = "/demo", asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("进入Servlet的时间:" + new Date() + ".");
out.flush();

//在子线程中执行业务调用,并由其负责输出响应,主线程退出
AsyncContext ctx = req.startAsync();
new Thread(new Executor(ctx)).start();

out.println("结束Servlet的时间:" + new Date() + ".");
out.flush();
}
}

public class Executor implements Runnable {
private AsyncContext ctx = null;
public Executor(AsyncContext ctx){
this.ctx = ctx;
}

public void run(){
try {
//等待十秒钟,以模拟业务方法的执行
Thread.sleep(10000);
PrintWriter out = ctx.getResponse().getWriter();
out.println("业务处理完毕的时间:" + new Date() + ".");
out.flush();
ctx.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
}

3. 异步监听器
异步监听器用于监听异步处理的事件。
要实现异步监听器,首先需要开发一个Java类,实现接口AsyncListener。
然后注册该监听器,方法如下:
AsyncContext ctx = req.startAsync();
ctx.addListener(new AsyncListener() {
public void onComplete(AsyncEvent asyncEvent) throws IOException {
// 做一些清理工作或者其他
}
...
});
你可以监听四种事件:
(1)当异步线程开始时:调用 AsyncListener的onStartAsync(AsyncEvent event)方法。
(2)当异步线程出错时:调用 AsyncListener的onError(AsyncEvent event)方法。
(3)当异步线程超时时:调用 AsyncListener的onTimeout(AsyncEvent event)方法。
(4)当异步线程结束时:调用 AsyncListener的onComplete(AsyncEvent event)方法。

没有评论: