Skip to content

幂等模块

鸣谢

本功能最初由 Gitee@Gyq灬明 大佬提交 PR,感谢大佬的开源贡献。

PR:https://gitee.com/continew/continew-starter/pulls/41

简介

continew-starter-idempotent 是 ContiNew Starter 提供的基于 AOP + 注解 结合 Redis 实现的分布式幂等模块,提供开箱即用的分布式幂等解决方案。

主要特性

  • 开箱即用:基于 AOP + 注解 结合 Redis 的分布式幂等实现
  • 提供 SpEL 表达式支持,支持动态解析请求参数进行幂等 key 配置
    • 示例:@Idempotent(key = "#userId")
  • 提供默认的 name 生成器

使用步骤

引入依赖

xml
<dependency>
    <groupId>top.continew.starter</groupId>
    <artifactId>continew-starter-idempotent</artifactId>
</dependency>

全局配置

配置详情请查看:top.continew.starter.idempotent.autoconfigure.IdempotentProperties

yaml
--- ### 幂等配置
continew-starter:
  idempotent:
    # 是否启用(默认:已启用)
    enabled: true
    # 幂等统一 Key 前缀(默认:Idempotent)
    key-prefix: Idempotent

使用 @Idempotent 注解

在需要幂等处理的接口上添加 top.continew.starter.idempotent.annotation.Idempotent 注解。

java
@Operation(summary = "创建用户")
@PostMapping
@Idempotent(key = "#req.username")
public R createUser(@Valid @RequestBody UserReq req) {
    // ...略 
}

@Idempotent 注解

java
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {

    /**
     * 名称
     */
    String name() default "";

    /**
     * 键(支持 Spring EL 表达式)
     */
    String key() default "";

    /**
     * 超时时间
     */
    int timeout() default 1000;

    /**
     * 时间单位(默认:毫秒)
     */
    TimeUnit unit() default TimeUnit.MILLISECONDS;

    /**
     * 提示信息
     */
    String message() default "请勿重复操作";
}

IdempotentNameGenerator 接口

top.continew.starter.idempotent.generator.IdempotentNameGenerator 是幂等名称生成器接口,当 @Idempotent 注解的 name 属性为空时用于生成幂等名称。

java
public interface IdempotentNameGenerator {

    /**
     * 生成幂等名称
     *
     * @param target 目标实例
     * @param method 目标方法
     * @param args   方法参数
     * @return 幂等名称
     */
    String generate(Object target, Method method, Object... args);
}

v2.12.1 开始我们默认提供了 DefaultIdempotentNameGenerator 实现(根据方法名、方法参数等生成幂等名称),如果不满足你的需要,可自行重写 IdempotentNameGenerator 接口来实现自定义幂等名称生成器,然后在 Spring 容器中提供 IdempotentNameGenerator Bean 即可。

理论上你肯定要重新实现 IdempotentNameGenerator 接口,最初我们就没有提供,因为幂等场景肯定要增加当前用户信息,比如当前用户的 Token,而我们在 starter 内是无法直接获取到这类信息的。

java
@Configuration
public class GlobalConfiguration {

    /**
     * 幂等名称生成器
     */
    @Bean
    public IdempotentNameGenerator nameGenerator() {
        return new MyIdempotentNameGenerator();
    }
}

核心依赖

依赖描述
top.continew:continew-starter-cache-redisson缓存模块
cn.hutool:hutool-cryptoHutool 加密解密模块(封装 JDK 中加密解密算法)