一:任务
1.任务
使用Runnable异步处理Rest服务
使用DefaultResult异步处理Rest服务
异步处理的配置
2.原理图说明
二:Callable进行异步处理
1.程序
新建一个anysc的包
1 package com.cao.web.async; 2 3 import java.util.concurrent.Callable; 4 5 import org.slf4j.Logger; 6 import org.slf4j.LoggerFactory; 7 import org.springframework.web.bind.annotation.RequestMapping; 8 import org.springframework.web.bind.annotation.RestController; 9 10 @RestController 11 public class AsyncController { 12 private Logger logger=LoggerFactory.getLogger(getClass()); 13 14 @RequestMapping("/order") 15 public Callable<String> order() throws Exception { 16 logger.info("主线程开始"); 17 //业务逻辑放在副线程中 18 Callable<String> result=new Callable<String>() { 19 20 @Override 21 public String call() throws Exception { 22 logger.info("副线程开始"); 23 Thread.sleep(5000); 24 logger.info("副线程返回"); 25 return "success"; 26 } 27 28 }; 29 30 logger.info("主线程返回"); 31 32 return result; 33 } 34 35 }
2.效果
重点关注时间
三:使用DeferredResult
1.问题
方式一是有问题的,因为副线程是需要主线程调用起来的。
是写在主线程中的。
有些场景是不合适的。
线程间使用DeferredResult沟通起来。
2.场景如下:
3.程序
程序太多,有点复杂
控制器
1 package com.cao.web.async; 2 3 import java.util.concurrent.Callable; 4 5 import org.apache.commons.lang.RandomStringUtils; 6 import org.slf4j.Logger; 7 import org.slf4j.LoggerFactory; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.RestController; 11 import org.springframework.web.context.request.async.DeferredResult; 12 13 @RestController 14 public class AsyncController { 15 private Logger logger=LoggerFactory.getLogger(getClass()); 16 @Autowired 17 private Queue queue; 18 19 @Autowired 20 private DeferredResultHolder deferredResultHolder; 21 22 /** 23 * 主要是验证Callable 24 * @return 25 * @throws Exception 26 */ 27 @RequestMapping("/order") 28 public Callable<String> order() throws Exception { 29 logger.info("主线程开始"); 30 //业务逻辑放在副线程中 31 Callable<String> result=new Callable<String>() { 32 33 @Override 34 public String call() throws Exception { 35 logger.info("副线程开始"); 36 Thread.sleep(5000); 37 logger.info("副线程返回"); 38 return "success"; 39 } 40 41 }; 42 43 logger.info("主线程返回"); 44 45 return result; 46 } 47 /** 48 * 主要是验证 49 * @return 50 * @throws Exception 51 */ 52 @RequestMapping("/newOrder") 53 public DeferredResult<String> newOrder() throws Exception { 54 logger.info("主线程开始"); 55 // 56 String oderNumber=RandomStringUtils.randomNumeric(8); 57 queue.setPlaceOrder(oderNumber); 58 DeferredResult<String> result=new DeferredResult<>(); 59 deferredResultHolder.getMap().put(oderNumber, result); 60 logger.info("主线程返回"); 61 62 return result; 63 } 64 65 }
queue.java
1 package com.cao.web.async; 2 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 import org.springframework.stereotype.Component; 6 7 @Component 8 public class Queue { 9 private String placeOrder; 10 private String completeOrder; 11 12 private Logger logger=LoggerFactory.getLogger(getClass()); 13 14 public String getPlaceOrder() { 15 return placeOrder; 16 } 17 public void setPlaceOrder(String placeOrder) throws Exception { 18 new Thread(() -> { 19 logger.info("接到下单请求"); 20 try { 21 Thread.sleep(2000); 22 } catch (InterruptedException e) { 23 e.printStackTrace(); 24 } 25 // 表示处理完成,应用2将结果返回给了completeOrder 26 this.completeOrder = placeOrder; 27 logger.info("下单请求处理完毕" + placeOrder); 28 } 29 30 ).start(); 31 32 } 33 public String getCompleteOrder() { 34 return completeOrder; 35 } 36 public void setCompleteOrder(String completeOrder) { 37 this.completeOrder = completeOrder; 38 } 39 40 }
deferredResultHolder.java
1 package com.cao.web.async; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import org.springframework.stereotype.Component; 7 import org.springframework.web.context.request.async.DeferredResult; 8 9 @Component 10 public class DeferredResultHolder { 11 //一个是订单号,一个是订单号的处理结果 12 private Map<String,DeferredResult<String>> map=new HashMap<>(); 13 public Map<String,DeferredResult<String>> getMap(){ 14 return map; 15 } 16 public void setMap(Map<String,DeferredResult<String>> map) { 17 this.map=map; 18 } 19 }
QueueListener.java
1 package com.cao.web.async; 2 3 import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.log; 4 5 import org.apache.commons.lang.StringUtils; 6 import org.slf4j.Logger; 7 import org.slf4j.LoggerFactory; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.context.ApplicationListener; 10 import org.springframework.context.event.ContextRefreshedEvent; 11 import org.springframework.stereotype.Component; 12 13 @Component 14 public class QueueListener implements ApplicationListener<ContextRefreshedEvent>{ 15 @Autowired 16 private Queue queue; 17 18 @Autowired 19 private DeferredResultHolder deferredResultHolder; 20 21 private Logger logger=LoggerFactory.getLogger(getClass()); 22 23 @Override 24 public void onApplicationEvent(ContextRefreshedEvent event) { 25 new Thread(() -> { 26 while (true) { 27 if (StringUtils.isNotBlank(queue.getCompleteOrder())) { 28 String orderNumber = queue.getCompleteOrder(); 29 logger.info("返回订单处理结果" + orderNumber); 30 deferredResultHolder.getMap().get(orderNumber).setResult("place order success"); 31 queue.setCompleteOrder(null); 32 } else { 33 try { 34 Thread.sleep(100); 35 } catch (InterruptedException e) { 36 // TODO Auto-generated catch block 37 e.printStackTrace(); 38 } 39 } 40 } 41 }).start(); 42 43 44 } 45 46 47 }
4.效果
前端效果
控制台效果
三:异步线程的配置
1.说明
对于拦截器,与同步的拦截器不一样,仍然需要配置、
2.主要配置