SpringBoot @Async 异步处理业务逻辑和发短信逻辑
有个业务场景,业务数据审核通过后需要给用户发短信,发短信过程比较耗时,可能需要几秒甚至十几秒,因此使用异步发短信
使用了注解@Async来实现:
1.SpringApplication启用注解@EnableAsync
@SpringBootApplication
@ImportResource(locations = { "classpath:/spring/spring-*.xml" })
@EnableTransactionManagement(proxyTargetClass=true)
@EnableScheduling
@EnableAutoConfiguration(exclude = { FreeMarkerAutoConfiguration.class })
@EnableSwagger2
@ServletComponentScan(basePackages="com.xx")
@EnableMongoRepositories(basePackages = "com.xx.xx.xx.xx")
@EnableAsync
public class IemsApplication { public static void main(String[] args) {
SpringApplication.run(IemsApplication.class, args);
}
...
2.在业务层(@Service)具体的审核方法上添加注释@Async
@Async
public void cancelAudit(DefectForm defectForm) {
Map<String,Object> params = new HashMap<>();
params.put("defectId", defectForm.getDefectId()); //缺陷记录ID
params.put("defectStatus", 3); //更新缺陷记录状态审核拒绝
params.put("reason", defectForm.getReason()); //拒绝理由
defectRecordDao.updateByPrimaryKeySelective(params);
//上面是业务处理,下面是发短信
//审核拒绝发送短信,短信发送给缺陷上报人,缺陷内容,审核拒绝理由
Account account = accountDao.findAccountById(xxx);
if(account != null && StringUtils.isNotBlank(account.getMobile())){
String mobile = account.getMobile();
String defectContent = defectForm.getDefectContent();
String reason = defectForm.getReason();
Map<String,String> templateData = new HashMap<>();
templateData.put("defectContent", defectContent);
templateData.put("reason", reason);
smsService.sendSms(null, mobile, SmsConstant.DEFECT_REFUSRD_CODE, templateData,false);
logger.debug("缺陷上报记录审核拒绝,发送短信给缺陷记录上报人******");
}
}
3.前端逻辑:
/**
* 审核拒绝,确定
* @returns
*/
function makeRefuse(){
var reason = $("#refuse_reason").val();
if (reason==null || reason.trim()==""){
AppUtils.showTooltip("请填写拒绝理由!",false);
return;
}
var curDefect = recordsJson[xxx];
$.ajax({
url: path + '/xxx/xxx/qqq/cancelAudit',
type: 'post',
dataType: 'json',
data:curDefect,
success: function(data){
if(data=="ok"){
AppUtils.showTooltip("审核拒绝成功!",true);
$("#topForm").attr("action",path + '/xxx/xxx/xxx');
$("#topForm").submit();
}
}
});
}
4.Controller层
@RequestMapping("/xxx/xxx/cancelAudit")
@ResponseBody
public String cancelAudit(DefectForm defectForm){
defectRecordService.cancelAudit(defectForm);
return "ok";
}
经测试,可以异步更新、发送短信
但是,发现一个严重的问题:前台页面点击取消审核后页面状态偶尔能刷新过来,偶尔还是之前的状态,重新查询一次后,页面显示正常
分析代码:Controller层代码写的有问题,Controller层调用Service层(defectRecordService.cancelAudit(defectForm);),Service层cancelAudit(DefectForm defectForm)方法整个是@Async,
主线程会直接返回,而新启的线程处理Service层的逻辑。这样ajax返回前台,前台再去刷新数据的时候,可能新启线程Service的更新逻辑还没处理完,这样就导致了页面刷新状态错误的问题
其实:我们期望的是,业务逻辑(更新操作)执行完成后再返回;整个业务逻辑(更新操作完成,返回)与发短信异步
修改后的代码:
1.Controller层
@RequestMapping("/xxx/xxx/cancelAudit")
@ResponseBody
public String cancelAudit(DefectForm defectForm){
defectRecordService.cancelAudit(defectForm); //更新操作,成功后往下走,sendCancelAuditMsg会新启一个线程处理,主线程继续往下走,走到return "ok";返回
//审核拒绝:业务操作完成后发短信
defectRecordService.sendCancelAuditMsg(defectForm);
return "ok";
}
2.Service层
//这里我们就不需要添加异步注解了
public void cancelAudit(DefectForm defectForm) {
Map<String,Object> params = new HashMap<>();
params.put("defectId", defectForm.getDefectId()); //缺陷记录ID
params.put("defectStatus", 3); //更新缺陷记录状态审核拒绝
params.put("reason", defectForm.getReason()); //拒绝理由
defectRecordDao.updateByPrimaryKeySelective(params);
}
//把发短信的逻辑抽出来,单独一个方法,使用异步注解
@Async
public void sendCancelAuditMsg(DefectForm defectForm){
//审核拒绝发送短信,短信发送给缺陷上报人,缺陷内容,审核拒绝理由
Account account = accountDao.findAccountById(defectForm.getCreatorUserid());
if(account != null && StringUtils.isNotBlank(account.getMobile())){
String mobile = account.getMobile();
String defectContent = defectForm.getDefectContent();
String reason = defectForm.getReason();
Map<String,String> templateData = new HashMap<>();
templateData.put("defectContent", defectContent);
templateData.put("reason", reason);
smsService.sendSms(null, mobile, SmsConstant.DEFECT_REFUSRD_CODE, templateData,false);
logger.debug("缺陷上报记录审核拒绝,发送短信给缺陷记录上报人******");
}
}
至此问题就解决了,写博客标注一下
SpringBoot @Async 异步处理业务逻辑和发短信逻辑的更多相关文章
- 项目一:在线下单(补充) activeMQ使用(重点) 重构客户注册功能,发短信功能分离
1 课程计划 1.在线下单(补充) 2.activeMQ使用(重点) n 简介和安装 n activeMQ入门案例 n spring整合activeMQ应用 3.重构客户注册功能,发短信功能分离 n ...
- java实现发短信功能---腾讯云短信
目录 java实现发短信功能 前言 开发环境 腾讯云 ---短信 代码 效果 结束语 java实现发短信功能 前言 如今发短信功能已经成为互联网公司的标配,本篇文章将一步步实现java发送短信 考察了 ...
- iOS开发之调用系统打电话发短信接口以及程序内发短信
在本篇博客开头呢,先说一下写本篇的博客的原因吧.目前在做一个小项目,要用到在本应用程序内发验证码给其他用户,怎么在应用内发送短信的具体细节想不大起来了,于是就百度了一下,发现也有关于这方面的博客,点进 ...
- 打电话,发短信,发邮件,app跳转
1.打电话 - (IBAction)callPhone1:(id)sender { NSURL *url = [NSURL URLWithString:@"tel://18500441739 ...
- linux下利用GPRS模块发短信、打电话
一.开发环境 内核版本:linux-3.0 开发板:FL2440(nandflash:K9F1G08 128M) GPRS模块:SIM900 二.与发短信和拨号相关的 AT 指 ...
- iOS中如何切换到发短信、打电话、发邮件
我们在做APP的时候,难免会遇到需要调用短信,电话等程序的时候.如美团. 当然,这些都只是一些简单的方法就可以实现,但是时间久了也会淡忘,所以想写这边博客.一是为了再捡起来复习一下,另一个相当于留个备 ...
- iOS开发中打电话发短信等功能的实现
在APP开发中,可能会涉及到打电话.发短信.发邮件等功能.比如说,通常一个产品的"关于"页面,会有开发者的联系方式,理想情况下,当用户点击该电话号码时,能够自动的帮用户拨出去,就涉 ...
- [stm32] SIM808模块之发短信\GPS\TCP\HTTP研究
SIM8008是四频模块,全球可用.含有TTL电平接口等接口,能够实现发短信.打电话.GPRS传输数据.GPS等功能.[正版资料请找beautifulzzzz·博客园] 一些细节: >> ...
- ios 设置亮度、声音;调用发短信、邮件、打电话
一,设置亮度 [[UIScreen mainScreen] setBrightness:0.5];//0.0~1.0 二,设置声音 1,添加 MediaPlayer.framework 框架 2,在需 ...
随机推荐
- 必应语音API(Bing text to speech API)
前言 Link : Microsoft Speech API overview 通过这个链接,大致了解Bing speech API的语音识别和语音合成两部分, 这次是需要用到TTS,所以就直接看TT ...
- Linux 多主机SSH互信操作---noob....
创建虚拟机后-- ssh-keygen 生成公钥和私钥对 -rw------- 1 root root 1679 11月 4 09:18 id_rsa-rw-r--r-- 1 root root 39 ...
- Excel 使用AutoFill提示“类Range的AutoFill方法无效”
今天遇到一个神奇的问题,之前一直使用很好的代码突然报错:“类Range的AutoFill方法无效”,在网上搜索了一番,感觉没有一个与我遇到的情况相同的.debug,查看一下代码,发现程序里,AutoF ...
- 设计模式之工厂模式(c++)
问题描述 在面向对象系统设计中经常可以遇到以下的两类问题:1)为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口.这样我们可以通过声明 ...
- js cookies
cookie用於識別用戶,存儲在訪問者的計算機里,當用戶首次使用瀏覽器時,會發送cookie.用戶可以創建和獲取cookie. cookie可以存儲用戶名字.用戶密碼和訪問時間等. document. ...
- SpringMVC @SessionAttributes 使用
@SessionAttributes 只能作用在类上,作用是将指定的Model中的键值对添加至session中,方便在下一次请求中使用. 简单示例 目标是通过 @SessionAttributes 注 ...
- C#利用反射来判断对象是否包含某个属性的实现方法
本文实例展示了C#利用反射来判断对象是否包含某个属性的实现方法,对于C#程序设计人员来说有一定的学习借鉴价值. 具体实现代码如下: /// <summary> /// 利用反射来判断对象是 ...
- 洛谷P3066 [USACO12DEC]逃跑的BarnRunning Away From…
题面链接 一句话题意:给出以1号点为根的一棵有根树,问每个点的子树中与它距离小于等于l的点有多少个. 我:似乎并不好做啊...看了题解后大雾... sol:考虑树上差分,对于一个点,在他那个位置++, ...
- TortoiseGit连接gitlab,一直要求输入密码
问题背景: 公司使用gitlab作为代码管理平台,安装了TortoiseGit之后,使用正常.但是重启电脑之后,再次使用TortoiseGit操作时总是提醒输入gitlab的账号.如下图: 问题原因: ...
- BZOJ4555 HEOI2016/TJOI2016求和(NTT+斯特林数)
S(i,j)=Σ(-1)j-k(1/j!)·C(j,k)·ki=Σ(-1)j-k·ki/k!/(j-k)!.原式=ΣΣ(-1)j-k·ki·2j·j!/k!/(j-k)! (i,j=0~n).可以发现 ...