zoukankan      html  css  js  c++  java
  • 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("缺陷上报记录审核拒绝,发送短信给缺陷记录上报人******");
    	}
    }

    至此问题就解决了,写博客标注一下 

  • 相关阅读:
    WPF之感触
    C# WinForm 给DataTable中指定位置添加列
    MyEclipse 8.6 download 官方下载地址
    将博客搬至CSDN
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
  • 原文地址:https://www.cnblogs.com/ph7seven/p/9549824.html
Copyright © 2011-2022 走看看