⒈使用Runnable异步处理Rest服务
1 /**
2 *使用Runnable异步处理Rest服务
3 * @return
4 */
5 @GetMapping("/order")
6 public Callable
7 logger.info("主线程开始");
8 System.out.println(Thread.currentThread().getId());
9 Callable
10 @Override
11 public String call() throws Exception {
12 logger.info("副线程开始");
13 Thread.sleep(1000);
14 System.out.println(Thread.currentThread().getId());
15 logger.info("副线程返回");
16 return "seccess";
17 }
18 };
19 logger.info("主线程返回");
20 return result;
21 }
Runnable的这种形式并不能满足所有的应用场景,使用Runnable异步处理的时候,副线程必须是由主线程调起的,在实际开发的过程中,有些场景是非常复杂的。
例如,如下场景:
我们可以使用DeferredResult来解决上面复杂的场景
⒉使用DeferredResult异步处理Rest服务
1.模拟队列
1 package cn.coreqi.security.async;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.springframework.stereotype.Component;
6
7 /**
8 * 用于模拟消息队列
9 */
10 @Component
11 public class MockQueue {
12
13 private String placeOrder; //代表下单的消息
14
15 private String completeOrder; //代表订单完成的消息
16
17 private Logger logger = LoggerFactory.getLogger(getClass());
18
19 public String getPlaceOrder() {
20 return placeOrder;
21 }
22
23 public void setPlaceOrder(String placeOrder){
24 new Thread(() -> {
25 logger.info("接到下单请求!" + placeOrder);
26 try {
27 Thread.sleep(1000);
28 } catch (InterruptedException e) {
29 e.printStackTrace();
30 }
31 this.completeOrder = placeOrder;
32 logger.info("下单请求处理完成!" + placeOrder);
33 }).start();
34 }
35
36 public String getCompleteOrder() {
37 return completeOrder;
38 }
39
40 public void setCompleteOrder(String completeOrder) {
41 this.completeOrder = completeOrder;
42 }
43 }
2.模拟结果
1 package cn.coreqi.security.async;
2
3 import org.springframework.stereotype.Component;
4 import org.springframework.web.context.request.async.DeferredResult;
5
6 import java.util.HashMap;
7 import java.util.Map;
8
9 @Component
10 public class DeferredResultHolder {
11
12 private Map
13
14 public Map
15 return map;
16 }
17
18 public void setMap(Map
19 this.map = map;
20 }
21 }
3.控制器处理
1 @Autowired
2 private MockQueue mockQueue;
3
4 @Autowired
5 private DeferredResultHolder deferredResultHolder;
6
7 /**
8 * 使用DeferredResult异步处理Rest服务
9 * @return
10 * @throws InterruptedException
11 */
12 @GetMapping("/order")
13 public DeferredResult
14 logger.info("主线程开始");
15 System.out.println(Thread.currentThread().getId());
16 String orderNumber = new Random().longs(8).toString(); //生成订单号
17 mockQueue.setPlaceOrder(orderNumber); //放入到消息队列里面
18 DeferredResult
19 deferredResultHolder.getMap().put(orderNumber,result);
20 return result;
21 }
4.监听结果并返回
1 package cn.coreqi.security.async;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.context.ApplicationListener;
7 import org.springframework.context.event.ContextRefreshedEvent;
8 import org.springframework.stereotype.Component;
9 import org.springframework.util.StringUtils;
10
11 @Component
12 public class QueueListener implements ApplicationListener
13 @Autowired
14 private MockQueue mockQueue; //模拟的队列
15 @Autowired
16 private DeferredResultHolder deferredResultHolder;
17
18 private Logger logger = LoggerFactory.getLogger(getClass());
19 @Override
20 public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
21 new Thread(() -> {
22 while (true){
23 if(StringUtils.hasText(mockQueue.getCompleteOrder())){
24 String oderNumber = mockQueue.getCompleteOrder(); //拿到订单号
25 logger.info("返回订单处理结果:" + oderNumber);
26 deferredResultHolder.getMap().get(oderNumber).setResult("place order success");
27 mockQueue.setCompleteOrder(null);
28 }else{
29 try {
30 Thread.sleep(100);
31 } catch (InterruptedException e) {
32 e.printStackTrace();
33 }
34 }
35 }
36 }).start();
37 }
38 }
⒊异步相关配置
1 package cn.coreqi.security.config;
2
3 import org.springframework.context.annotation.Configuration;
4 import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
6
7 @Configuration
8 public class WebConfig implements WebMvcConfigurer {
9
10 /**
11 * 配置异步支持
12 * @param configurer
13 */
14 @Override
15 public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
16 //configurer.registerCallableInterceptors(); //设置异步的拦截器
17 //configurer.registerDeferredResultInterceptors(); //设置异步的拦截器
18 //configurer.setDefaultTimeout(20000); //设置超时时间
19 //configurer.setTaskExecutor(); //默认情况下Spring用自己简单的异步线程池来处理,不会重用池里面的线程,
20 //而是每次调用时都会开启新的线程,可以自己设置一些可重用的线程池来替换
21 //Spring默认的简单异步线程池。
22 }
23 }