SpringMVC与Servlet3.0异步处理(二)

我们之前 SpringMVC与Servlet3.0异步处理(一)中学习过Servlet的异步处理,那我们Spring基于Servlet肯定也有响应的处理方法,我们怎么进行异步处理呢,我们可以仿照SpringMVC官网的说明,进行处理
SpringMVC与Servlet3.0异步处理(二)_第1张图片
官网中给我们提供了两种方式,我们逐一来看,首先是利用Callable来实现

@Controller
public class TestController {
    @ResponseBody
    @RequestMapping("/test")
    public Callable<String> test(){
        System.out.println("请求开始..."+Thread.currentThread());
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("异步处理开始..."+Thread.currentThread());
                Thread.sleep(6666);
                System.out.println("异步处理结束..."+Thread.currentThread());
                return "success!!!";
            }
        };
        System.out.println("请求结束..."+Thread.currentThread());
        return callable;
    }
}

我们启动Tomcat,访问 http://localhost:8080/test ,然后等待 6-7 秒后
在这里插入图片描述
我们同样去查看其控制台
SpringMVC与Servlet3.0异步处理(二)_第2张图片
我们发现请求和Callable方法内的是有不同的两个线程进行处理的,我们除此之后还发现了,在我们之前实现的拦截器的preHandle方法被执行了两个,这是为什么呢?

The Callable produces a result and Spring MVC dispatches the request back to the Servlet container to resume processing.

我们从官网中找到这么一句话,发现它说 Callable 生成结果后Spring MVC会将请求送回servlet容器以恢复处理,也就是说我们请求会发现一次被拦截,然后我们Callable方法体内执行完成后,Spring MVC又会发送一次,然后又被拦截了。


除了上述的Callable的方法,我们官网还提供了第二种方式
SpringMVC与Servlet3.0异步处理(二)_第3张图片
我们就按照官网提示进行操作

public class TestQueue {
    public static final Queue<DeferredResult<String>> queue = new ConcurrentLinkedQueue<>();

    public static void save(DeferredResult<String> deferredResult){
        queue.add(deferredResult);
    }

    public static DeferredResult<String> get(){
        return queue.poll();
    }
}

我们新建了一个类,用队列专门来保存我们的 DeferredResult

@Controller
public class TestController {

    @ResponseBody
    @RequestMapping("/test")
    public DeferredResult<String> test(){
        System.out.println("请求开始..."+Thread.currentThread());

        DeferredResult<String> deferredResult = new DeferredResult<>();
        TestQueue.save(deferredResult);

        new Thread() {
            @Override
            public void run() {
                try {
                    System.out.println("异步处理开始..."+Thread.currentThread());
                    Thread.sleep(6666);

                    DeferredResult<String> stringDeferredResult = TestQueue.get();
                    stringDeferredResult.setResult("success!!!");
                    System.out.println("异步处理结束..."+Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        System.out.println("请求结束..."+Thread.currentThread());
        return deferredResult;
    }
}

然后我们再创建一个线程模拟我们进行它的业务操作

运行Tomcat,访问 http://localhost:8080/test ,发现等待6-7秒同样成功了
在这里插入图片描述
查看我们的控制台打印内容
SpringMVC与Servlet3.0异步处理(二)_第4张图片
同样发现是一个异步的,并且也是被拦截了两次。

上述我们在方法体内是直接new了一个新的线程,进行处理,我们还可以用另一个请求方法进行处理,可能就会更加的直观

@Controller
public class TestController {

    @ResponseBody
    @RequestMapping("/test")
    public DeferredResult<String> test(){
        System.out.println("请求开始..."+Thread.currentThread());

        DeferredResult<String> deferredResult = new DeferredResult<>();
        TestQueue.save(deferredResult);

        System.out.println("请求结束..."+Thread.currentThread());
        return deferredResult;
    }

    @ResponseBody
    @RequestMapping("/doSomething")
    public String doSomething(){
        try {
            System.out.println("异步处理开始..."+Thread.currentThread());
            Thread.sleep(6666);

            DeferredResult<String> stringDeferredResult = TestQueue.get();
            stringDeferredResult.setResult("success!!!");
            System.out.println("异步处理结束..."+Thread.currentThread());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "over";
    }
}

我们启动Tomcat后,访问 http://localhost:8080/test,发现会一直在等待,然后我们访问 http://localhost:8080/doSomething 6-7秒后,页面显示over,我们发现之前访问的页面也会显示success!!!

但是我们不想一直等待怎么办呢,我们也可以设置超时时间的,以及超时后返回的内容
在这里插入图片描述

你可能感兴趣的:(SpringMVC)