ホームページ >データベース >Redis >SpringBoot が AOP+Redis を使用してフォームの繰り返し送信を防ぐ方法

SpringBoot が AOP+Redis を使用してフォームの繰り返し送信を防ぐ方法

PHPz
PHPz転載
2023-06-03 18:10:041106ブラウズ

    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 の構成と使用の最適化に注意する必要があります。パイプラインおよびその他のテクノロジー Redis のパフォーマンスを向上させます。

    以上がSpringBoot が AOP+Redis を使用してフォームの繰り返し送信を防ぐ方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。