インターフェースの冪等性に対する解決策

1. フロントエンドのアンチヘビー

フロントエンドの重複防止によって冪等性を確保することが最も簡単な実装方法であり、フロントエンド関連のプロパティと JS コードを設定できます。信頼性は良くありませんが、経験豊富な担当者はツールを使用してページをスキップしても繰り返し送信できます。主にフォームの繰り返し送信やボタンの繰り返しクリックに適しています。

2.PRGモード

PRG モードは POST-REDIRECT-GET です。ユーザーがフォームを送信すると、元のフォーム ページに留まるのではなく、送信が成功した別のページにリダイレクトされます。これにより、ユーザーの更新による繰り返しの送信が回避されます。同時に、ブラウザの進む/戻るボタンを使用してフォームが繰り返し送信されるのを防ぎます。これは比較的一般的なフロントエンドのアンチヘビー戦略です

3. 固有の識別(トークンメカニズム)

1. ソリューションの紹介: 固有の識別メカニズムを通じて冪等性を確保することは非常に一般的なソリューションであり、ほとんどのシナリオにも適しています。このソリューションを完了するには、フロントエンドとバックエンドの間である程度の対話が必要です。

画像の説明を追加してください
2. プロセスは次のとおりです。

  1. サーバーは、クライアントが使用するトークン取得インターフェイスを提供します。サーバーがトークンを生成した後、現在のアーキテクチャが分散されている場合は redis にトークンが保存されますが、単一のアーキテクチャの場合は jvm キャッシュに保存されます。
  2. クライアントがトークンを取得すると、そのトークンを使用してリクエストを開始します。
  3. クライアント要求を受信した後、サーバーはまずトークンが Redis に存在するかどうかを判断します。存在する場合は、トークンを削除して業務処理を終了します。存在しない場合は、現在のリクエストが繰り返しのリクエストであることを意味し、対応する ID がクライアントに直接返されます。

4. 固有識別の実現(トークン機構)

1. カスタム ビジネス プロセスの実装に基づく (コードは無視される)
ここに画像の説明を挿入します
2. アノテーション メソッドに基づく

トークン実装をメソッドに直接埋め込むと、多くの重複コードが発生します。したがって、上記のコードはカスタム アノテーションを通じて変換できます。冪等である必要があるメソッドにカスタム アノテーションを追加するだけです。

3. 注釈を定義する

/**
* 幂等性注解
*/
@Target({
    
    ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Idemptent {
    
    
}

4. 新しいインターセプターを作成する

public class IdempotentInterceptor implements HandlerInterceptor {
    
    

    @Resource
    private RedisTemplate redisTemplate;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        if (!(handler instanceof HandlerMethod)){
    
    
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Idempotent annotation = method.getAnnotation(Idempotent.class);
        if (annotation != null){
    
    
            //幂等性校验
            checkToken(request);
        }
        return true;
    }

    private void checkToken(HttpServletRequest request) {
    
    

        //获取token
        String token = request.getHeader("token");

        if (StringUtils.isEmpty(token)){
    
    
            throw new RuntimeException("非法参数");
        }

        Boolean deleteResult = redisTemplate.delete(token);
        if (!deleteResult){
    
    
            //重复请求
            throw new RuntimeException("重复请求");
        }
    }
}

5. スタートアップ クラスは WebMvcConfigurerAdapter を継承し、次のコードを追加します。

 @Bean
 public IdempotentInterceptor idempotentInterceptor(){
    
    
     return new IdempotentInterceptor();
 }

 @Override
 public void addInterceptors(InterceptorRegistry registry) {
    
    
     registry.addInterceptor(idempotentInterceptor());
     super.addInterceptors(registry);
 }

おすすめ

転載: blog.csdn.net/weixin_44702984/article/details/131603200