首頁  >  文章  >  資料庫  >  SpringBoot怎麼使用AOP+Redis防止表單重複提交

SpringBoot怎麼使用AOP+Redis防止表單重複提交

PHPz
PHPz轉載
2023-06-03 18:10:041073瀏覽

    設定Redis

    1. 新增Redis依賴

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    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儲存要求需要注意以下幾點:

    • Redis需要單獨部署,不要將Redis和應用程式部署在同一台機器上。

    • Redis的效能相對於記憶體儲存方式可能​​會下降,需要根據實際情況進行測試和最佳化。

    • 如果Redis中出現異常,可能會影響到應用程式的正常運行,需要增加對應的容錯機制。

    • Redis儲存請求需要考慮到並發問題,可以使用Redis的分散式鎖定來解決。

    • 如果應用程式中需要頻繁地進行Redis操作,可能會導至Redis的效能下降,因此需要注意優化Redis的配置和使用方式,例如使用Redis Pipeline等技術來提高Redis的效能。

    #

    以上是SpringBoot怎麼使用AOP+Redis防止表單重複提交的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除