11.4 异步监听器
为支持Servlet
和过滤器配合执行异步操作,Servlet3.0
还增加了**AsyncListener
接口用于接收异步处理过程中发生事件的通知**。AsyncListener
接口定义了如下方法,
onStartAsync方法
当某些事件发生时调用:
1
| void onStartAsync(AsyncEvent event)
|
onComplete方法
在异步操作启动完毕后调用该方法。
1
| void onComplete(AsyncEvent event)
|
onError方法
在异步操作失败后调用该方法。
1
| void onError(AsyncEvent event)
|
onTimeout方法
1
| void onTimeout(AsyncEvent event)
|
获取相关的AsyncEvent
在异步操作超时后调用该方法,即当它未能在指定的超时时间内完成时。
所有四种方法可以分别通过它们的getAsyncContext
、getSuppliedRequest
和getSuppliedResponse
方法,从AsyncContext
、ServletRequest
、ServletResponse
中获取相关的AsyncEvent
。
实例
这里有一个例子,MyAsyncListener
类实现AsyncListener
接口,以便在异步操作事件发生时,它能够得到通知。请注意,和其他网络监听器不同,你不需要通过@WebListener
注解来实现。
MyAsyncListener.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package listener; import java.io.IOException; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener;
public class MyAsyncListener implements AsyncListener { @Override public void onComplete(AsyncEvent asyncEvent) throws IOException { System.out.println("onComplete"); } @Override public void onError(AsyncEvent asyncEvent) throws IOException { System.out.println("onError"); } @Override public void onStartAsync(AsyncEvent asyncEvent) throws IOException { System.out.println("onStartAsync"); } @Override public void onTimeout(AsyncEvent asyncEvent) throws IOException { System.out.println("onTimeout"); } }
|
由于AsyncListener
类不是用@WebListener
注解的,因此必须为AsyncContext
手动注册一个AsyncListener
监听器,用于接收所需要的事件。通过调用addListener
方法为AsyncContext
注册一个AsyncListener
监听器:
1
| void addListener(AsyncListener listener)
|
AsyncListenerServlet.java
AsyncListenerServlet
类是一个异步Servlet
,它利用监听器MyAsyncListener
获取事件通知。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package servlet; import java.io.IOException; import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import listener.MyAsyncListener; @WebServlet( name = "AsyncListenerServlet", urlPatterns ={"/asyncListener"}, asyncSupported = true ) public class AsyncListenerServlet extends HttpServlet { private static final long serialVersionUID = 62738L; @Override public void doGet(final HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException { final AsyncContext asyncContext = request.startAsync(); asyncContext.setTimeout(5000); asyncContext.addListener(new MyAsyncListener()); asyncContext.start(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) {} String greeting = "Hi from listener"; request.setAttribute("greeting", greeting); asyncContext.dispatch("/test.jsp"); } }); } }
|
test.jsp
1 2 3 4 5 6
| <!DOCTYPE HTML> <html> <body> ${greeting} </body> </html>
|
运行效果
你可以通过如下URL
调用Servlet
:
http://localhost:8080/app11a/asyncListener
等待3秒钟后,浏览器显示效果如下:
控制台输出:
这表明该异步Servlet结束了
模拟超时
现在修改sleep的时间,如下:
1 2 3 4
| try { Thread.sleep(6000); } catch (InterruptedException e) {}
|
6秒钟比超时时间5秒长,该异步Servlet将会超时.
浏览器显示效果:
控制台输出如下:
1 2 3 4
| onTimeout onComplete Exception in thread "http-nio-8080-exec-28" ......
|