首页
友链
统计
留言
关于
Search
1
网站声明
53 阅读
2
Java生成二维码——基于Google插件
50 阅读
3
Java使用poi-tl动态生成word和pdf
31 阅读
4
循环单链表及其实现
28 阅读
5
双链表及其实现
28 阅读
默认分类
Java
C语言
数据库技术
Linux
前端
其他
登录
/
注册
Search
标签搜索
C语言
数据结构
Java
Spring
数据库技术
MySQL
设计模式
策略模式
工厂模式
IDEA
SpringMVC
AOP
MybatisPlus
POI
easyExcel
LiXiangrong
累计撰写
56
篇文章
累计收到
4
条评论
首页
栏目
默认分类
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日
13 阅读
0 评论
0 点赞