防重复提交解决方案
基于springboot切面
package com.minex.handler.aop; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) // 可以标记在方法上 @Retention(RetentionPolicy.RUNTIME) // 在运行时通过反射来读取 public @interface NoRepeatSubmit { // 可以设置一些参数,例如过期时间等,这里简化处理 String keyPrefix() default "v3:NoRepeatSubmit:"; int expire() default 2; // 默认为2秒 }
package com.minex.handler.aop; import cn.hutool.core.util.StrUtil; import com.minex.common.exception.ExceptionFactory; import com.minex.manager.RemoteCacheManager; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.Objects; import java.util.concurrent.TimeUnit; @Aspect @Component public class NoRepeatSubmitAspect { @Resource private RemoteCacheManager remoteCacheManager; @Resource public RedisTemplate redisTemplate; @Around("@annotation(noRepeatSubmit)") public Object around(ProceedingJoinPoint point, NoRepeatSubmit noRepeatSubmit) throws Throwable { return handleCheck(point, noRepeatSubmit); } private Object handleCheck(ProceedingJoinPoint point, NoRepeatSubmit noRepeatSubmit) throws Throwable { String keyPrefix = noRepeatSubmit.keyPrefix(); Integer expire = noRepeatSubmit.expire(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); // 构建key,可以根据实际情况设计,这里简单使用请求URL和请求方法作为key String key = buildKey(keyPrefix, request); // 检查Redis中是否存在该key boolean exists = redisTemplate.hasKey(key); if (!exists) { remoteCacheManager.setCacheObject(key, "1", expire, TimeUnit.SECONDS); // 如果key不存在,则认为是有效请求,继续执行 return point.proceed(); } else { // 如果key已存在,则认为是重复请求 并且刷新过期时间 remoteCacheManager.expire(key, expire, TimeUnit.SECONDS); throw ExceptionFactory.bizException("请勿重复提交," + expire + "秒内不能重复提交"); } } private String buildKey(String prefix, HttpServletRequest request) { // 根据实际情况构建key,这里以请求的URL和HTTP方法为基础 String uri = request.getRequestURI(); String method = request.getMethod(); String token = request.getHeader("authorization"); if (StrUtil.isNotEmpty(token)) { return prefix + ":" + uri + ":" + method + ":" + token; } else { return prefix + ":" + uri + ":" + method; } } }
使用示例
⎛⎝官萧何⎠⎞一只快乐的爪哇程序猿;邮箱:1570608034@qq.com