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

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

  • 相关阅读:
    VUE框架的初识
    cookie和session的区别及在Django中应用
    Django分页器的设置
    Django中manger/QuerySet类与mysql数据库的查询
    photoshop cc 2017使用快捷方式
    markdown基础语法
    pycharm中的flask项目如何开启debug模式
    flask连接数据库
    flask连接数据库
    pycharm中的flask项目如何开启debug模式
  • 原文地址:https://www.cnblogs.com/ph7seven/p/9549824.html
Copyright © 2020-2023  润新知