美文网首页SpringBoot精选Spring BootSpring-Boot
Spring MVC异步处理-DeferedResult使用

Spring MVC异步处理-DeferedResult使用

作者: _挑灯看剑_ | 来源:发表于2016-11-23 17:02 被阅读0次

    DeferedResult处理流程


    • Spring mvc的控制层接收用户的请求之后,如果要采用异步处理,那么就要返回DeferedResult<>泛型对象。在调用完控制层之后,立即回返回DeferedResult对象,此时驱动控制层的容器主线程,可以处理更多的请求。
    • 可以将DeferedResult对象作为真实响应数据的代理,而真实的数据是该对象的成员变量result,它可以是String类型,或者ModelAndView类型等。
    • 容器主线程,会调用DeferedResult对象的getResult方法,然后响应到客户端。在业务没有处理完毕时,result真实数据还没有形成,那么容器主线程会发生阻塞。
    • 业务处理完毕之后,要执行setResult方法,将真实的响应数据赋值到DeferedResult对象中。此时,异步线程会唤醒容器主线程。那么容器主线程会继续执行getResult方法,将真实数据响应到客户端。
    DeferedResult对象.png

    也可以有这样的应用场景。在Spring Mvc的控制层中,只要有一个用户请求便会实例化一个DeferedResult对象,然后返回该对象,进行响应客户端。只要DeferedResult对象不设置result响应的内容,则控制层的容器主线程在响应客户端上就会发生阻塞。因为SpringMVC只会实例化一个Controller对象,无论有多少个用户请求,在堆上只有一个Controller对象,因此可以添加一个成员变量List,将这些用户请求的DeferedResult对象存放到List中,然后启动一个定时线程扫描list,从而依次执行setResult方法,响应客户端。

    @Controller
    public class DeferedResultController {
    
    
        private ConcurrentLinkedDeque<DeferredResult<String>> deferredResults =
                new ConcurrentLinkedDeque<DeferredResult<String>>();
    
    
        @RequestMapping("/getResult")
        @ResponseBody
        public DeferredResult<String> getDeferredResultController(){
    
            //设置 5秒就会超时
            final DeferredResult<String> stringDeferredResult = new DeferredResult<String>(1000);
            
            //将请求加入到队列中
            deferredResults.add(stringDeferredResult);
    
            final String message = "{username:wangbinghua}";
    
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            executorService.submit(new Runnable() {
                @Override
                public void run() {
              
                    try {
                        Thread.sleep(1010);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    //业务处理
                    System.out.println("业务处理");
                    stringDeferredResult.setResult(message);
                }
            });
    
    
            //setResult完毕之后,调用该方法
            stringDeferredResult.onCompletion(new Runnable() {
                @Override
                public void run() {
                    System.out.println("异步调用完成");
                    //响应完毕之后,将请求从队列中去除掉
                    deferredResults.remove(stringDeferredResult);
                }
            });
    
            stringDeferredResult.onTimeout(new Runnable() {
                @Override
                public void run() {
                    System.out.println("业务处理超时");
                    stringDeferredResult.setResult("error:timeOut");
                }
            });
            return stringDeferredResult;
        }
    
        //开启线程定时扫描队列,响应客户端
        @Scheduled(fixedRate = 1000)
        public void scheduleResult(){
            System.out.println(new Date());
            for(int i = 0;i < deferredResults.size();i++){
                DeferredResult<String> deferredResult = deferredResults.getFirst();
                deferredResult.setResult("result:" + i);
            }
        }
    }
    

    DeferedResult 两个监听器(onCompletion & onTimeout)


    • 当DeferedResult对象调用setResult之后,响应完毕客户端,则直接调用onCompletion对应的方法。
    • 当业务处理相当耗时,则响应客户端超时,也会调用onCompletion对应的方法以及onTimeout方法。此时,响应客户端的内容为deferedResult.setErrorResult的内容,否则500错误。
    • 发生异常,调用onCompletion方法,此时,响应客户端的内容为deferedResult.setErrorResult的内容,否则500错误。
        @RequestMapping("/getResult")
        @ResponseBody
        public DeferredResult<String> getDeferredResultController(){
    
            //设置 5秒就会超时
            final DeferredResult<String> stringDeferredResult = new DeferredResult<String>(1000);
            deferredResults.add(stringDeferredResult);
    
            final String message = "{username:wangbinghua}";
    
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            executorService.submit(new Runnable() {
                @Override
                public void run() {
    
                    try {
                        Thread.sleep(1010);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    //业务处理
                    System.out.println("业务处理");
                    stringDeferredResult.setResult(message);
                }
            });
    
    
            //setResult完毕之后,调用该方法
            stringDeferredResult.onCompletion(new Runnable() {
                @Override
                public void run() {
                    System.out.println("异步调用完成");
                    deferredResults.remove(stringDeferredResult);
    
                }
            });
    
            stringDeferredResult.onTimeout(new Runnable() {
                @Override
                public void run() {
                    System.out.println("业务处理超时");
                    stringDeferredResult.setResult("error:timeOut");
                }
            });
            return stringDeferredResult;
        }
    

    WebAsyncTask对象使用实例


        @RequestMapping("/async")
        @ResponseBody
        public WebAsyncTask<String> asyncTask(){
    
            // 1000 为超时设置
            WebAsyncTask<String> webAsyncTask = new WebAsyncTask<String>(1000,new Callable<String>(){
    
                @Override
                public String call() throws Exception {
                    //业务逻辑处理
                    Thread.sleep(5000);
                    String message = "username:wangbinghua";
                    return message;
                }
            });
            webAsyncTask.onCompletion(new Runnable() {
                @Override
                public void run() {
                    System.out.println("调用完成");
                }
            });
    
            webAsyncTask.onTimeout(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println("业务处理超时");
                    return "<h1>Time Out</h1>";
                }
            });
    
            return webAsyncTask;
        }
    

    相关文章

      网友评论

        本文标题:Spring MVC异步处理-DeferedResult使用

        本文链接:https://www.haomeiwen.com/subject/elevpttx.html