一:任务

1.任务

  使用Runnable异步处理Rest服务

  使用DefaultResult异步处理Rest服务

  异步处理的配置

2.原理图说明

  

二:Callable进行异步处理

1.程序

  新建一个anysc的包

 package com.cao.web.async;

 import java.util.concurrent.Callable;

 import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class AsyncController {
private Logger logger=LoggerFactory.getLogger(getClass()); @RequestMapping("/order")
public Callable<String> order() throws Exception {
logger.info("主线程开始");
//业务逻辑放在副线程中
Callable<String> result=new Callable<String>() { @Override
public String call() throws Exception {
logger.info("副线程开始");
Thread.sleep(5000);
logger.info("副线程返回");
return "success";
} }; logger.info("主线程返回"); return result;
} }

2.效果

  重点关注时间

  

三:使用DeferredResult

1.问题

  方式一是有问题的,因为副线程是需要主线程调用起来的。

  是写在主线程中的。

  有些场景是不合适的。

  线程间使用DeferredResult沟通起来。

2.场景如下:

  

3.程序

  程序太多,有点复杂

  控制器

 package com.cao.web.async;

 import java.util.concurrent.Callable;

 import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult; @RestController
public class AsyncController {
private Logger logger=LoggerFactory.getLogger(getClass());
@Autowired
private Queue queue; @Autowired
private DeferredResultHolder deferredResultHolder; /**
* 主要是验证Callable
* @return
* @throws Exception
*/
@RequestMapping("/order")
public Callable<String> order() throws Exception {
logger.info("主线程开始");
//业务逻辑放在副线程中
Callable<String> result=new Callable<String>() { @Override
public String call() throws Exception {
logger.info("副线程开始");
Thread.sleep(5000);
logger.info("副线程返回");
return "success";
} }; logger.info("主线程返回"); return result;
}
/**
* 主要是验证
* @return
* @throws Exception
*/
@RequestMapping("/newOrder")
public DeferredResult<String> newOrder() throws Exception {
logger.info("主线程开始");
//
String oderNumber=RandomStringUtils.randomNumeric(8);
queue.setPlaceOrder(oderNumber);
DeferredResult<String> result=new DeferredResult<>();
deferredResultHolder.getMap().put(oderNumber, result);
logger.info("主线程返回"); return result;
} }

  queue.java

 package com.cao.web.async;

 import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class Queue {
private String placeOrder;
private String completeOrder; private Logger logger=LoggerFactory.getLogger(getClass()); public String getPlaceOrder() {
return placeOrder;
}
public void setPlaceOrder(String placeOrder) throws Exception {
new Thread(() -> {
logger.info("接到下单请求");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 表示处理完成,应用2将结果返回给了completeOrder
this.completeOrder = placeOrder;
logger.info("下单请求处理完毕" + placeOrder);
} ).start(); }
public String getCompleteOrder() {
return completeOrder;
}
public void setCompleteOrder(String completeOrder) {
this.completeOrder = completeOrder;
} }

  deferredResultHolder.java

 package com.cao.web.async;

 import java.util.HashMap;
import java.util.Map; import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult; @Component
public class DeferredResultHolder {
//一个是订单号,一个是订单号的处理结果
private Map<String,DeferredResult<String>> map=new HashMap<>();
public Map<String,DeferredResult<String>> getMap(){
return map;
}
public void setMap(Map<String,DeferredResult<String>> map) {
this.map=map;
}
}

  QueueListener.java

 package com.cao.web.async;

 import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.log;

 import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component; @Component
public class QueueListener implements ApplicationListener<ContextRefreshedEvent>{
@Autowired
private Queue queue; @Autowired
private DeferredResultHolder deferredResultHolder; private Logger logger=LoggerFactory.getLogger(getClass()); @Override
public void onApplicationEvent(ContextRefreshedEvent event) {
new Thread(() -> {
while (true) {
if (StringUtils.isNotBlank(queue.getCompleteOrder())) {
String orderNumber = queue.getCompleteOrder();
logger.info("返回订单处理结果" + orderNumber);
deferredResultHolder.getMap().get(orderNumber).setResult("place order success");
queue.setCompleteOrder(null);
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start(); } }

  

4.效果

  前端效果

  

  控制台效果

  

三:异步线程的配置

1.说明

  对于拦截器,与同步的拦截器不一样,仍然需要配置、

2.主要配置

  

010 异步处理Rest服务的更多相关文章

  1. WPF异步调用WCF服务

    wpf调用wcf时,第一次访问总耗时到达几秒,影响界面的用户体验,因此在wpf加载界面和加载数据时采用异步加载,即异步访问wcf服务, 由于是否采用异步加载和服务端无关,仅仅由客户端自己根据需要来选择 ...

  2. Java笔记(十七) 异步任务执行服务

    异步任务执行服务 一.基本原理和概念 一)基本接口 1)Runnable和Callable:表示要执行的异步任务. 2)Executor和ExecutorService:表示执行服务. 3)Futur ...

  3. 使用kendynet构建异步redis访问服务

    使用kendynet构建异步redis访问服务 最近开始在kendynet上开发手游服务端,游戏类型是生存挑战类的,要存储的数据结构和类型都比较简单,于是选择了用redis做存储,数据类型使用stri ...

  4. Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token

    原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf?   因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...

  5. mvc路由引起异步调用web服务的问题

    从一篇blog得知使用脚本可以异步调用Web服务,觉得很新鲜,因为自己很少用到Web服务,所以决定写一写看看什么效果. 首先在UI项目(我使用的是MVC4.0)里创建一个Web服务. 添加Web服务后 ...

  6. Silverlight中异步调用WCF服务,传入回调函数

    以前学的ASP.NET,调用的都是同步方法,同步方法的好处就是,一步一步走,完成这步才会走下一步.然而,WCF使用的都是异步方法,调用之后不管有没有获得结果就直接往下走,最可恶的是异步函数都是Void ...

  7. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

  8. Java编程的逻辑 (77) - 异步任务执行服务

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  9. 25.C# 异步调用Web服务

    1.创建Web服务 1.1VS新建ASP.Net空Web应用程序 1.2添加Web服务新建项 1.3添加GetWeather方法和相关类 using System; using System.Coll ...

随机推荐

  1. python-函数入门(二)

    一.函数对象 什么是函数? 函数是第一类对象,指的是函数名指向的值(函数)可以被当做数据去使用 1.函数的特性 1.函数可以被引用,即函数可以把值赋值给一个变量 def foo(): print('f ...

  2. linux学习之软件包安装

    本学习基于redhat系统或者centos系统 一.软件包的安装 1.rpm安装,rpm安装分为俩种,一种是直接安装xxx.rpm包,另一种是通过yum安装一系列的rpm包. #推荐使用yum安装,y ...

  3. linux命令排序

    sort -k1 -n 第一列按数字正排序 sort -K1 -rn 第一列按数字倒排序

  4. Confluence 6 在你的 LDAP 目录中优化用户和用户组数量

    连接 LDAP 服务器能为你的用户管理提供灵活高效的解决方案.为了达到优化的性能,后台同步程序将会从 LDAP 上查找和下载数据同步到你本地的 Confluence 服务器数据库上同时还会定时的更新数 ...

  5. 简化版的AXI-LITE4和配合使用的RTL

    ////////////////////////////////////////////////////////////////////////////////// // // The ZYNQ FI ...

  6. LeetCode(77):组合

    Medium! 题目描述: 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3] ...

  7. LeetCode(70): 爬楼梯

    Easy! 题目描述: 假设你正在爬楼梯.需要 n 步你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 ...

  8. mongoDB通过_id删除doc

    转载: 点击查看原文 做项目遇到一个需求,需要根据mongodb数据记录里面的_id字段删除相应的docs,实际使用时发现直接如下使用 db.collection('infochanges').rem ...

  9. C++ lstrlen()

    关于lstrlen function,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms647492(v=vs.85).asp ...

  10. linux-umount挂载点无法卸载:device is busy(解决)

    umount不了的原因一般是由于有程序有用户在占用 解决方法: 1.      首先查找谁在占用:#fuser /mnt/nfs 得到进程号. 2.      查找进程:#ps –ef|grep 进程 ...