天天看点

springMVC整合异步请求特性

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();
            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();
        return "Callableresult";//超时之后不会执行返回操作,但是return之前的能够执行完成
    }
};
      System.out.println("已交给服务线程处理");
      WebAsyncTask<String> webAsyncTask = new WebAsyncTask<String>(, 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>();
      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。

继续阅读