All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.acyou.leo.framework.aspect.AccessLimitAspect Maven / Gradle / Ivy

package cn.acyou.leo.framework.aspect;


import cn.acyou.leo.framework.annotation.AccessLimit;
import cn.acyou.leo.framework.constant.CommonErrorEnum;
import cn.acyou.leo.framework.constant.Constant;
import cn.acyou.leo.framework.model.Result;
import cn.acyou.leo.framework.util.ElParser;
import cn.acyou.leo.framework.util.Md5Util;
import cn.acyou.leo.framework.util.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 防止重复提交切面
 *
 * use support {@link AccessLimit}
 *
 * @author fangyou
 * @version [1.0.0, 2021-09-26 18:01]
 */
@Slf4j
@Aspect
@Component
public class AccessLimitAspect {
    //标识 prefix
    private static final String ACCESS_LIMIT_KEY_PREFIX = "ACCESS_LIMIT:";

    @Autowired
    private RedisUtils redisUtils;

    @Pointcut("@annotation(accessLimit)")
    public void pointCut(AccessLimit accessLimit) {

    }

    @Around("pointCut(accessLimit)")
    public Object around(ProceedingJoinPoint joinPoint, AccessLimit accessLimit) throws Throwable {
        String keyValue = getKeyValue(joinPoint, accessLimit.value());
        long accessInterval = accessLimit.interval();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();
        String path = request.getServletPath();
        String token = request.getHeader(Constant.HeaderEnum.TOKEN_NAME);
        StringBuilder keyBuffer = new StringBuilder(path);
        if (StringUtils.hasText(token)) {
            keyBuffer.append(token);
        }
        keyBuffer.append("ARGS:");
        keyBuffer.append(Md5Util.md5(keyValue));
        if (accessInterval == -1) {
            //设置 1 小时 :3600000
            accessInterval = 60 * 60 * 1000;
        }
        //Redis setNx
        Boolean aBoolean = redisUtils.setIfAbsent(keyBuffer.toString(), "1", accessInterval, TimeUnit.MILLISECONDS);
        if (!aBoolean) {
            log.error("接口访问限制 |访问最低间隔:{}", accessLimit.interval());
            if (accessLimit.interval() == -1) {
                return Result.error(CommonErrorEnum.CONCURRENT_ERROR);
            } else {
                return Result.error(CommonErrorEnum.ACCESS_LIMIT);
            }
        }
        try {
            return joinPoint.proceed();
        } finally {
            redisUtils.delete(keyBuffer.toString());
        }
    }

    public String getKeyValue(ProceedingJoinPoint joinPoint , String express) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();
        DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        String[] parameterNames = discoverer.getParameterNames(method);
        return ACCESS_LIMIT_KEY_PREFIX + signature.getDeclaringTypeName() + ":" + methodName + ":" + ElParser.getKey(express, parameterNames, joinPoint.getArgs());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy