简介
spring cloud gateway中内置了很多的路由过滤工程,这些路由过滤工程允许以某种方式修改请求进来的http请求的内容(请求头,请求体)或返回的http响应。路由过滤器主要作用于需要处理的特定路由。spring cloud gateway内置了很多种类的过滤器,大致可以分为:Header、Paramter、Path、Status、Redirect、Hystrix熔断和限流RateLimiter。spring cloud gateway的路由过滤器的命令也遵循一定的规范,xxxxGatewayFilterFactory
Header
AddRequestHeaderGatewayFilter
该过滤器用于:在请求中添加配置的请求头,使用示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- AddRequestHeader=need-trace, true
- StripPrefix=1
RemoveRequestHeaderGatewayFilterFactory
该过滤器用于:在请求中移除配置的请求头,使用示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- RemoveRequestHeader=x-lw-agent
该配置表示移除请求中的请求头:x-lw-agent
AddResponseHeaderGatewayFilterFactory
该过滤器用于:在响应中添加配置的请求头,使用示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- AddResponseHeader=wtf,1111
RemoveResponseHeaderGatewayFilterFactory
该过滤器用于:在响应中移除配置的请求头,使用示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- RemoveResponseHeader=Date
RequestHeaderToRequestUriGatewayFilterFactory
该过滤器用于把请求转到请求头中对应配置的映射地址,比如如下的配置:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
# - RemoveResponseHeader=Date
- RequestHeaderToRequestUri=ddd
此时,如果发起如下请求时:
curl -i -H "X-New-Url: http://192.168.56.1:9001" http://192.168.56.1:9000/sc-c/hello/gatewayTest
会把该请求转到http://192.168.56.101:9001上,如果配置其他的过滤器:AddRequestHeaderGatewayFilterFactory可以实现灰度发布、路由分流等功能
HystrixGatewayFilterFactory
该过滤器用于处理spring cloud 的熔断逻辑,配置如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- name: Hystrix # Hystrix Filter的名称
args: # Hystrix配置参数
name: fallbackcmd #HystrixCommand的名字
fallbackUri: forward:/fallback #fallback对应的uri
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
其中:
fallbackUri配置项配置gateway网关处的熔断逻辑
java
@RequestMapping("/fallback")
public String fallback() {
return "Spring Cloud Gateway Fallback!";
}
XML
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
该配置项表示熔断降级的超时时间
tips:使用Hystrix过滤器需要添加熔断组件依赖:
XML
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
Parameter
AddRequestParameterGatewayFilterFactory
该过滤器用于在请求中添加请求参数中,使用示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- AddRequestParameter=address,123
此时在请求时,会添加请求参数address,值时123
RemoveRequestParameterGatewayFilterFactory
移除原始请求请求参数
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- RemoveRequestParameter=xxx
Path
StripPrefixGatewayFilterFactory
截取部分请求uri,使用示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
执行请求:/sc-c/hello/gatewayTest会截取第一个路径地址(sc-c),最终的请求uri地址是:/hello/gatewayTest
RewritePathGatewayFilterFactory
通过正则表达式重写原始的请求路径,配置示例:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- RewritePath=/sc-c/(?<segment>.*), /$\{segment}
这里的效果和使用StripPrefix效果一样,不过RewritePath更灵活
PrefixPathGatewayFilterFactory
该过滤器为请求添加路由前缀,和StripPrefix相反,配置示例如下:
XML
spring:
application:
name: sc-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: sc-service
uri: lb://sc-consumer
predicates:
- Path=/sc-c/**
filters:
- StripPrefix=1
- PrefixPath=/hello
此时请求:/sc-c/gatewayTest 最终请求的地址是:/hello/gatewayTest
Body
ModifyRequestBodyGatewayFilterFactory
用于在转发请求之前修改原始请求体内容,使用示例如下:
java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes().route("test11",r -> r.path("/sc-c/**")
.filters(f -> f.stripPrefix(1)
.modifyRequestBody(String.class,String.class,
当然也可以采用另外一种配置文件的方式实现:
1 在classpath下新增route.txt,配置示例内容如下:
XML
[
{
"filters": [
{
"name": "ModifyRequestBody",
"args": {
"inClass": "java.lang.String",
"outClass": "java.lang.String",
"rewriteFunction": "#{@testRewriteFunction}"
}
},
{
"name": "StripPrefix",
"args": {
"_genkey_0": "1"
}
}
],
"id": "test",
"order": 0,
"predicates": [
{
"args": {
"pattern": "/sc-c/**"
},
"name": "Path"
}
],
"uri": "lb://sc-consumer"
}
]
2 增加配置代码保存路由
java
@Component
public class RouteService {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@PostConstruct
public void init() {
String routeConfig = FileUtil.readString("route.txt", StandardCharsets.UTF_8);
List<RouteDefinition> list = JSONUtil.toList(routeConfig, RouteDefinition.class);
for (RouteDefinition routeDefinition : list) {
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
}
}
}
ModifyResponseBodyGatewayFilterFactory
用于在转发响应之前修改原始响应体内容,使用示例如下:
java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes().route("test11",r -> r.path("/sc-c/**")
.filters(f -> f.stripPrefix(1)
.modifyRequestBody(String.class,String.class,
(exchange,s) -> Mono.just(s + "test"))
.modifyResponseBody(String.class,String.class,(exchange,s) -> {
try {
JSONObject entries = JSONUtil.parseObj(s);
entries.set("appName","yc-music");
return Mono.just(JSONUtil.toJsonStr(entries));
} catch (Exception e) {
return Mono.just(s);
}
}))
.uri("lb://sc-consumer"))
.build();
}
当然也可以使用配置文件实现,
XML
[
{
"filters": [
{
"name": "ModifyRequestBody",
"args": {
"inClass": "java.lang.String",
"outClass": "java.lang.String",
"rewriteFunction": "#{@testRewriteFunction}"
}
},
{
"name": "ModifyResponseBody",
"args": {
"inClass": "java.lang.String",
"outClass": "java.lang.String",
"rewriteFunction": "#{@testResponseBodyRewriteFunction}"
}
},
{
"name": "StripPrefix",
"args": {
"_genkey_0": "1"
}
}
],
"id": "test",
"order": 0,
"predicates": [
{
"args": {
"pattern": "/sc-c/**"
},
"name": "Path"
}
],
"uri": "lb://sc-consumer"
}
]
代码配置:
java
@Component
public class RouteService {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@PostConstruct
public void init() {
String routeConfig = FileUtil.readString("route.txt", StandardCharsets.UTF_8);
List<RouteDefinition> list = JSONUtil.toList(routeConfig, RouteDefinition.class);
for (RouteDefinition routeDefinition : list) {
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
}
}
}
组件代码:
java
@Component
public class TestRewriteFunction implements RewriteFunction<String, String> {
@Override
public Publisher<String> apply(ServerWebExchange serverWebExchange, String s) {
return Mono.just(s);
}
}
@Component
public class TestResponseBodyRewriteFunction implements RewriteFunction<String,String> {
@Override
public Publisher<String> apply(ServerWebExchange serverWebExchange, String s) {
try {
JSONObject entries = JSONUtil.parseObj(s);
entries.set("appName","yc-music");
return Mono.just(JSONUtil.toJsonStr(entries));
} catch (Exception e) {
return Mono.just(s);
}
}
}
其他
RetryGatewayFilterFactory
spring cloud gateway的重试组件,可以通过配置对应的条件,满足时可以重试,使用示例如下:
java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes().route("test11",r -> r.path("/sc-c/**")
.filters(f -> f.stripPrefix(1)
.modifyRequestBody(String.class,String.class,
(exchange,s) -> Mono.just(s + "test"))
.retry((retryConfig -> {
retryConfig.setRetries(3);
retryConfig.setMethods(HttpMethod.POST,HttpMethod.GET);
retryConfig.setExceptions(RuntimeException.class);
}))
.modifyResponseBody(String.class,String.class,(exchange,s) -> {
try {
JSONObject entries = JSONUtil.parseObj(s);
entries.set("appName","yc-music");
return Mono.just(JSONUtil.toJsonStr(entries));
} catch (Exception e) {
return Mono.just(s);
}
}))
.uri("lb://sc-consumer"))
.build();
}
当然也可以在配置文件中配置使用:
java
[
{
"filters": [
{
"name": "StripPrefix",
"args": {
"_genkey_0": "1"
}
},
{
"name": "ModifyRequestBody",
"args": {
"inClass": "java.lang.String",
"outClass": "java.lang.String",
"rewriteFunction": "#{@testRewriteFunction}"
}
},
{
"name":"Retry",
"args":{
"retries": 3,
"methods": ["GET", "POST"]
}
},
{
"name": "ModifyResponseBody",
"args": {
"inClass": "java.lang.String",
"outClass": "java.lang.String",
"rewriteFunction": "#{@testResponseBodyRewriteFunction}"
}
}
],
"id": "test",
"order": 0,
"predicates": [
{
"args": {
"pattern": "/sc-c/**"
},
"name": "Path"
}
],
"uri": "lb://sc-consumer"
}
]