010 异步处理Rest服务
一:任务
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服务的更多相关文章
- WPF异步调用WCF服务
wpf调用wcf时,第一次访问总耗时到达几秒,影响界面的用户体验,因此在wpf加载界面和加载数据时采用异步加载,即异步访问wcf服务, 由于是否采用异步加载和服务端无关,仅仅由客户端自己根据需要来选择 ...
- Java笔记(十七) 异步任务执行服务
异步任务执行服务 一.基本原理和概念 一)基本接口 1)Runnable和Callable:表示要执行的异步任务. 2)Executor和ExecutorService:表示执行服务. 3)Futur ...
- 使用kendynet构建异步redis访问服务
使用kendynet构建异步redis访问服务 最近开始在kendynet上开发手游服务端,游戏类型是生存挑战类的,要存储的数据结构和类型都比较简单,于是选择了用redis做存储,数据类型使用stri ...
- Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token
原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf? 因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...
- mvc路由引起异步调用web服务的问题
从一篇blog得知使用脚本可以异步调用Web服务,觉得很新鲜,因为自己很少用到Web服务,所以决定写一写看看什么效果. 首先在UI项目(我使用的是MVC4.0)里创建一个Web服务. 添加Web服务后 ...
- Silverlight中异步调用WCF服务,传入回调函数
以前学的ASP.NET,调用的都是同步方法,同步方法的好处就是,一步一步走,完成这步才会走下一步.然而,WCF使用的都是异步方法,调用之后不管有没有获得结果就直接往下走,最可恶的是异步函数都是Void ...
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
- Java编程的逻辑 (77) - 异步任务执行服务
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- 25.C# 异步调用Web服务
1.创建Web服务 1.1VS新建ASP.Net空Web应用程序 1.2添加Web服务新建项 1.3添加GetWeather方法和相关类 using System; using System.Coll ...
随机推荐
- 【转】Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍
Jmeter中使用CSV Data Set Config参数化不重复数据执行N遍 要求: 今天要测试上千条数据,且每条数据要求执行多次,(模拟多用户多次抽奖) 1.用户id有175个,且没有任何排序规 ...
- [maven] dependency标签理解
在maven pom.xml文件中最多的就是dependency标签,我们用maven管理我们项目的依赖.这篇文章简单介绍dependency标签内部各个子标签的意义. 下面是dependency标签 ...
- ECS分区挂载数据盘
地址:https://help.aliyun.com/document_detail/25426.html?spm=5176.11065259.1996646101.searchclickresult ...
- android高级页面效果集锦
程序员界有个神奇的网站,那就是github,这个网站集合了一大批优秀的开源框架,极大地节省了开发者开发的时间,在这里我进行了一下整理,这样可以使我们在使用到时快速的查找到,希望对大家有所帮助! 一个强 ...
- ios 清除缓存文件
获取缓存文件的大小 由于缓存文件存在沙箱中,我们可以通过NSFileManager API来实现对缓存文件大小的计算. 计算单个文件大小 +(float)fileSizeAtPath:(NSStrin ...
- Hibrenate之事务的理解以及代码编写
3 事务概念 事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务,SQL Server能将逻辑相关的一组操作绑定 ...
- Confluence 6 配置服务器基础地址备注
使用不同 URL.如果你配置了不同的基础 URL 地址或者你站点的访问者使用了不同的 URL 地址来访问你的 Confluence 地址,你有很大概率可能会受到错误信息. 修改上下文地址.如果你修改了 ...
- Confluence 6 修改站点标题
站点标题是在浏览器的标题栏中显示的.在默认的情况下,标题被显示为 Confluence. 希望修改你站点的标题: 在屏幕的右上角单击 控制台按钮 ,然后选择 General Configuration ...
- js模块化编程之CommonJS和AMD/CMD
js模块化编程commonjs.AMD/CMD与ES6模块规范 一.CommonJS commonjs的require是运行时同步加载,es6的import是静态分析,是在编译时而不是在代码运行时.C ...
- webpack2配置备份
package.json: { "name": "leyi", "version": "1.0.0", "ma ...