1.Spring Cloud gateway介绍
Spring Cloud Gateway 是一个基于 Spring Framework 和 Spring Boot 的 API 网关服务,它利用了 Spring WebFlux 来提供响应式非阻塞式Web请求处理能力。它的核心功能是路由,即根据请求的特定规则将请求转发到后端服务,同时提供了一系列跨领域关注点的处理,如安全认证、监控、限流等。Spring Cloud Gateway 还提供了多种内置的 GatewayFilter 工厂,如 AddRequestHeader、AddRequestParameter、CircuitBreaker、RequestRateLimiter 等,用于修改请求和响应、实现断路器功能、限流等。此外,还可以自定义 GatewayFilter 来满足特定的需求。
2. predicate介绍
简单来说就是路由条件是否满足的判断,如果满足则进入当前定义的路由规则
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
这里以官网的 AfterRoutePredicateFactory 示例解释
及满足请求时间在 2017-01-20T17:42:47.789-07:00[America/Denver] 之后则断言通过 ,请求会到对应的uri 即 https://example.org
所以这里的断言主要是匹配路由规则的
接下来介绍Spring Cloud Gateway 自带的谓词工厂
项目启动时可以看见这些谓词工厂
他们都继承了 AbstractRoutePredicateFactory 又实现了 RoutePredicateFactory 和 ShortcutConfigurable(捷径匹配)
可以查看每个谓词名称都是类名的前几个字这里可以从 源码中看到把RoutePredicateFactory替换为空了,所以注册时是类名的前几个字
// RoutePredicateFactory
default String name() {
return NameUtils.normalizeRoutePredicateName(getClass());
}
// NameUtils
public static String normalizeRoutePredicateName(Class<? extends RoutePredicateFactory> clazz) {
return removeGarbage(clazz.getSimpleName().replace(RoutePredicateFactory.class.getSimpleName(), ""));
}
这是捷径匹配的配置 主要返回的是配置的名称(通过”,“分开如果有多个)对应的顺序就是对应名称的配置内容
default List<String> shortcutFieldOrder() {
return Collections.emptyList();
}
断言的匹配规则
Predicate<ServerWebExchange> apply(C config);
3.filter介绍
同理都继承了 AbstractGatewayFilterFactory 和实现了 GatewayFilterFactory 以及ShortcutConfigurable
其他都差不多,主要重写 apply 把你的自定义过滤规则写清楚就好了
GatewayFilter apply(C config);
4.自定义工厂
4.1 自定义predicate工厂
这里我写了一个判断请求路径中user 的判断,满足则通过,并且重写了shortcutFieldOrder 来
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
private final String USER_KEY = "user";
public MyRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return serverWebExchange -> {
if (serverWebExchange.getRequest().getQueryParams().containsKey(USER_KEY)) {
String user = serverWebExchange.getRequest().getQueryParams().getFirst(USER_KEY);
return Objects.equals(user, config.getUser());
}else {
return false;
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return List.of(USER_KEY);
}
@Validated
public static class Config {
@Getter
@Setter
@NotBlank
private String user;
}
}
查看配置
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: "factory" # id 不要重复即可
uri: http://localhost:8080 # 代理地址
predicates:
# - My=user # user=user
- name: My
args:
user: user
既满足请求路径上有?user=user 的请求地址则可以通过当前路由规则请求http://localhost:8080 服务
4.2 自定义filter 工厂
这里也是通过请求参数status 来判断是否返回 若不满足则返回错误请求
@Slf4j
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
private final String STATUS ="status";
public MyGatewayFilterFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return List.of(STATUS);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
log.info("进入自定义过滤器");
String status = exchange.getRequest().getQueryParams().getFirst(STATUS);
if (Objects.equals(status, config.getStatus())){
return chain.filter(exchange);
}else {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
};
}
@Setter
@Getter
@Validated
public static class Config {
@NotBlank
private String status;
}
}