首页
友链
统计
留言
关于
Search
1
Java生成二维码——基于Google插件
125 阅读
2
Java使用poi-tl动态生成word和pdf
121 阅读
3
网站声明
98 阅读
4
利用Spring的InitializingBean优雅的实现策略模式
88 阅读
5
循环单链表及其实现
82 阅读
默认分类
Java
C语言
数据库技术
Linux
前端
其他
登录
/
注册
Search
标签搜索
C语言
数据结构
Java
Spring
数据库技术
MySQL
Hadoop
MapReduce
大数据
easyExcel
POI
MybatisPlus
AOP
SpringMVC
IDEA
工厂模式
策略模式
设计模式
LiXiangrong
累计撰写
57
篇文章
累计收到
151
条评论
首页
栏目
默认分类
Java
C语言
数据库技术
Linux
前端
其他
页面
友链
统计
留言
关于
搜索到
1
篇与
的结果
2024-01-03
AOP实现防止前端请求重复提交
1.防止重复提交注解package com.risesun.common.core.annotation; import java.lang.annotation.*; /** * @Author LiXiangrong * @Description 防止重复提交注解 * @Date 2023/04/03 9:04:15 **/ @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RepeatSubmit { /** * 防重复操作限时标记数值(存储redis限时标记数值) */ String value() default "value" ; /** * 防重复操作过期时间(借助redis实现限时控制) */ long expireSeconds() default 10; }2.AOP实现防止请求重复提交package com.risesun.business.aspect; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.json.JSONUtil; import com.risesun.common.core.annotation.RepeatSubmit; import com.risesun.common.core.constant.TokenConstants; 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.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Objects; import java.util.concurrent.TimeUnit; /** * @Author LiXiangrong * @Description AOP实现防止请求重复提交 * @Date 2023/04/03 8:41:04 **/ @Slf4j @Component @Aspect public class NoRepeatSubmitAspect { @Autowired private RedisTemplate redisTemplate; private final String SIGN = "submit duplication"; private final String PREFIX = "PREVENT_DUPLICATION_PREFIX:"; /** * @Author LiXiangrong * @Description 定义切点 * @Date 2023/04/03 8:53:11 * @Return void **/ @Pointcut("@annotation(com.risesun.common.core.annotation.RepeatSubmit)") public void preventDuplication() {} /** * @Author LiXiangrong * @Description 环绕方法 * @Date 2023/04/03 8:52:50 * @Param pjp * @Return java.lang.Object **/ @Around("NoRepeatSubmitAspect.preventDuplication()") public Object around(ProceedingJoinPoint pjp) throws Throwable { // 获取请求信息 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 获取执行方法 Method method = ((MethodSignature) pjp.getSignature()).getMethod(); //获取防重复提交注解 RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); // 获取authorization以及方法标记,生成redisKey和redisValue String authorization = request.getHeader(TokenConstants.AUTHENTICATION); String url = request.getRequestURI(); // 通过前缀 + url + token + 函数参数签名 来生成redis上的 key String redisKey = PREFIX.concat(url).concat(authorization).concat(getMethodSign(method, pjp.getArgs())); // 判断redisTemplate是否存在标记,如果没有,则是首次提交该请求,需要把设置标记并且正常返回 if (!redisTemplate.hasKey(redisKey) && Objects.nonNull(annotation)) { // 这个值只是为了标记,不重要 String redisValue = redisKey.concat(annotation.value()).concat(SIGN); // 设置防重复操作的限时标记(前置通知) redisTemplate.opsForValue().set(redisKey, redisValue, annotation.expireSeconds(), TimeUnit.SECONDS); try { // 正常执行方法并返回 ProceedingJoinPoint类型参数可以决定是否执行目标方法, // 环绕通知必须要有返回值,返回值即为目标方法的返回值 return pjp.proceed(); } catch (Throwable throwable) { //确保方法执行异常实时释放限时标记(异常后置通知) redisTemplate.delete(redisKey); throw throwable; } } else { throw new RuntimeException("数据正在处理,请勿重复提交!"); } } /** * @Author LiXiangrong * @Description 获取方法签名生成方法标记,采用数字签名算法SHA1对方法签名字符串加签 * @Date 2023/04/03 8:49:45 * @Param method * @Param args * @Return java.lang.String **/ private String getMethodSign(Method method, Object... args) { StringBuilder sb = new StringBuilder(method.toString()); for (Object arg : args) { sb.append(toString(arg)); } return DigestUtil.sha1Hex(sb.toString()); } /** * @Author LiXiangrong * @Description 对参数重写toString方法,避免空参造成的影响 * @Date 2023/04/03 8:50:58 * @Param arg * @Return java.lang.String **/ private String toString(Object arg) { if (Objects.isNull(arg)) { return "null"; } if (arg instanceof Number) { return arg.toString(); } return JSONUtil.toJsonStr(arg); } }
2024年01月03日
45 阅读
0 评论
0 点赞