在处理一个耗时的请求时,我们应该把这个耗时业务的处理放到一个子线程中去处理,让处理我们请求的Tomcat线程能快速的回到池中,让tomca能处理更多的请求,提升系统的吞吐量。
Spring MVC 对 Servlet3.0中的异步请求处理做了集成封装。
1、在Controller中我们可以通过返回DeferredResult 和 Callable来实现异步的支持(单个异步值)。
2、Controller可以流式传输多个值(多个异步值),包括sse和raw data
3、略
接下来我们一个一个的说:
- 返回DeferredResult
代码:
![ac40864aef6705b26f3278a6373a108a.png](https://i-blog.csdnimg.cn/blog_migrate/8e81e5f6f078ce6f4fb05830b37afb39.jpeg)
返回DeferredResult
setResult 用来设置我们异步任务执行完后的返回结果
setErrorResult 当有错误发生时设置错误的信息,也可以是一个exception对象,当是一个异常对象时,可以被@ExceptionHandler捕获处理。
DeferredResult.onCompletion 当异步请求执行完成时执行,这里的执行线程是我们的容器线程(Tomcat线程)。
执行结果:
![ea6b7ed0cc61bf0afbc91b77d7d81e1f.png](https://i-blog.csdnimg.cn/blog_migrate/08efd9f890ce65626cd08be66425dce9.jpeg)
运行结果
代码执行的开始和结束都打印了当前线程及时间。
在代码中我们模拟了一个耗时的任务执行5秒后我们设置返回的结果。通过控制台我们发现处理我们请求的Tomcat线程立即就返回了(0ms),等到5秒后我们的页面输出了def.setResult("DeferredResult...") ;设置的值。tomcat线程可以处理更多的请求,tomcat吞吐量瞬间提高了。
这里是每来一个请求创建一个线程,实际肯定是不能这么做的,应该使用线程池来做,不能无止境的创建线程。
- 返回Callable
代码:
![51ba3c740919b90805954659ab4c98e4.png](https://i-blog.csdnimg.cn/blog_migrate/6c9da308c0321856aa3e0a2d46638f32.jpeg)
结果:
![24af96f12ab04bdb8abe151241d4da85.png](https://i-blog.csdnimg.cn/blog_migrate/8b48db9080cc3e61098c58fc13c423c6.jpeg)
1毫秒后tomcat返回了。
DeferredResult与Callable的区别是,DeferredResult的结果或是发生的异常都是由DeferredResult设置产生,Callable则是通过返回值或者是Callable在执行时的自身产生异常。
以上为单一异步的异步请求。
如果想更进一步的对异步请求进行相关的处理我们可以通用异步拦截器:
示例:
![05629e8ddf1d58a57d9dc722703149cb.png](https://i-blog.csdnimg.cn/blog_migrate/514c8405cd160c608c2586f78d48121f.jpeg)
![8a6d552aeaa22af8f4cfcc7fc4180359.png](https://i-blog.csdnimg.cn/blog_migrate/bb06e849fcab2a59d551b5181976071a.jpeg)
以上是DeferredResult,Callable通过实现CallableProcessingInterceptor ,这里不再列出了。
- HTTP Streaming可以用来处理多个异步任务
1、Controller 返回 ResponseBodyEmitter
代码:
![36c422e86d4ed519fd0faebe01cf81f9.png](https://i-blog.csdnimg.cn/blog_migrate/adff5348b7b0c8fe77b9415c8e57c4ae.jpeg)
这里我们模拟了2个异步耗时任务,使用了原子操作类来计数,当都进行输出了后执行complete方法,只有调用了complete才会将send中的内容输出到客户端。
2、SseEmitter(server sent event)
SseEmitter是ResponseBodyEmitter的子类使用方法完全一致,唯一不同的是ResponseBodyEmitter是所有的数据一次性发送到客户端。SseEmitter是每一个异步任务执行完了后就发送到了客户端。
注:SSE 通信是单向的,也就是说数据只能通过服务器向客户端推送。
3、RAW DATA
数据以流的形式直接输出
代码:
![cb93a60778954185c192fcc48bc736ee.png](https://i-blog.csdnimg.cn/blog_migrate/e44b65ebed44083e2e4f408a789fa326.jpeg)
我们通过该种异步方式进行文件的下载。
以上是spring mvc支持的所有异步处理方式,如有错误,请指正谢谢。
其他文章:
Spring MVC 异常处理方式
SpringMVC参数统一验证方法
Spring Cloud Sentinel 熔断降级
Spring Cloud Sentinel 基础配置
Spring Cloud Sentinel 热点参数限流
Spring Cloud Sentinel整合Feign