防止重复提交的方式有很多
可以用数据库的唯一索引,保证数据完整性
在业务层用select....for update,依然是使用数据库的事务来做的
使用注解+拦截器 HandlerIntercetper+redis
我这里使用注解+aop+redis。
1、注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Resubmit { int interval() default 5; // s 单位为秒,x秒内防止重复提交 }
2、切面实现,
@Aspect @Component public class ResubmitAspect { private final static String CACHE_KEY = "resubmit:"; @Resource private CacheComponent cacheComponent; @Around(value = "@annotation(resubmit)") public Object around(ProceedingJoinPoint point, Resubmit resubmit) throws Throwable { ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); Object loginUser = ThreadLocalConst.getLoginUser(); String username = null; if(Objects.nonNull(loginUser)){ username = ThreadLocalConst.getUserId().toString(); }else { username = ThreadLocalConst.getRequestIp(); }
// 这里用于redis缓存的key用的是,已经登录的userId + 请求方法 + 请求路径。没登录就用ip地址。
// 可以用getSignature() 是方法的全限定名称 String cacheKey = CACHE_KEY + username + request.getMethod() + request.getRequestURI(); String shortString = point.getSignature().toShortString(); Boolean success = cacheComponent.setNx(cacheKey, shortString, resubmit.interval(), TimeUnit.SECONDS); // redis的setNx 命令,保证原子性 if(success){ Object result = point.proceed(); return result; }else { throw new BizException("请勿重复提交"); } } }
3、使用
@PutMapping @Resubmit public JsonResult<Boolean> save(@Validated @RequestBody EnterpriseRecheckEditRequest request){ return JsonResult.success(enterpriseRecheckService.add(request)); }
对比是否是同一数据重复提交,判断方式还可以加入请求参数
标签:java,String,request,redis,resubmit,Aop,注解,public From: https://www.cnblogs.com/junnnnnnnn/p/16892297.html