首页 > 其他分享 >spring接口重放过滤问题

spring接口重放过滤问题

时间:2022-12-02 12:23:39浏览次数:42  
标签:lang 过期 spring 接口 过滤 key import org annotation

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>

 

标签:lang,过期,spring,接口,过滤,key,import,org,annotation
From: https://www.cnblogs.com/raorao1994/p/16944071.html

相关文章

  • 车载测试系列:SOA接口测试(二)
    SOA服务测试内容及环境搭建SOME/IP协议底层通过以太网实现,基于service的控制器之间对服务的调用流程,以及基于service的控制器和基于信号(signal)的控制器之间对信息的传输......
  • 车载测试系列:SOA接口测试(一)
    SOA是什么?SOA(ServiceOrientedArchitecture)是一种面向服务的架构,最早应用于IT行业,SOA把功能定义成为服务,服务带有明确的可调用接口,并可以通过网络调用。在汽车领域,对于......
  • Spring Cloud OpenFeign
    该项目通过自动配置为SpringBoot应用程序提供OpenFeign集成并绑定到Spring环境和其他Spring编程模型习语。1.声明式REST客户端:假装Feign是一个声明式Web服务......
  • lspci能查看lmini pcie接口设备吗
    root@OpenWrt:/#lspci00:00.0Class0604:0e8d:080100:01.0Class0604:0e8d:080101:00.0Class0002:14c3:766302:00.0Class0280:14c3:7603lspci能查看lminipcie......
  • 代码讲解spring中的singleton和prototype
    1.singleton配置中的bean定义可以看作是一个模板,容器会根据这个模板来构造对象。bean定义中的scope语义会决定:容器将根据这个模板构造多少对象实例,......
  • CXF spring jaxws:endpoint jaxws:server 区别 与 关系
    First,theyareallfortheserversideconfiguration.Second,jaxws:endpointiscomingfromJAXWSAPI,anditisusedtoconfiguretheo......
  • springIOC和AOP
    IOC(InverseofControl:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。Ioc在其他语言中也有应用,并非spring特有。Ioc容器是Spring用......
  • spring mvc中普通类获得request
    springmvc中,在控制层很容易获得request,response,但在其他层的话获得的话,其实必要性不大,但可以实现:在web.xml中加入<listener><list......
  • springsecurity中处理框架页
    X-Frame-Options响应头X-Frame-OptionsHTTP响应头是用来给浏览器指示允许一个页面可否在<frame>,</iframe>或者<object>中展现的标记。网站可以使用此功能,来确保自......
  • spring+hibernate中用好DAO模版设置
     在spring+hibernate中,由于基于hibernatedaosupport的dao组件必须获得sessionfactory的引用,因此可以让所有的DAO组件继承一个DAO模版,在其中防止其......