Spring Cloud Gateway:我的地盘我做主!😎 自定义过滤器,玩转流量的魔法棒!
各位观众,各位朋友,大家好!我是你们的老朋友,人称“代码界的段子手”的程序猿老王!今天,咱们不聊那些高大上的架构理论,也不谈那些深奥难懂的算法,咱们来点接地气的,聊聊Spring Cloud Gateway的自定义过滤器!
说到Spring Cloud Gateway,那可是微服务架构中不可或缺的流量守门员!它就像一个精明的保安,负责接收所有请求,然后根据规则将它们分发到不同的服务。但是,再精明的保安也需要个性化定制,才能更好地满足我们的需求。而自定义过滤器,就是我们用来定制这个保安的魔法棒!✨
一、 什么是自定义过滤器?🤔 别怕,没那么玄乎!
想象一下,你开了一家餐厅,门口站着一位服务员。这位服务员的任务是引导顾客入座、检查顾客是否衣冠整洁、统计客流量等等。
- Spring Cloud Gateway 就像这家餐厅。
- 过滤器 就像这位服务员。
- 默认过滤器 就像餐厅标配的服务员,只能做一些基本的事情。
- 自定义过滤器 就像你专门培训的,拥有特殊技能的服务员,可以做更多个性化的事情。
简单来说,自定义过滤器就是你在Spring Cloud Gateway中添加的,可以对请求和响应进行拦截和处理的组件。它可以让你在请求到达目标服务之前或之后,做一些你想要做的事情,比如:
- 权限校验: 只有VIP客户才能进入专属包间!
- 日志记录: 记录每一位顾客的喜好,方便以后提供更贴心的服务!
- 流量控制: 防止餐厅爆满,影响顾客体验!
- 请求头修改: 统一顾客的称谓,显得更专业!
- 响应体修改: 给顾客送上一份小甜点,增加回头率!
总之,自定义过滤器就像一块橡皮泥,你想把它捏成什么形状,就捏成什么形状!只要你能想到,它就能做到!💪
二、 为什么要自定义过滤器?🤷♂️ 原生的不够用吗?
Spring Cloud Gateway自带了很多开箱即用的过滤器,比如AddRequestHeaderGatewayFilterFactory、RewritePathGatewayFilterFactory等等。它们可以满足一些基本的场景。
但是,世界上的需求千奇百怪,总有一些需求是原生过滤器无法满足的。比如:
- 需要根据用户的IP地址进行限流: 原生过滤器只能根据请求路径进行限流。
- 需要对请求体进行加密或解密: 原生过滤器只能对请求头进行修改。
- 需要根据请求的来源进行路由: 原生过滤器只能根据请求路径进行路由。
这时候,就需要我们自己动手,定制专属的过滤器,才能更好地解决问题。就像餐厅的标配服务员只能做一些基本的服务,但你想要提供更个性化的服务,就必须自己培养专门的服务员!
三、 如何自定义过滤器?👨💻 磨刀不误砍柴工!
自定义过滤器主要有两种方式:
- 实现
GatewayFilter接口: 这是最基本的方式,也是最灵活的方式。 - 继承
AbstractGatewayFilterFactory类: 这种方式可以简化配置,更加方便。
咱们先来看看第一种方式:
1. 实现GatewayFilter接口
这种方式就像自己从零开始搭建一个房子,你需要自己设计图纸、准备材料、一步一步地建造。虽然比较麻烦,但是也最灵活,可以完全按照自己的想法来设计。
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class AuthFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取请求头中的token
String token = exchange.getRequest().getHeaders().getFirst("token");
// 2. 校验token是否有效
if (token == null || token.isEmpty() || !token.equals("my-secret-token")) {
// 3. 如果token无效,则返回401 Unauthorized
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 4. 如果token有效,则放行
return chain.filter(exchange);
}
}
代码解释:
@Component:将该类标记为Spring组件,方便Spring管理。GatewayFilter接口:该接口是所有自定义过滤器的父接口,必须实现filter方法。filter方法:该方法是过滤器的核心逻辑,接收两个参数:ServerWebExchange:包含了请求和响应的所有信息。GatewayFilterChain:过滤器链,用于将请求传递给下一个过滤器。
exchange.getRequest().getHeaders().getFirst("token"):获取请求头中的token。exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED):设置响应状态码为401 Unauthorized。exchange.getResponse().setComplete():结束请求处理,返回响应。chain.filter(exchange):将请求传递给下一个过滤器。
2. 继承AbstractGatewayFilterFactory类
这种方式就像购买了一个毛坯房,只需要进行简单的装修,就可以入住。虽然不如自己搭建房子那么灵活,但是也更加方便快捷。
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class LogFilterFactory extends AbstractGatewayFilterFactory<LogFilterFactory.Config> {
public LogFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// 1. 获取请求的URI
String uri = exchange.getRequest().getURI().toString();
// 2. 打印日志
System.out.println("请求URI:" + uri + ",是否打印响应:" + config.isPrintResponse());
// 3. 放行
return chain.filter(exchange);
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("printResponse");
}
public static class Config {
private boolean printResponse;
public boolean isPrintResponse() {
return printResponse;
}
public void setPrintResponse(boolean printResponse) {
this.printResponse = printResponse;
}
}
}
代码解释:
AbstractGatewayFilterFactory<LogFilterFactory.Config>:继承该类,并指定配置类为LogFilterFactory.Config。Config类:用于定义过滤器的配置参数。shortcutFieldOrder方法:用于指定配置参数的顺序,方便在配置文件中配置。apply方法:该方法是过滤器的核心逻辑,接收一个Config对象作为参数。
四、 如何配置自定义过滤器?📝 别忘了激活它!
自定义过滤器写好之后,还需要在配置文件中进行配置,才能生效。配置方式有两种:
- 在
application.yml或application.properties中配置: 这种方式比较简单,但是不够灵活。 - 通过Java代码配置: 这种方式比较灵活,可以动态地修改配置。
咱们先来看看第一种方式:
spring:
cloud:
gateway:
routes:
- id: my-route
uri: http://example.com
filters:
- AuthFilter # 使用实现GatewayFilter接口的过滤器
- LogFilter=true # 使用继承AbstractGatewayFilterFactory的过滤器,并配置参数
代码解释:
filters:用于配置过滤器列表。AuthFilter:使用实现GatewayFilter接口的过滤器,直接写过滤器的名称即可。LogFilter=true:使用继承AbstractGatewayFilterFactory的过滤器,需要写过滤器的名称,并配置参数。
再来看看第二种方式:
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, AuthFilter authFilter, LogFilterFactory logFilterFactory) {
return builder.routes()
.route("my-route", r -> r.path("/api/**")
.filters(f -> f.filter(authFilter)
.filter(logFilterFactory.apply(config -> config.setPrintResponse(true))))
.uri("http://example.com"))
.build();
}
}
代码解释:
@Configuration:将该类标记为Spring配置类。@Bean:将customRouteLocator方法标记为Spring Bean。RouteLocatorBuilder:用于构建路由。r.path("/api/**"):指定请求路径为/api/**的请求,都路由到该路由。f.filter(authFilter):使用AuthFilter过滤器。f.filter(logFilterFactory.apply(config -> config.setPrintResponse(true))):使用LogFilterFactory过滤器,并配置printResponse参数为true。uri("http://example.com"):指定目标服务地址为http://example.com。
五、 最佳实践和注意事项 ⚠️ 千万别踩坑!
- 过滤器顺序很重要: 过滤器链中的过滤器顺序决定了它们的执行顺序。一定要根据实际需求,合理安排过滤器的顺序。
- 避免过度设计: 不要为了追求完美,而过度设计过滤器。只需要满足当前的需求即可,避免引入不必要的复杂性。
- 测试是王道: 在发布之前,一定要进行充分的测试,确保过滤器能够正常工作。
- 监控和告警: 监控过滤器的性能和错误率,及时发现和解决问题。
- 性能优化: 尽量避免在过滤器中进行耗时的操作,比如IO操作、数据库查询等。
六、 总结 🎉 恭喜你,又掌握了一项新技能!
今天,咱们一起学习了Spring Cloud Gateway的自定义过滤器,了解了它的概念、作用、实现方式和配置方式。希望通过今天的学习,大家能够掌握这项技能,并在实际工作中灵活运用,打造更加强大和稳定的微服务架构!
记住,自定义过滤器就像你的专属魔法棒,只要你敢想,它就能帮你实现!💪
最后,送大家一句代码界的至理名言:
- Bug虐我千百遍,我待Bug如初恋! ❤️
希望大家在未来的编程道路上,能够披荆斩棘,勇往直前,成为一名真正的代码大师!😎
附:常用过滤器示例(表格形式)
| 过滤器名称 | 功能描述 | 示例代码 |
|---|---|---|
AddRequestHeaderGatewayFilterFactory |
添加请求头。 | yaml spring: cloud: gateway: routes: - id: add-request-header uri: http://example.com filters: - AddRequestHeader=X-Request-Id, 123456 |
RewritePathGatewayFilterFactory |
重写请求路径。 | yaml spring: cloud: gateway: routes: - id: rewrite-path uri: http://example.com filters: - RewritePath=/api/(?<segment>.*), /${segment} |
RequestRateLimiterGatewayFilterFactory |
限制请求速率。 | yaml spring: cloud: gateway: routes: - id: request-rate-limiter uri: http://example.com filters: - RequestRateLimiter=redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 redis-rate-limiter.requestedTokens: 1 |
| 自定义鉴权过滤器 (AuthFilter) | 验证用户身份,只有通过验证的用户才能访问后端服务。 | (见上面的示例代码) |
| 自定义日志过滤器 (LogFilterFactory) | 记录请求信息,例如请求URI、请求头、请求体等,方便排查问题。 | (见上面的示例代码) |
希望这些示例能够帮助大家更好地理解和使用Spring Cloud Gateway的自定义过滤器!
好了,今天就到这里,咱们下次再见!👋