赞
踩
前提:整合好springboot + redis环境,可参考博文
springboot 整合redis-CSDN博客
0 添加aop依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-aop</artifactId>
- </dependency>
1 编写自定义注解,注解的作用是标记一个方法是否支持幂等性
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Idempotent {
- long expire() default 2L;
- }
2 AOP切面逻辑,来判断一个方法是否被标记了该注解。如果被标记了该注解,那么就需要对该方法进行特殊处理,以实现幂等性
- @Aspect
- @Component
- public class IdempotentAspect {
-
- private final RedisTemplate redisTemplate;
-
- @Autowired
- public IdempotentAspect(RedisTemplate redisTemplate) {
- this.redisTemplate = redisTemplate;
- }
-
- @Around("@annotation(com.example.demo.annotation.Idempotent)")
- public Object idempotent(ProceedingJoinPoint joinPoint) throws Throwable {
- // 获取请求参数
- Object[] args = joinPoint.getArgs();
- // 获取请求方法
- MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- Method method = signature.getMethod();
- // 获取注解信息
- Idempotent idempotent = method.getAnnotation(Idempotent.class);
- String key = getKey(joinPoint);
- // 判断是否已经请求过
- if (redisTemplate.hasKey(key)) {
- throw new RuntimeException("请勿重复提交");
- }
- // 标记请求已经处理过
- redisTemplate.opsForValue().set(key, "1", idempotent.expire(), TimeUnit.SECONDS);
- // 处理请求
- return joinPoint.proceed(args);
- }
-
- /**
- * 获取redis key
- */
- private String getKey(ProceedingJoinPoint joinPoint) {
- MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- Method method = signature.getMethod();
- String methodName = method.getName();
- String className = joinPoint.getTarget().getClass().getSimpleName();
- Object[] args = joinPoint.getArgs();
- StringBuilder sb = new StringBuilder();
- sb.append(className).append(":").append(methodName);
- for (Object arg : args) {
- sb.append(":").append(arg.toString());
- }
- return sb.toString();
- }
- }
3 示例测试
- @RestController
- public class DemoController {
-
- @Autowired
- private TBookOrderMapper tBookOrderMapper;
-
- @GetMapping("/demo")
- @Idempotent(expire = 60)
- public String demo(@RequestBody TBookOrder tBookOrder) {
- // 处理请求
- int insert = tBookOrderMapper.insert(tBookOrder);
- return insert==1?"ok":"wrong";
- }
- }
参考博文
SpringBoot自定义注解+AOP+redis实现防接口幂等性重复提交,从概念到实战_aop防重复提交-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。