源自:http://blog.csdn.net/u013755987/article/details/62424001
springMVC中也整合了异步请求的特性,我们只需要配置好支持异步请求特性,然后结合Java自带的回调函数处理就可以实现简单的异步请求,但是这样的异步请求往往是不能满足我们需求的,所以最终我们还是会使用比较完整的异步请求接口,那就是spring的WebAsyncTask和DeferredResult。
首先需要添加配置项:
- springmvc-servlet.xml:
- <mvc:annotation-driven>
- <mvc:async-support default-timeout="5000"/>
- </mvc:annotation-driven>
-
- web.xml的所有servlet和filter
- <async-supported>true</async-supported>
使用Callable实现异步请求
- @RequestMapping("/response-body")
- public @ResponseBody Callable<String> callable() {
-
- Callable<String> asyncTask = new Callable<String>() {
- @Override
- public String call() throws Exception {
- Thread.sleep(4000);
- return "Callableresult";
- }
- };
- System.out.println("已交给服务线程处理");
- return asyncTask;
- }
这种方法可以实现异步请求,但是没有设置超时时间和相关超时回调。只是客户端发起请求,服务端保证执行完成即可,然后将直接成功的结果返回给客户端,客户端根绝返回值判断是否需要发起另一个请求。
使用WebAsyncTask实现异步请求
- @RequestMapping("/response-body2")
- public @ResponseBody WebAsyncTask<String> webAsyncHandle() {
-
- Callable<String> asyncTask = new Callable<String>() {
- @Override
- public String call() throws Exception {
- Thread.sleep(10000);
- return "Callableresult";
- }
- };
- System.out.println("已交给服务线程处理");
- WebAsyncTask<String> webAsyncTask = new WebAsyncTask<String>(5000, asyncTask);
- webAsyncTask.onCompletion(new CompleteWork(webAsyncTask));
- webAsyncTask.onTimeout(timeOutCallBack());
- System.out.println("main over");
- return webAsyncTask;
- }
-
- public Callable<String> timeOutCallBack(){
-
- Callable<String> callback = new Callable<String>() {
- @Override
- public String call() throws Exception {
- System.out.println("我超时了");
- return "我超时了";
- }
- };
- return callback;
- }
-
-
- class CompleteWork<T> implements Runnable{
-
- private T t;
- public CompleteWork(T t){
- this.t = t;
- }
-
- @Override
- public void run() {
- if (t instanceof WebAsyncTask) {
- if (((WebAsyncTask) t).getTimeout() > 0) {
- System.out.println("WebAsyncTask:我执行完啦!");
- }
- }else if (t instanceof DeferredResult) {
- if(!((DeferredResult) t).isSetOrExpired()){
- System.out.println("DeferredResult:我执行完啦!");
- }
- }
- }
-
- }
这种方法通过使用spring的WebAsyncTask实现了异步请求,并且可以设置超时时间,以及超时和完成之后的回调函数。需要注意的是,超时之后也会回调onCompletion中设置方法。
使用DeferredResult实现异步请求
@RequestMapping("/response-body3")
@ResponseBody
public DeferredResult<String> quotes(HttpServletResponse response) {
DeferredResult<String> deferredResult = new DeferredResult<String>(5000);
dealInOtherThread(deferredResult);
return deferredResult;
}
public void dealInOtherThread(DeferredResult<String> deferredResult){
deferredResult.onTimeout(new TimeOutWork());
deferredResult.onCompletion(new CompleteWork(deferredResult));
new Thread(new work(deferredResult)).start();
System.out.println("main over");
}
class TimeOutWork implements Runnable{
private DeferredResult<String> deferredResult;
public TimeOutWork(DeferredResult<String> deferredResult){
this.deferredResult = deferredResult;
}
@Override
public void run() {
System.out.println("我超时啦!");
deferredResult.setErrorResult("我超时了");
}
}
这种方法跟上面的WebAsyncTask类似,超时之后也会调用onCompletion函数。所以我们需要在回调函数中增加超时的判断。上面的方法中DeferredResult可以通过isSetOrExpired()来判断,但是WebAsyncTask还不知道如何判断。还有一点就是DeferredResult是在设置deferredResult.setResult(…)的时候就响应客户端,而WebAsyncTask是直接return。