在项目中发现有接口(excel导入数据)处理数据需要耗时比较长的时间,是因为数据量比较大,同时数据的校验需要耗费一定时间,决定使用一种通用的方法解决这个问题。
解决方案:通过aop使接口异步处理,前端轮询另外一个接口查询进度。
目标:
1接口上一个注解即可实现接口异步(优化:可以通过header参数动态控制是否异步)
2一个方法实现进度条的更新
@enableasync是自已定义注解更新缓存进度asyncrvice.updatepercent(per);
@enableasync @requestmapping(value = "test", method = requestmethod.post) @apioperation(value = "接口测试") @apiimplicitparams({ @apiimplicitparam(name = "num", value = "数字", required = true, datatype = "int", paramtype = "query", defaultvalue = "1") }) 北周是什么朝代 public object demo(integer num) throws interruptedexception { for (int i = 0; i < 15; i++) { thread.sleep(1000); //计算百分比 string per = bigdecimal.valueof(i).divide(bigdecimal.valueof(15), 2, roundingmode.half_down).tostring(); //更新redis缓存进度 asyncrvice.updatepercent(per); } integer b = 100; return result.success(string.format("线程变量值:%s,100除以%s的结果是%s", requestholder.get(), num, b / num)); }
impor柳州有什么大学t cn.hutool.core.util.idutil;import com.asyf.demo.common.result;import com.asyf.demo.common.pojo.requestholder;import com.asyf.demo.rvice.asyncrvice;import lombok.extern.slf4j.slf4j;import org.aspectj.lang.proceedingjoinpoin女性健康体检t;import org.aspectj.lang.annotation.around;import org.aspectj.lang.annotation.aspect;import org.aspectj.lang.annotation.pointcut;import org.aspectj.lang.reflect.methodsignature;import org.springframework.beans.factory.annotation.autowired;import org.springframework.stereotype.component;import org.springframework.web.context.request.requestcontextholder;import org.springframework.web.context.request.rvletrequestattributes; import javax.rvlet.http.httprvletrequest; @aspect@component@slf4jpublic class asyncaop { @autowired private asyncrvice asyncrvice; @pointcut("@annotation(com.asyf.demo.common.aop.enableasync)") public void costtimepointcut() { } @around("costtimepointcut()") public object around(proceedingjoinpoint point) throws throwable { long begintime = system.currenttimemillis(); //请求header rvletrequestattributes rvletrequestattributes = (rvletrequestattributes) requestcontextholder.getrequestattributes(); httprvletrequest request = rvletrequestattributes.getrequest(); requestholder.t(request.getheader("dateformat")); //异步消息 string id = idutil.simpleuuid(); asyncmsg asyncmsg = new asyncmsg(); asyncmsg.tid(id); //异步返回值 object result = result.success(asyncmsg); string requestholder = requestholder.get(); //异步执行 asyncrvice.async(requestholder, asyncmsg, point); //执行时长(毫秒) long time = system.currenttimemillis() - begintime; logcosttime(point, time); return result; } private void logcosttime(proceedingjoinpoint point, long time) { methodsignature signature = (methodsignature) point.getsignature(); string classname = point.gettarget().getclass().getname(); string methodname = signature.getname(); log.info("class:{} method:{} 耗时:{}ms", classname, methodname, time); }}
实现异步消息的更新
异步消息的进度信息传递通过本地线程与redis实现
import cn.hutool.core.exceptions.exceptionutil;import com.asyf.demo.common.aop.asyncmsg;import com.asyf.demo.common.pojo.asyncholder;import com.asyf.demo.common.pojo.requestholder;import com.asyf.demo.rvice.asyncrvice;import lombok.extern.slf4j.slf4j;import org.aspectj.lang.proceedingjoinpoint;import org.springframework.beans.factory.annotation.autowired;import org.springframework.data.redis.core.redistemplate;import org.springframework.stereotype.rvice; import java.util.concurrent.timeunit; @rvice@slf4jp适合度蜜月的地方ublic class asyncrviceimpl implements asyncrvice { @autowired private redistemplate redistemplate; @override public void async(string requestholder, asyncmsg asyncmsg, proceedingjoinpoint point) { new thread(new runnable() { @override public void run() { string id = asyncmsg.getid(); //请求线程变量-传递请求线程参数 requestholder.t(requestholder); //异步消息线程变量-传送id到实际方法以便方法更新进度 asyncholder.t(asyncmsg); //执行方法 try { redistemplate.opsforvalue().t(id, asyncmsg, 60, timeunit.minutes); object result = point.proceed(); asyncmsg.tresult(result); asyncmsg.tstatus("0"); redistemplate.opsforvalue().t(id, asyncmsg, 60, timeunit.minutes); } catch (throwable throwable) { log.error(exceptionutil.stacktracetostring(throwable)); asyncmsg.tstatus("-1"); asyncmsg.tresult(throwable.getlocalizedmessage()); redistemplate.opsforvalue().t(id, asyncmsg, 60, timeunit.minutes); } } }).start(); } @override public void updatepercent(string per) { asyncmsg asyncmsg = asyncholder.get(); has和have的用法 asyncmsg.tpercent(per); redistemplate.opsforvalue().t(asyncmsg.getid(), asyncmsg, 60, timeunit.minutes); } }
java-demo: 存储代码示例 – gitee.com
到此这篇关于springboot利用aop实现接口异步(进度条)的文章就介绍到这了,更多相关springboot aop实现接口异步内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 13:04:05,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/a342bbe126768a2e4c84a652e646a481.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:springboot利用aop实现接口异步(进度条)的全过程.doc
本文 PDF 下载地址:springboot利用aop实现接口异步(进度条)的全过程.pdf
留言与评论(共有 0 条评论) |