使用SpringBoot自定义注解+AOP+redis来实现防接口幂等性重复提交
·
前提:整合好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博客
更多推荐


所有评论(0)