试试让chatgpt 写个spring boot接口限流方法

538 阅读2分钟

提问1:spring boot 实现单个用户访问接口限流的方法 一分钟内限制20次 可以使用别的框架

回答如下:

可以使用Spring Cloud Gateway和Redis实现单个用户访问接口限流的方法,具体步骤如下:

添加依赖 在Spring Boot项目的pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis 在application.yml文件中添加Redis的连接配置:

spring:
  redis:
    host: localhost
    port: 6379

配置限流过滤器 在Spring Cloud Gateway中添加限流过滤器,该过滤器可以通过Redis记录用户访问次数和访问时间,实现单个用户访问接口限流的功能。具体代码如下:
配置限流过滤器的Bean 在Spring Boot项目中,将限流过滤器配置为一个Bean:

public class RateLimiterFilter implements GatewayFilter, Ordered {
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    public RateLimiterFilter(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
        String key = "rate_limiter:" + ip;
        String count = redisTemplate.opsForValue().get(key);
        if (count == null) {
            redisTemplate.opsForValue().set(key, "1", Duration.ofMinutes(1));
        } else {
            int cnt = Integer.parseInt(count);
            if (cnt >= 20) {
                exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                return exchange.getResponse().setComplete();
            } else {
                redisTemplate.opsForValue().increment(key);
            }
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return -1;
    }
}
@Configuration
public class GatewayConfig {
    @Bean
    public RateLimiterFilter rateLimiterFilter(RedisTemplate<String, String> redisTemplate) {
        return new RateLimiterFilter(redisTemplate);
    }
}

测试限流效果 通过postman等工具发送20次以上的请求后,将会返回状态码429,表示访问过于频繁。 以上就是使用Spring Cloud Gateway和Redis实现单个用户访问接口限流的方法。

提问2:不使用spring-cloud-starter-gateway ,保留redis的呢?

回答:

如果不使用Spring Cloud Gateway,可以通过拦截器实现单个用户访问接口限流的功能,具体步骤如下:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置Redis 在application.yml文件中添加Redis的连接配置:

spring:
  redis:
    host: localhost
    port: 6379

配置拦截器 在Spring Boot项目中添加一个拦截器,该拦截器可以通过Redis记录用户访问次数和访问时间,实现单个用户访问接口限流的功能。具体代码如下:

@Component
public class RateLimiterInterceptor implements HandlerInterceptor {
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    public RateLimiterInterceptor(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = request.getRemoteAddr();
        String key = "rate_limiter:" + ip;
        String count = redisTemplate.opsForValue().get(key);
        if (count == null) {
            redisTemplate.opsForValue().set(key, "1", Duration.ofMinutes(1));
        } else {
            int cnt = Integer.parseInt(count);
            if (cnt >= 20) {
                response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
                return false;
            } else {
                redisTemplate.opsForValue().increment(key);
            }
        }
        return true;
    }
}

配置拦截器的Bean 在Spring Boot项目中,将拦截器配置为一个Bean:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final RateLimiterInterceptor rateLimiterInterceptor;
    @Autowired
    public WebConfig(RateLimiterInterceptor rateLimiterInterceptor) {
        this.rateLimiterInterceptor = rateLimiterInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(rateLimiterInterceptor)
                .addPathPatterns("/**");
    }
}

测试限流效果 通过postman等工具发送20次以上的请求后,将会返回状态码429,表示访问过于频繁。 以上就是使用拦截器和Redis实现单个用户访问接口限流的方法。