1 创建IIdempotent
@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface IIdempotent { }
2 创建aop
@Component @Aspect public class IdempotentAction {public final static String ERROR_REPEATSUBMIT = "Repeated submission";//redis @Autowiredprotected StringRedisTemplate idempotentTemplate;//配置接入点,如果不知道怎么配置,可以百度一下规则@Pointcut("execution(* com.kps.webAPI*.controller..*.*(..))&&@annotation(com.kps.web.aop.Idempotent.IIdempotent)")private void controllerAspect() {}//成功处理请求@AfterReturning("controllerAspect()")public void AfterReturning(JoinPoint jp) throws Exception {IdempotentCheck(jp, ComContants.OP_RESULT[1]);}//后置异常通知@AfterThrowing("controllerAspect()")public void AfterThrowing(JoinPoint jp) throws Exception{IdempotentCheck(jp,ComContants.OP_RESULT[2]);}private void IdempotentCheck(JoinPoint jp, String opResult) throws Exception {String controllerName = jp.getTarget().getClass().getName();controllerName = controllerName.substring(controllerName.lastIndexOf(".") + 1);Signature sig = jp.getSignature();MethodSignature msig = (MethodSignature) sig;// 获得被拦截的方法Method method = msig.getMethod();// webUI控制器 @Controller注解IIdempotent systemlog = method.getAnnotation(IIdempotent.class);HttpServletRequest request = WebUtil.getHttpServletRequest();String body = NetUtil.getBodyString(request);String signMD5= MD5.md5(body);if (Boolean.parseBoolean(idempotentTemplate.opsForValue().get(signMD5))) {throw new ErrorSignException(ERROR_REPEATSUBMIT);} else {idempotentTemplate.opsForValue().set(signMD5, "true", ComContants.IDEMPOTENT_EXTIME, TimeUnit.SECONDS);}} }
测试:
//幂等apo,测试实例,30秒不可重复提交相同数据 @IIdempotent@RequestMapping(value = "test", method = RequestMethod.POST)public ApiResult<String> test(@RequestBody ApiRequest<String> requestVO) {ApiResult<String> r = new ApiResult<String>();r.setData(requestVO.getData());r.setCodeToSuccessed();return r;}