贝利信息

SpringBoot怎么使用AOP+Redis防止表单重复提交

日期:2023-06-03 00:00 / 作者:PHPz

配置Redis

1. 添加Redis依赖


    org.springframework.boot
    spring-boot-starter-data-redis

2. 添加redis配置信息

redis:
  host: 127.0.0.1
  port: 6379
  database: 0
  password:
  # 连接超时时间
  timeout: 10s

配置AOP

1. 自定义注解

/**
 * 防止表单重复提交注解
 */
@Target(ElementType.METHOD) // 注解的作用目标为方法
@Retention(RetentionPolicy.RUNTIME) // 注解的保留期限为运行时
public @interface PreventDuplicateSubmission {
    /**
     * 时间(s)
     */
    int time() default 3;
}

2. AOP切面

@Aspect // 表明这是一个切面类
@Component // 表示这是一个Bean
public class DuplicateSubmissionAspect {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
// 定义切入点,即标注了@PreventDuplicateSubmission注解的方法
    @Pointcut("@annotation(com.example.demo.annotation.PreventDuplicateSubmission)")
    public void preventDuplicateSubmission() {
    }

    @Around("preventDuplicateSubmission()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String requestURI = request.getRequestURI();
        String key = requestURI + ":" + JSON.toJSONString(request.getParameterMap());

        if (stringRedisTemplate.hasKey(key)) { // 如果Redis中已存在该请求
            throw new RuntimeException("请勿重复提交");
        }
        // 获取注解的参数
        PreventDuplicateSubmission formSubmission = ((MethodSignature) pjp.getSignature()).getMethod().getAnnotation(PreventDuplicateSubmission.class);
        int time = formSubmission.time();
        // 设置请求的key和value,有效期为3秒
        stringRedisTemplate.opsForValue().set(key, "1", time, TimeUnit.SECONDS);
        return pjp.proceed();
    }
}

在上面的代码中,我们使用了spring boot提供的stringredistemplate来连接redis,可以直接通过@autowired注解来注入该对象。在@around注解中,我们使用stringredistemplate.haskey()方法来检查redis中是否已存在该请求,如果存在,则抛出异常;如果不存在,则使用stringredistemplate.opsforvalue().set()方法将该请求存储到redis中,同时设置过期时间为3秒。

注意事项

使用Redis存储请求需要注意以下几点: