java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java幂等性校验

Java实现幂等性校验的示例代码

作者:名一

我们在做web应用的时候通常会遇到前端提交按钮重复点击的场景,在某些新增操作上就需要做幂等性限制来保证数据的可靠性,所以本文主要介绍了如何使用java aop实现幂等性校验,需要的可以参考下

我们在做web应用的时候通常会遇到前端提交按钮重复点击的场景,在某些新增操作上就需要做幂等性限制来保证数据的可靠性。下面来用java aop实现幂等性校验。

一:首先我们需要一个自定义注解

package com.yuku.yuku_erp.annotation;

import java.lang.annotation.*;

/**
 * @author 名一
 * @ClassName IdempotentAnnotation
 * @description: 用来标记需要校验幂等性的接口
 * @datetime 2024年 02月 03日 14:48
 * @version: 1.0
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IdempotentAnnotation {
    String idempotentType();
}

二:创建一个幂等校验的切面类

package com.yuku.yuku_erp.aop;

import com.yuku.yuku_erp.annotation.IdempotentAnnotation;
import com.yuku.yuku_erp.constant.RedisKeyConstant;
import com.yuku.yuku_erp.exception.MyException;
import com.yuku.yuku_erp.utils.RedisShardedPoolUtil;
import com.yuku.yuku_erp.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author 名一
 * @ClassName CheckIdempotentAop
 * @description: 幂等性校验
 * @datetime 2024年 02月 03日 14:59
 * @version: 1.0
 */
@Slf4j
@Aspect
@Component
public class CheckIdempotentAop {

    @Pointcut("execution(* com.yuku.yuku_erp.controller..*.*(..))")
    public void checkCut(){
    }

    @Before("checkCut()")
    public void checkIdempotent(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        if (method.isAnnotationPresent(IdempotentAnnotation.class)){
            IdempotentAnnotation annotation = method.getAnnotation(IdempotentAnnotation.class);
            String idempotentType = annotation.idempotentType();
            String idempotentToken = TokenUtil.getRequest().getHeader("idempotentToken");
            String idemToken = idempotentType + idempotentToken;
            log.info("checkIdempotent idempotentType:{}, idempotentToken:{}", idempotentType, idempotentToken);

            Boolean flag = RedisShardedPoolUtil.sismember(RedisKeyConstant.IDEMPOTENT_TOKEN_LIST, idemToken);
            if (!flag){
                log.error("checkIdempotent error idempotentType:{}, idempotentToken:{}, flag:{}", idempotentType, idempotentToken, flag);
                throw new MyException("该接口已提交过,请不要重复提交");
            }
            RedisShardedPoolUtil.delSetByValue(RedisKeyConstant.IDEMPOTENT_TOKEN_LIST, idemToken);
            log.info("checkIdempotent idempotentType:{}, idempotentToken:{}, flag:{}", idempotentType, idempotentToken, flag);
        }
    }
}

三:在需要切面的接口上使用幂等校验注解

@IdempotentAnnotation(idempotentType = "checkIdempotentToken")
    @GetMapping("/checkIdempotentToken")
    @ApiOperation(value = "校验幂等性示例")
    public CommonResult<String> checkIdempotentToken(){
        return CommonResult.success();
    }

到此幂等校验就完成了

四:方法补充

除了上文的方法,小编还为大家整理了其他实现幂等校验的方法,希望对大家有所帮助

1.唯一标识符校验

一种简单的方式是使用唯一标识符来校验请求的幂等性,每次请求时,客户端生成一个唯一的标识符,并将其作为请求的一部分发送给服务器。服务器在接收到请求后先检查该标识符是否已经存在,如果存在则认为是重复请求,直接忽略;如果不存在,则执行相应的业务逻辑,并将标识符保存到一个幂等性校验表中

下面是一个使用 UUID 实现的示例代码:

// 生成唯一标识符
String requestId = UUID.randomUUID().toString();

// 发送清求
HttpResponse response = httpClient.execute(request);

// 检查响应结果
if (response.getStatusLine().getStatusCode() == 200){
    // 保存标识符到幂等性校验表
    idempotentTable.put(requestId, true);
}

2. Token 校验

另一种方式是使用 Token 来校验请求的幂等性。服务器在第一次收到请求时,在响应中返回一个唯一的 Token 给客户端,客户端在下次请求时将该 Token 作为请求的一部分发送给服务器。服务器在接收到请求后,先检查该 Token 是否有效,如果有效则执行相应的业务逻辑,并将 Token 标记为已使用;如果无效则忽略该请求。

下面是一个使用 Token 实现的示例代码:

// 发送第一次诗求,并获 Token
HttpResponse response1 = httpClient.execute(request);
String token = response1.getFirstHeader("Token").getValue();

// 发送第二次诗求,并附 Token
request.addHeader("Token",token);
HttpResponse response2 = httpClient.execute(request);

// 检查响应结果
if (response2.getStatusLine().getstatusCode() == 200) {
    // 标记 Token 为已使用
    tokenService.markAsUsed(token);
}

到此这篇关于Java实现幂等性校验的示例代码的文章就介绍到这了,更多相关Java幂等性校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文