在以前的Servlet规范化,如果Servlet作为控制器调用了一个耗时的业务方法,那么必须等到业务方法完全返回之后才能生成响应,这将使用Servlet对业务方法的调用变成一种阻塞式的调用,因此效率比较低。
Servlet3.0规范引入了异步处理来解决这个问题,异步处理允许Servlet重新发起一条新线程去调用 耗时业务方法,这样就可以避免等待。
Servlet3.0的异步处理是通过AsyncContext类来处理的,Servlet可通过ServletRequest的如下两个方法开启异步调用,创建AsyncContext对象:
- AsyncContext startAsync()
- AsyncContext startAsync(ServletRequest,ServletResponse)
在ServletRequest中增加的有关异步相关方法分为:
- startAsync(servletRequest, servletResponse) 传入指定的request和response对象,便于在AsyncContext中重复使用(这样被Filter、Servlet包装过的请求、相应对象才会在异步的环境下继续生效)。
- startAsync()
调用HttpServletRequest.startAsync(),将servlet置于异步模式,返回AsyncContext对象,且流将不在从Servlet.service()返回时提交。 - isAsyncSupported() 和 isAsyncStarted()
辅助性的方法,用于判断当前请求是否支持异步或者异步已经开始。 - getAsyncContext()
需要在异步启动之后才能够访问,否则会报异常。 - AsyncContext.start()
启动请求 —— 将其指派给工作线程。
在AsyncContext中分发的方法有三个,不太容易区分:
- AsyncContext.dispatch()
若当前AsyncContext由ServletRequest.startAsync(ServletRequest, ServletResponse)方法启动,返回的地址可以通过HttpServletRequest.getRequestURI()得到。
否则,分发的地址则是当前URL request对象最后一次分发的地址。
虽有些拗口,两者分发的地址大部分情况下一致;但尽量使用带有参数的异步上下文启动器。
如本例中请求/asyncDispatch2Async?disUrl=self,执行dispatch()方法之后,自身会再次分发到自身,包括传递的参数。 - AsyncContext.dispatch(String path)
等同于ServletRequest.getRequestDispatcher(String),
算是一个快捷方法。
可以转向一个同步或异步的servlet,或者JSP,或其它资源地址等。
- AsyncContext.dispatch(ServletContext context, String path)
请求的地址将在给定的上下文里面(ServletContext),有有可能传入的上下文与当前站带你应用的上下文有所区别。