赞
踩
Redis 作为一个高效的内存存储系统,可以用来构建各种类型的过滤器。下面是一个使用 Redis 实现简单请求过滤的例子。在这个例子中,我们将实现一个基于 IP 的限流过滤器,即通过 Redis 来限制某个 IP 在一定时间内的请求次数。
首先,你需要在 Spring Boot 项目中添加 Redis 相关的依赖。在 pom.xml
中添加以下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
在 application.yml
或 application.properties
文件中配置 Redis 连接信息。
spring:
redis:
host: localhost
port: 6379
创建一个过滤器类,用于实现基于 IP 的限流功能。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.Filter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.TimeUnit; @Component public class RateLimitFilter extends OncePerRequestFilter { @Autowired private StringRedisTemplate redisTemplate; private static final String RATE_LIMIT_PREFIX = "rate_limit:"; private static final int MAX_REQUESTS = 5; private static final long TIME_WINDOW_SECONDS = 60; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String clientIp = getClientIp(request); String key = RATE_LIMIT_PREFIX + clientIp; // 获取 Redis 操作对象 ValueOperations<String, String> ops = redisTemplate.opsForValue(); // 获取当前请求计数 String countStr = ops.get(key); int count = (countStr == null) ? 0 : Integer.parseInt(countStr); if (count >= MAX_REQUESTS) { // 超过限制,返回 429 错误 response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS); response.getWriter().write("Too many requests"); } else { // 增加计数 if (count == 0) { ops.set(key, "1", TIME_WINDOW_SECONDS, TimeUnit.SECONDS); } else { ops.increment(key); } filterChain.doFilter(request, response); } } private String getClientIp(HttpServletRequest request) { String clientIp = request.getHeader("X-Forwarded-For"); if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) { clientIp = request.getHeader("Proxy-Client-IP"); } if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) { clientIp = request.getHeader("WL-Proxy-Client-IP"); } if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) { clientIp = request.getRemoteAddr(); } return clientIp; } }
你需要在 Spring Boot 应用中注册这个过滤器。你可以通过创建一个配置类来实现。
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<RateLimitFilter> rateLimitFilter() { FilterRegistrationBean<RateLimitFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new RateLimitFilter()); registrationBean.addUrlPatterns("/api/*"); // 你可以根据需求设置 URL 模式 registrationBean.setOrder(1); // 设置过滤器的顺序 return registrationBean; } }
通过上述步骤,你实现了一个基于客户端 IP 的限流过滤器。在这个例子中:
RateLimitFilter
类是具体的过滤器实现:
FilterConfig
类将过滤器注册到 Spring Boot 应用中,使其对指定的 URL 模式生效。
你可以根据业务需求调整请求的限制次数和时间窗口,以及添加更多的自定义处理逻辑。通过这种方式,你可以有效地控制请求流量,避免滥用问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。