接口重复提交 解决接口冥幂问题

注解类

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RabbitNoRepeatSubmit {
}

实现类

@Aspect
@Component
@Slf4j
public class RabbitNoRepeatSubmitAspect {

    @Autowired
    RabbitRedisService rabbitRedisService;

    @Autowired
    RabbitAuthenticationComponent rabbitAuthenticationComponent;

    @Around("execution(* com.zsxt..*Controller.*(..)) && @annotation(nrs)")
    public Object arround(ProceedingJoinPoint pjp, RabbitNoRepeatSubmit nrs) {

        // validator 参数检查
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            if (arg instanceof BindingResult) {
                BindingResult result = (BindingResult) arg;
                if (result.hasErrors()) {
                    StringBuilder messageBuilder = new StringBuilder();
                    result.getAllErrors().forEach(err -> messageBuilder.append(err.getDefaultMessage() + ","));
                    return new RabbitResponse("400",
                            messageBuilder.toString().substring(0, messageBuilder.toString().length() - 1), null);
                }

            }
        }

        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();

            String key = rabbitAuthenticationComponent.getUser().getUsername() + "-" + request.getServletPath();

            if (!rabbitRedisService.exists(key)) {
                rabbitRedisService.set(key, null, 3000L);
                Object o = pjp.proceed();
                return o;
            } else {
                log.error("重复提交");
                return new RabbitResponse(RabbitResponseEnums.REAPTE_SUBMIT);
            }

        } catch (Throwable e) {
            e.printStackTrace();
            log.error("验证重复提交时出现未知异常!");
            return new RabbitResponse(RabbitResponseEnums.SYS_ERROR);
        }

    }
}

调用

    @PostMapping("/create")
    @RabbitNoRepeatSubmit
    public Object create(@RequestBody @Valid SystemVo vo, BindingResult result) {

        boolean success = oauthSystemService.save(vo);

        if (!success) {
            return new RabbitResponse(RabbitResponseEnums.UPDATE_ERROR);
        }
        return new RabbitResponse(RabbitResponseEnums.SUCCESS);
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要防止接口重复提交,可以采取以下几种方式: 1. 生成唯一的请求标识:在每次请求中生成一个唯一的标识符(比如请求ID),并将其添加到请求的参数或者请求头部中。服务器端在处理请求时,可以根据该标识符进行判断,如果已经处理过相同标识符的请求,则拒绝重复提交。 2. 设置请求时间戳:在每次请求中添加一个时间戳字段,表示请求的时间。服务器端在接收到请求后,可以判断该时间戳与最近一次相同请求的时间戳进行比较,如果时间间隔太短,则认为是重复提交。 3. 使用令牌机制:在每次请求中,客户端需要携带一个有效的令牌(token)。服务器端在接收到请求后,验证令牌的有效性,并记录已经处理过的令牌。如果同一个令牌被重复提交,则拒绝重复请求。 4. 前端禁用按钮或者限制点击频率:在前端页面中,可以通过禁用按钮或者限制用户点击的频率来避免用户重复提交请求。比如,在用户点击按钮后,禁用按钮并设置一个短暂的计时器,在计时器结束前禁止再次点击。 5. 后端等性处理:在服务器端对接口进行等性处理,即使接收到重复的请求,也能保证结果的一致性。比如,对于写操作(如新增、修改),可以使用唯一标识符进行等性校验;对于查询操作,直接返回上一次请求的结果。 综合使用以上方法可以有效地防止接口重复提交问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值