Spring Cloud Gateway(二)
GlobalFilter
The GlobalFilter interface has the same signature as GatewayFilter. These are special filters that are conditionally applied to all routes.
引用官方例子,自定义一个过滤器,且其为排序较前的过滤器
@Configuration
@Slf4j
public class ExampleConfiguration {
@Bean
public GlobalFilter customFilter() {
return new CustomGlobalFilter();
}
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
}
基于Spring官方提供的例子生成自己的自定义扩展
@Configuration
@Slf4j
public class ExampleConfiguration {
// ...
@Bean
public GlobalFilter versionFilter() {
return new VersionGlobalFilter();
}
}
@Slf4j
public class VersionGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// String crVersion = exchange.getRequest().getQueryParams().getFirst("cr_version");
String crVersion = exchange.getRequest().getHeaders().getFirst("cr_version");
if (null == crVersion) {
log.info("crVersion is latest.");
} else if ("1.0".equals(crVersion)) {
log.info("crVersion is {}", crVersion);
}
return chain.filter(exchange);
}
// 此处顺序比CustomGlobalFilter Order 还小,则此Filter将被优先处理
@Override
public int getOrder() {
return -2;
}
}
输出结果, VersionGlobalFilter#getOrder()
返回值更小 优先被处理
2022-09-04 19:02:46.710 INFO 133028 --- [ctor-http-nio-3] p.i.f.g.filters.VersionGlobalFilter : crVersion is 1.0
2022-09-04 19:02:46.714 INFO 133028 --- [ctor-http-nio-3] p.i.f.g.filters.ExampleConfiguration : custom global filter
Predicates
自定义路由断言器
In order to write a Route Predicate you will need to implement RoutePredicateFactory
as a bean. There is an abstract class called AbstractRoutePredicateFactory
which you can extend.
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
// grab configuration from Config object
return exchange -> {
//grab the request
ServerHttpRequest request = exchange.getRequest();
//take information from the request to see if it
//matches configuration.
return matches(config, request);
};
}
public static class Config {
//Put the configuration properties for your filter here
}
}
基于Spring官方提供的例子生成自己的自定义扩展
@Component
@Slf4j
public class CvVersionRoutePredicateFactory extends AbstractRoutePredicateFactory<CvVersionRoutePredicateFactory.Config> {
public CvVersionRoutePredicateFactory() {
super(CvVersionRoutePredicateFactory.Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
log.info("test start");
String value = serverWebExchange.getRequest().getHeaders().getFirst(config.getCvKey());
boolean result = null != value && getValue().equals(value);
log.info("test end result = {}", result);
return result;
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(CV_KEY, CV_VALUE);
}
public static final String CV_KEY = "cvKey";
public static final String CV_VALUE = "cvValue";
public String getValue() {
return "2.0";
}
@Getter
@Setter
public static class Config {
@NotNull
private String cvKey;
@NotNull
private String cvValue;
}
}
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://docs.spring.io/
predicates:
- Header=X-Request-Id, \d+
- CvVersion=version, 2.0
filters:
- StripPrefix=1
配置文件中 spring.cloud.gateway.routes.predicates.CvVersion
是 CvVersionRoutePredicateFactory
的前缀 (此处需2者保持一致)
断言是可以叠加的,如果前面的断言失败,则不会继续后面的断言。
2022-09-04 20:38:49.301 INFO 130396 --- [ctor-http-nio-3] p.i.f.g.p.CvVersionRoutePredicateFactory : test start
2022-09-04 20:38:55.338 INFO 130396 --- [ctor-http-nio-3] p.i.f.g.p.CvVersionRoutePredicateFactory : test end result = true
2022-09-04 20:38:55.343 INFO 130396 --- [ctor-http-nio-3] p.i.f.g.filters.VersionGlobalFilter : crVersion is latest.
2022-09-04 20:38:55.343 INFO 130396 --- [ctor-http-nio-3] p.i.f.g.filters.ExampleConfiguration : custom global filter
GatewayFilter
自定义GatewayFilter
@Component
@Slf4j
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
private static final String AUTHORIZE_TOKEN = "token";
public AuthorizeGatewayFilterFactory() {
super(AuthorizeGatewayFilterFactory.Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("enable");
}
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!config.enable) return chain.filter(exchange);
String token = exchange.getRequest().getHeaders().getFirst(AUTHORIZE_TOKEN);
if (null == token) {
token = exchange.getRequest().getQueryParams().getFirst(AUTHORIZE_TOKEN);
}
if (null == token || token.length() == 0) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
};
}
@Validated
@Getter
@Setter
public static class Config {
private boolean enable = false;
}
}
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://docs.spring.io/
predicates:
- Header=X-Request-Id, \d+
- CvVersion=cvKey, 2.0
filters:
- StripPrefix=1
- Authorize=true