使用自定义注解阻止短时间内的重复提交

思路:
1、自定义IdempotentAop注解。
2、把注解标注在controller层方法上。
3、进行前置增强业务的编写。
 
详细如下:
1、自定义IdempotentAop注解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface IdempotentAop {
}
@Retention可以定义的值有三个
RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
@Target可以定义的值有十个
ElementType.TYPE:类、接口(包括注解类型)和枚举的声明
ElementType.FIELD:字段声明(包括枚举常量)
ElementType.METHOD:方法声明
ElementType.PARAMETER:参数声明
ElementType.CONSTRUCTOR:构造函数声明
ElementType.LOCAL_VARIABLE:本地变量声明
ElementType.ANNOTATION_TYPE:注解类型声明
ElementType.PACKAGE:包声明
ElementType.TYPE_PARAMETER:类型参数声明,JavaSE8引进,可以应用于类的泛型声明之处
ElementType.TYPE_USE:JavaSE8引进,此类型包括类型声明和类型参数声明,是为了方便设计者进行类型检查
 
2、把注解标注在controller层方法上。
@IdempotentAop
@RequestMapping(value = "/updateChannelAdvertiser",
        produces = {"application/json"},
        consumes = {"application/json"},
        method = RequestMethod.POST)
public ResponseEntity<String> updateChannelAdvertiser(HttpServletRequest request, @RequestBody String json) {
}
3、进行前置增强业务的编写。
 
@Aspect
@Component
@Slf4j
public class ControllerIdempotent {

    @Autowired
    private JedisManager jedisManager;
    private static final String PRE_REDIS_KEY="IDEMPOTENT:";
    private static final int dbIndex=1;

    @Before("@annotation(com.xx.aop.IdempotentAop)")
    public void privilege(JoinPoint jp) {
        //方法
        Signature signature = jp.getSignature();
        //参数
        Object[] args = jp.getArgs();
        String s = MD5Utils.md5BySalt_OnlySecond(args[1].toString());
        String currentKey=PRE_REDIS_KEY+signature.getName()+":"+s;

        Jedis jedis =null;
        try {
            jedis = jedisManager.getJedis();
            jedis.select(dbIndex);
            String set = jedis.set(currentKey, "1", "NX", "EX", 30);
            if (set==null){
                throw new OpenApiException("请勿重复提交 !");
            }
        }finally {
            if (jedis!=null){
                jedis.close();
            }
        }
    }
}
这里@Before("@annotation(com.xx.aop.IdempotentAop)")的@Before代表着进行前置增强的,里面的@annotation(com.xx.aop.IdempotentAop)代表进行基于注解的扫描。
具体实现就是把PRE_REDIS_KEY加上signature.getName()(方法名称)+":"+s(请求json的md5加密字符串)作为key进行redis的set,过期时间设置为30s。
如果set返回为null代表这个key里面有值,即为重复提交,这是就会终止方法的执行,返回一个异常提示不要重复提交。
posted @ 2020-12-21 18:42  alwaysFly  阅读(249)  评论(0编辑  收藏  举报