springboot怎么利用aop实现接口异步
发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,小编给大家分享一下springboot怎么利用aop实现接口异步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、前言在项目中发现有接口(excel导入数据)处理数据需要耗时比较长的
千家信息网最后更新 2025年02月02日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") }) 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缓存进度 asyncService.updatePercent(per); } Integer b = 100; return Result.success(String.format("线程变量值:%s,100除以%s的结果是%s", RequestHolder.get(), num, b / num)); }
AsyncAop
import cn.hutool.core.util.IdUtil;import com.asyf.demo.common.Result;import com.asyf.demo.common.pojo.RequestHolder;import com.asyf.demo.service.AsyncService;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;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.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Aspect@Component@Slf4jpublic class AsyncAop { @Autowired private AsyncService asyncService; @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 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttributes.getRequest(); RequestHolder.set(request.getHeader("dateFormat")); //异步消息 String id = IdUtil.simpleUUID(); AsyncMsg asyncMsg = new AsyncMsg(); asyncMsg.setId(id); //异步返回值 Object result = Result.success(asyncMsg); String requestHolder = RequestHolder.get(); //异步执行 asyncService.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); }}
AsyncService
实现异步消息的更新
异步消息的进度信息传递通过本地线程与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.service.AsyncService;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.Service; import java.util.concurrent.TimeUnit; @Service@Slf4jpublic class AsyncServiceImpl implements AsyncService { @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.set(requestHolder); //异步消息线程变量-传送id到实际方法以便方法更新进度 AsyncHolder.set(asyncMsg); //执行方法 try { redisTemplate.opsForValue().set(id, asyncMsg, 60, TimeUnit.MINUTES); Object result = point.proceed(); asyncMsg.setResult(result); asyncMsg.setStatus("0"); redisTemplate.opsForValue().set(id, asyncMsg, 60, TimeUnit.MINUTES); } catch (Throwable throwable) { log.error(ExceptionUtil.stacktraceToString(throwable)); asyncMsg.setStatus("-1"); asyncMsg.setResult(throwable.getLocalizedMessage()); redisTemplate.opsForValue().set(id, asyncMsg, 60, TimeUnit.MINUTES); } } }).start(); } @Override public void updatePercent(String per) { AsyncMsg asyncMsg = AsyncHolder.get(); asyncMsg.setPercent(per); redisTemplate.opsForValue().set(asyncMsg.getId(), asyncMsg, 60, TimeUnit.MINUTES); } }
看完了这篇文章,相信你对"springboot怎么利用aop实现接口异步"有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!
接口
进度
方法
线程
更新
数据
消息
参数
变量
时间
注解
篇文章
缓存
处理
代码
信息
关键
前端
前言
功能
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
海淀区正规软件开发经历
服务器输入密码不对怎么办
计算机与网络安全考研大学排名
打印机服务器是什么
疫情下的网络安全生活
南通海安软件开发培训
办公软件开发价格表
手机大宗商品交易软件开发
大学生网络安全教育证书
网络安全法企业责任解读
网络安全专业题库
高中生网络安全常识题
app软件开发的威胁怎么解决
济宁电商软件开发公司
数据库的人才缺口
智库的数据库
怎样保证家用网络安全
宁波第三届网络安全大赛结果
晕数据库
开热点网络安全吗
网络安全技术研究 基本问题
湖南数据软件开发有哪些
软件开发论文章节
js加载cad数据库
触摸屏打不开数据库
大学生网络安全教育证书
云动风起网络技术有限公司
怎么找网络安全培训机构
数据库采用的数据模一般有
计算机网络安全是指选择题