springboot自定义注解实现防重复提交(服务缓存)

  • Post author:
  • Post category:其他


缓存基于redis

@Target(ElementType.METHOD,ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface RepeatSubmit {

    /**
     * 需要忽略的参数
     * @return
     */
    String[] ignoreParam() default {};

    /**
     * 
     * @return
     */
    String returnObj() default "";


    /**
     * 单位时间默认3秒
     * @return
     */
    long unitTime() default 3L;


    /**
     * 是否限制为同一ip
     * @return
     */
    boolean limitIp() default false;
}
@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {

    @Autowired
    private RedisClient redisClient;


    @Pointcut("@annotation(com.*类全路径*.RepeatSubmit)||@within(com.*类全路径*.RepeatSubmit)")
    public void cut() {
    }


    @Around("cut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        RepeatSubmit repeatSubmit = getAnnotation(proceedingJoinPoint);
        Object o = proceedingJoinPoint.proceed();
        if(Objects.isNull(repeatSubmit)){
            log.info("【repeatsubmit】缓存失败获取不到缓存目标annotation");
            return o;
        }

        String[] ignoreArr = repeatSubmit.ignoreParam();
        List ignoreList =  CollectionUtils.arrayToList(ignoreArr);
        String returnObj = repeatSubmit.returnObj();

        StringBuilder key = new StringBuilder("repeatCheck-");
        //类名
        String className = proceedingJoinPoint.getSignature().getDeclaringTypeName();
        //方法名称
        String methodName = proceedingJoinPoint.getSignature().getName();
        key.append(className);
        key.append(methodName);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(Objects.isNull(attributes)){
            log.info("【repeatsubmit】缓存失败获取不到缓存目标attributes");
            return o;
        }
        HttpServletRequest request = attributes.getRequest();
        Map<String, String[]> map = request.getParameterMap();
        //方法参数
        map.forEach((k,v) -> {
            if(!ignoreList.contains(k)){
                for (String s : v) {
                    key.append(s);
                }
            }
        });
        if(repeatSubmit.limitIp()){
            key.append(request.getRemoteHost());
        }
        long unitTime = repeatSubmit.unitTime();
        //检查是否为重复提交
        Object result =  redisClient.get(key.toString());
        if(Objects.isNull(result)){
            if(!StringUtils.hasText(returnObj)){
                redisClient.set(key.toString(), BaseResult.success(),unitTime);
            }else{
                redisClient.set(key.toString(), returnObj,unitTime);
            }

            redisClient.set(key.toString(), o ,unitTime);
            return o;
        }else{
            log.info("【repeatsubmit】从缓存中获取返回数据:{}",result);
            return result;
        }
    }

    /**
     * 获得注解
     * @param joinPoint
     * @return
     * @throws Exception
     */
    private static RepeatSubmit getAnnotation(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(RepeatSubmit.class);
        }
        return null;
    }

说明:单位时间内(unitTime)参数一样的重复请求会直接从redis中读取上次的缓存结果返回



版权声明:本文为bobjy_happybird原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。