springboot怎么利用aop实现接口异步

springboot怎么利用aop实现接口异步

小编给大家分享一下springboot怎么利用aop实现接口异步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

    一、前言

    在项目中发现有接口(excel导入数据)处理数据需要耗时比较长的时间,是因为数据量比较大,同时数据的校验需要耗费一定时间,决定使用一种通用的方法解决这个问题。

    解决方案:通过aop使接口异步处理,前端轮询另外一个接口查询进度。

    目标:

    1接口上一个注解即可实现接口异步(优化:可以通过header参数动态控制是否异步)

    2一个方法实现进度条的更新

    二、时序图

    三、功能演示

    四、关键代码

    Controller

    @EnableAsync是自已定义注解更新缓存进度asyncService.updatePercent(per);

    @EnableAsync@RequestMapping(value="test",method=RequestMethod.POST)@ApiOperation(value="接口测试")@ApiImplicitParams({@ApiImplicitParam(name="num",value="数字",required=true,dataType="int",paramType="query",defaultValue="1")})publicObjectdemo(Integernum)throwsInterruptedException{for(inti=0;i<15;i++){Thread.sleep(1000);//计算百分比Stringper=BigDecimal.valueOf(i).divide(BigDecimal.valueOf(15),2,RoundingMode.HALF_DOWN).toString();//更新redis缓存进度asyncService.updatePercent(per);}Integerb=100;returnResult.success(String.format("线程变量值:%s,100除以%s的结果是%s",RequestHolder.get(),num,b/num));}

    AsyncAop

    importcn.hutool.core.util.IdUtil;importcom.asyf.demo.common.Result;importcom.asyf.demo.common.pojo.RequestHolder;importcom.asyf.demo.service.AsyncService;importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Pointcut;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importorg.springframework.web.context.request.RequestContextHolder;importorg.springframework.web.context.request.ServletRequestAttributes;importjavax.servlet.http.HttpServletRequest;@Aspect@Component@Slf4jpublicclassAsyncAop{@AutowiredprivateAsyncServiceasyncService;@Pointcut("@annotation(com.asyf.demo.common.aop.EnableAsync)")publicvoidcostTimePointCut(){}@Around("costTimePointCut()")publicObjectaround(ProceedingJoinPointpoint)throwsThrowable{longbeginTime=System.currentTimeMillis();//请求headerServletRequestAttributesservletRequestAttributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequestrequest=servletRequestAttributes.getRequest();RequestHolder.set(request.getHeader("dateFormat"));//异步消息Stringid=IdUtil.simpleUUID();AsyncMsgasyncMsg=newAsyncMsg();asyncMsg.setId(id);//异步返回值Objectresult=Result.success(asyncMsg);StringrequestHolder=RequestHolder.get();//异步执行asyncService.async(requestHolder,asyncMsg,point);//执行时长(毫秒)longtime=System.currentTimeMillis()-beginTime;logCostTime(point,time);returnresult;}privatevoidlogCostTime(ProceedingJoinPointpoint,longtime){MethodSignaturesignature=(MethodSignature)point.getSignature();StringclassName=point.getTarget().getClass().getName();StringmethodName=signature.getName();log.info("class:{}method:{}耗时:{}ms",className,methodName,time);}}

    AsyncService

    实现异步消息的更新

    异步消息的进度信息传递通过本地线程与redis实现

    importcn.hutool.core.exceptions.ExceptionUtil;importcom.asyf.demo.common.aop.AsyncMsg;importcom.asyf.demo.common.pojo.AsyncHolder;importcom.asyf.demo.common.pojo.RequestHolder;importcom.asyf.demo.service.AsyncService;importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.ProceedingJoinPoint;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Service;importjava.util.concurrent.TimeUnit;@Service@Slf4jpublicclassAsyncServiceImplimplementsAsyncService{@AutowiredprivateRedisTemplateredisTemplate;@Overridepublicvoidasync(StringrequestHolder,AsyncMsgasyncMsg,ProceedingJoinPointpoint){newThread(newRunnable(){@Overridepublicvoidrun(){Stringid=asyncMsg.getId();//请求线程变量-传递请求线程参数RequestHolder.set(requestHolder);//异步消息线程变量-传送id到实际方法以便方法更新进度AsyncHolder.set(asyncMsg);//执行方法try{redisTemplate.opsForValue().set(id,asyncMsg,60,TimeUnit.MINUTES);Objectresult=point.proceed();asyncMsg.setResult(result);asyncMsg.setStatus("0");redisTemplate.opsForValue().set(id,asyncMsg,60,TimeUnit.MINUTES);}catch(Throwablethrowable){log.error(ExceptionUtil.stacktraceToString(throwable));asyncMsg.setStatus("-1");asyncMsg.setResult(throwable.getLocalizedMessage());redisTemplate.opsForValue().set(id,asyncMsg,60,TimeUnit.MINUTES);}}}).start();}@OverridepublicvoidupdatePercent(Stringper){AsyncMsgasyncMsg=AsyncHolder.get();asyncMsg.setPercent(per);redisTemplate.opsForValue().set(asyncMsg.getId(),asyncMsg,60,TimeUnit.MINUTES);}}

    看完了这篇文章,相信你对“springboot怎么利用aop实现接口异步”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

    发布于 2022-01-05 23:22:23
    收藏
    分享
    海报
    0 条评论
    40
    上一篇:Java基础知识点有哪些 下一篇:如何解决Unity自定义组件之序列帧播放组件问题
    目录

      0 条评论

      本站已关闭游客评论,请登录或者注册后再评论吧~

      忘记密码?

      图形验证码