使用自定义注解阻止短时间内的重复提交
思路:
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里面有值,即为重复提交,这是就会终止方法的执行,返回一个异常提示不要重复提交。