当前位置: 首页 > article >正文

接口请求限制自定义注解

该功能有二个文件内容,其一自定义请求限制注解,其二请求限制注解中功能的实现拦截。

其请求限制功能实习,主要是因为继承了HandlerInterceptorAdapter拦截器功能,在里面去判断是否超时与超次数。

注解文件内容

package com.annotation;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {
    // 默认请求限制次数
    long limit() default 10;

    // 默认请求限制时间,单位 ms
    long period() default 10 * 1000;
}

功能实习内容

package com.aspect;

import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
//该类继承自 HandlerInterceptorAdapter,因此可以重写其方法以实现拦截器功能。
public class RequestLimitAspect extends HandlerInterceptorAdapter {
    //定义一个 ConcurrentHashMap 来存储每个 IP 地址和对应的请求信息。请求信息包含请求计数和上次请求的时间。
    private ConcurrentHashMap<String, RequestInfo> ipRequestInfo = new ConcurrentHashMap<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //获取 RequestLimit 注解,检查该方法是否被标记需要限制请求。
            RequestLimit requestLimit = handlerMethod.getMethodAnnotation(RequestLimit.class);

            if (requestLimit == null) {
                return true;
            }
            //从 RequestLimit 注解中获取每个 IP 最大请求次数和重置时间间隔。
            long maxRequestsPerIP = requestLimit.limit();
            long requestResetInterval = requestLimit.period();
            //获取请求的远程 IP 地址
            String ipAddress = request.getRemoteAddr();
            // 获取注解所在的方法名称
            String methodName = handlerMethod.getMethod().getName();
            String identifier = ipAddress + "/" + methodName;
            //从 ipRequestInfo 中获取该标识符对应的请求信息
            RequestInfo requestInfo = ipRequestInfo.get(identifier);

            if (requestInfo == null || System.currentTimeMillis() - requestInfo.getLastRequestTime() > requestResetInterval) {
                // 如果 IP 地址不存在或者超过时间限制,重置请求计数
                requestInfo = new RequestInfo();
                ipRequestInfo.put(identifier, requestInfo);
            }

            if (requestInfo.getRequestCount().get() > maxRequestsPerIP) {
                // 超过最大请求数,可以采取适当的措施,例如返回错误响应或记录日志

                response.setStatus(429); // Too Many Requests
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json; charset=utf-8");
                //向响应中写入提示信息,告知用户请求次数过多,并关闭输出流。然后返回 false,阻止请求继续处理。
                PrintWriter out = response.getWriter();
                String body = "{\"msg\":\"请求次数过多,请稍候重试\"}";
                out.write(body);
                out.close();
                return false;
            }

            requestInfo.getRequestCount().incrementAndGet();
            requestInfo.setLastRequestTime(System.currentTimeMillis());

            return true;
        }

        return true;
    }


    //定义一个静态内部类 RequestInfo 用于存储请求的计数和时间。
    static class RequestInfo {
        private AtomicInteger requestCount = new AtomicInteger(1);
        private long lastRequestTime = System.currentTimeMillis();

        public AtomicInteger getRequestCount() {
            return requestCount;
        }

        public long getLastRequestTime() {
            return lastRequestTime;
        }

        public void setLastRequestTime(long lastRequestTime) {
            this.lastRequestTime = lastRequestTime;
        }
    }

}


http://www.kler.cn/a/589678.html

相关文章:

  • 机器学习核心概念解读
  • Webpack构建流程详解优化前端性能\Dev-Server与Proxy\网络攻击\HMR
  • 深入解析 Spring Boot 中的 FailureAnalyzer
  • C++菱形继承内存模型
  • ONENET数据可视化命令框下发命令使用
  • 内网环境安装dlv,本地远程调试go
  • 自动化实施的常用元件有哪几种?
  • hadoop-配置安装jdk
  • Linux目录结构以及文件操作
  • IDEA的相关配置
  • 孤儿进程与僵尸进程:Linux进程管理中的“隐形杀手”与“无主孤儿”
  • 蓝桥杯 之 数学规律求解
  • React:React主流组件库对比
  • 【数据库】Data Model(数据模型)数据模型分析
  • AGI大模型(8):提示词的安全与防护
  • Redis 持久化机制:AOF 与 RDB 详解
  • 使用Ollama本地部署DeepSeek
  • (hash表+vector 数位和相等数对的最大和)leetcode 2342
  • CUDA多线程
  • EB-Cable许可证的常见问题及解决方案