麻了,5年Java竟然不知道幂等......

在分布式系统中,接口幂等性是确保操作一致性的关键特性。

啥是幂等性

幂等性 指的是在给定的条件下,无论操作执行多少次,其结果都保持不变。在接口设计中,幂等性意味着使用相同的参数多次调用接口,应产生与单次调用相同的效果。

图片

CRUD操作的幂等性分析

  • 查询(Read):通常幂等,但若依赖可变数据,则可能非幂等。

  • 创建(Create):天然幂等,重复创建相同记录应避免或处理。

  • 更新(Update):理论上幂等,但如基于前一状态的增量更新则非幂等。

  • 删除(Delete):天然幂等,重复删除相同记录应直接返回成功。

接口幂等与防抖的区别

  • 防抖:防止用户在短时间内重复触发操作,通常用于前端。

  • 幂等性:确保后端接口在重复调用时保持一致性。

Demo

定义Idempotent注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Idempotent {
    String key() default "#root.methodName + #root.args";
    int expireTime() default 60; // 过期时间,默认60秒
    TimeUnit timeUnit() default TimeUnit.SECONDS;
    String info() default "操作过于频繁,请稍后再试";
    boolean delKeyAfterSuccess() default true; // 成功后是否删除key
}

AOP实现幂等性检查

@Aspect
@Component
public class IdempotentAspect {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Around("@annotation(idempotent)")
    public Object around(ProceedingJoinPoint joinPoint, Idempotent idempotent) throws Throwable {
        String key = generateKey(joinPoint, idempotent);
        boolean isExecuted = redisTemplate.hasKey(key);
        if (isExecuted) {
            throw new RuntimeException(idempotent.info());
        }
        redisTemplate.opsForValue().set(key, "executed", idempotent.expireTime(), idempotent.timeUnit());
        Object result = joinPoint.proceed();
        if (idempotent.delKeyAfterSuccess()) {
            redisTemplate.delete(key);
        }
        return result;
    }

    private String generateKey(JoinPoint joinPoint, Idempotent idempotent) {
        EvaluationContext context = new StandardEvaluationContext();
        String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }
        return ExpressionUtils.evaluateStringExpression(idempotent.key(), context);
    }
}

使用Idempotent注解

@RestController
public class TestController {

    @PostMapping("/test")
    @Idempotent(expireTime = 30, info = "请求太频繁,请稍后再试", delKeyAfterSuccess = true)
    public ResponseEntity<?> testMethod(@RequestParam String param) {
        // 业务逻辑...
        return ResponseEntity.ok("操作成功");
    }
}

通过定义专用的注解和使用AOP,我们能够以一种声明式的方式实现接口幂等性。这种方法不仅代码侵入性低,而且易于维护和扩展。

欢迎关注我的公众号“程序员洋哥”,原创技术文章第一时间推送。

图片

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值