spring接口重放過濾問題

1、定義註釋

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface AvoidRepeatRequest {
    /** 請求間隔時間,單位秒,該時間範圍內的請求爲重複請求 */
    int intervalTime() default 3;

    /** 是否根據參數進行校驗 */
    boolean checkParameter() default false;

    /** 是否根據用戶進行校驗 */
    boolean checkUser() default true;

    /** 返回的提示信息 */
    String msg() default "請不要頻繁重複請求!";
}

2、添加過濾器

import com.alibaba.fastjson.JSON;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
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.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description : 重複請求過濾器
 * @Author : cxw
 * @Date : 2022/11/30 10:56
 * @Version : 1.0
 **/
@Component
@Aspect
@Order(100)
public class RepeatRequestFilter {

    Logger logger= LoggerFactory.getLogger(RepeatRequestFilter.class);

    ExpiringMap<String,String> cacheMap = ExpiringMap.builder()
            //設置最大值,添加第101個entry時,會導致第1個立馬過期(即使沒到過期時間)
            .maxSize(100000)
            //設置每個key有效時間60s,如果key不設置過期時間,key永久有效
            .expiration(60, TimeUnit.SECONDS)
            //允許更新過期時間值,如果不設置variableExpiration,不允許後面更改過期時間,一旦執行更改過期時間操作會拋異常UnsupportedOperationException
            .variableExpiration()
            //CREATED:只在put和replace方法清零過期時間
            //ACCESSED:在CREATED策略基礎上增加 在還沒過期時get方法清零過期時間。
            //清零過期時間也就是重置過期時間,重新計算過期時間
            .expirationPolicy(ExpirationPolicy.CREATED)
            .build();



    private static final String SUFFIX = "C_";

    // 定義 註解 類型的切點
    @Pointcut("@annotation(com..api.common.annotation.AvoidRepeatRequest)")
    public void arrPointcut() {}

    // 實現過濾重複請求功能
    @Around("arrPointcut()")
    public Object arrBusiness(ProceedingJoinPoint joinPoint) throws Throwable {
        // 獲取 redis key,由 session ID 和 請求URI 構成
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        String key = SUFFIX + "_" + request.getRequestURI();

        // 獲取方法的 AvoidRepeatRequest 註解
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        AvoidRepeatRequest arr = method.getAnnotation(AvoidRepeatRequest.class);
        if(arr!=null&&arr.checkUser()){
                key+="_"+ request.getSession().getId();
        }
        if(arr!=null&&arr.checkParameter()){
            Map<String, Object> nameAndValue = ParameterNameUtils.getNameAndValue(joinPoint);
            if(nameAndValue!=null&&nameAndValue.size()>0){
                key+="_"+ JSON.toJSONString(nameAndValue);
            }
        }
        // 判斷是否是重複的請求
        if (arr!=null&&continceKey(key,arr.intervalTime())) {
            throw new Exception("提示:"+arr.msg());
        }

        return joinPoint.proceed();
    }

    /**
     * 驗證
     * @param key
     * @param intervalTime
     * @return
     */
    private boolean continceKey(String key, int intervalTime) {
        String s = cacheMap.get(key);
        cacheMap.put(key,"v",intervalTime,TimeUnit.SECONDS);
        if(s!=null){
            return true;
        }
        return false;
    }
}

3、使用

@AvoidRepeatRequest(intervalTime = 30, msg = "不允許重複提交",checkParameter = true,checkUser = false)

 

 4、引用

        <!-- 過期map -->
        <dependency>
            <groupId>net.jodah</groupId>
            <artifactId>expiringmap</artifactId>
            <version>0.5.9</version>
        </dependency>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章