
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
昆明IT培训的老师这一期给大家讲Servlet3.0的异步。
servlet之前的操作同时同步的,就是按照这样的一个流程来走的:
1.请求根据一个路径路由到一个servlet中,
2.servlet获取一系列的参数
3.执行一系列的逻辑(花费时间所占的比重也更大)
4.返回结果
上面的问题出现在这一系列的操作都是同步的,所以这个请求必定是堵塞到所以任务都完成之后才返回的,
这样将会很浪费资源,因为线程堵塞在那里,仅仅是等待任务的完成。但是在servlet3.0之后,我们基本上可以
是这样做的
1.请求根据一个路径路由到一个servlet中,
2.将逻辑放入到异步队列中去
3.返回结果
4.异步队列处理任务,得出结果,返回给页面
而servet3.0对于异步的处理主要涉及的有两个特性,一个是新增的类AsyncContext,另外的一个就是asyncSupported属性
①如果我们想要让我们的servlet支持异步的话,那么asyncSupported这个属性是一定需要设置的,对于注解的类型来说,我们直接设置属性
1
@WebServlet(asyncSupported=true,urlPatterns={"/async"})
就可以了,对于老版本的配置问价来说,只需要在配置web.xml的servlet那里增加一个
<async-supported>true</async-supported>
还有一个就是对于动态的servlet,设置
dynamic.setAsyncSupported(true);
就可以了
②而对于AsyncContext需要记住的东西还是蛮多的,但是它主要的是保留了请求和相应的引用,在前面提到的返回结果之后的操作就是通过在异步环境下,对这两个引用进行操作。
要获取这个就需要使用request在3.0之后增加的方法,startAsync(..),这个方法就是返回一个AsyncContext实体对象,这里包含了request和response的引用,至于我们异步的处理方式,就有很多种了,我们可以直接定义一个工作队列,异步的方式一个个的进行处理,又或者是直接使用AsyncContext.start(Runnable)方法启动一个新的线程去进行处理逻辑
AsyncContext主要的方法:
getRequest()获得请求即request,我们可以在异步的环境像在service中使用一样
getReponse()和上面差不多一个意思
hasOriginalRequestAndResponse()这个方法表示的是我们使用的AsyncContext是使用原始的请求获取的,还是通过封装过的请求和相应创建的
简单的讲就是原始的类型表示的是调用startAsync()。但是封装的就是startAsync(ServletRequest, ServletResponse)或者其他类型啦,
dispatch()方法,这个方法有有好几个重载,表示的是转发,和req.getRequestDispatcher()有点类似,但是比较丰富
如果使用的是startAsync(ServletRequest, ServletResponse)初始化AsyncContext,且传入的请求是HttpServletRequest的一个实例,则使用HttpServletRequest.getRequestURI()返回的URI进行分派。否则分派的是容器最后分派的请求URI。
下面是代码:
//请求到/url/A
AsyncContext ac = request.startAsync();
...
ac.dispatch(); //异步分派到/url/A
//请求到/url/A
//转发到/url/B
request.getRequestDispatcher(“/url/B”).forward(request, response);
//从FORWARD的目标内启动异步操作
AsyncContext ac = request.startAsync();
ac.dispatch(); //异步分派到/url/A
//请求到/url/A
//转发到/url/B
request.getRequestDispatcher(“/url/B”).forward(request, response);
//从FORWARD的目标内启动异步操作
AsyncContext ac = request.startAsync(request, response);
ac.dispatch(); //异步分派到/url/B
dispatch(String path)这个方法就是转发到指定的url上去
complete():在我们使用了request.startAsync(..)获得AsyncContext之后,在完成异步操作以后,需要调用这个方法结束异步的操作。如果请求分派到一个不支持异步操作的Servlet,或者由AsyncContext.dispatch调用的目标servlet之后没有调用complete,则complete方法会由容器调用。但是对于比合法操作来说,比如没有调用startAsync放方法,却代用complete() ,那么就会抛出IllegalStateException的异常,同时在调用complete()之前,调用dispath()方法是不起作用的,当然了,因为这个时候异步还没结束嘛,当然不会又什么作用了。
setTimeOut(..)设置超时的时间表示的是异步处理的最大时间,如果是一个负数的话,那么表示永远不会超时
start(Runnable run) Runnable表示的就是异步处理的任务。我们在做的时候会AsyncContext 带进去因为所以的操作都需要依靠他呢
addListener(AsyncListener listener);增加监听器 就是监听AsyncContext各种状态发现变化的。