【Spring Cloud】 Gateway网关 之 那些好玩的网关过滤器
1.添加请求头的网关过滤 AddRequestHeader
匹配到的路由将添加指定的请求头和值 格式为 请求头名称 , 请求头值
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:80 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- AddRequestHeader=gateway,8848
改下controller代码
package gateway.controller;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import reactor.netty.http.server.HttpServerRequest;
import java.util.Iterator;
import java.util.Map;
/**
* @author sz
* @DATE 2022/3/20 20:15
*/
@Data
@RestController
public class HelloController {
@Value("${server.port}")
public String serverPort;
@GetMapping("/say")
public String say(
@RequestHeader(name = "gateway",required = false)String value
)
{
return "HelloWord "+serverPort +" "+value;
}
@GetMapping("/say/one")
public String sayOne()
{
return "HelloWord one";
}
}
返回结果
发送请求时我们并没有携带请求头, 这是因为匹配到 apptest1路由后将指定的请求头添加到了请求中
2.添加请求参数的网关过滤 AddRequestParameter
匹配到的路由将添加指定的请求参数和值 格式为 请求参数名 , 请求参数值
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- AddRequestParameter=gateway,8848
package gateway.controller;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import reactor.netty.http.server.HttpServerRequest;
import java.util.Iterator;
import java.util.Map;
/**
* @author sz
* @DATE 2022/3/20 20:15
*/
@Data
@RestController
public class HelloController {
@Value("${server.port}")
public String serverPort;
@GetMapping("/say")
public String say(
@RequestParam(name = "gateway",required = false)String value
)
{
return "HelloWord "+serverPort +" "+value;
}
@GetMapping("/say/one")
public String sayOne()
{
return "HelloWord one";
}
}
3.添加响应头的网关过滤 AddResponseHeader
匹配到的路由将添加指定的响应头参数和值 格式为 响应头名 , 响应头值
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- AddResponseHeader=gateway, 8848
我们发送请求的时候并未携带任何请求头,但是response响应的时候可以看到添加了 我们指定的请求头
4.请求头映射网关过滤 MapRequestHeader
MapRequestHeader= 请求头一,请求头二
如果请求对象中请求头一不存在,不会对请求对象的请求头做出任何改变
如果请求对象中请求头一存在,请求头二不存在,将在请求对象的请求头中添加请求头二,且将请求头一的值赋值给请求头二
如果请求对象中请求头二已经存在也将不会对请求对象做出任何改变
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- MapRequestHeader=fuck, hello
这个什么意思呢?
如果请求对象的请求头中携带了fuck请求头,且没有hello请求头
将添加hello请求头,且将fuck请求头的值赋值给hello请求头
如果请求对象的请求头中已经携带了hello 请求头,或者没有fuck请求头,hello请求头将不会做出任何改变
来看演示
@Data
@RestController
public class HelloController {
@Value("${server.port}")
public String serverPort;
@GetMapping("/say")
public String say(
)
{
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
HttpServletResponse response = servletRequestAttributes.getResponse();
String fuck = request.getHeader("fuck");
System.out.println("fuck = " + fuck);
String hello = request.getHeader("hello");
System.out.println("hello = " + hello);
return "HelloWord ";
}
@GetMapping("/say/one")
public String sayOne()
{
return "HelloWord one";
}
}
5.添加路径前缀网关过滤器 PrefixPath
如果匹配当前路由,则在路径前添加指定前缀
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- PrefixPath=/prefix
如上配置
此时访问 /say是找不到请求映射的,因为请求对象的映射地址已经被添加前缀地址 /prefix
此时访问的路径为 localhost:81/prefix/say
6.重定向网关过滤器 RedirectTo
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- RedirectTo=302,http://localhost:8081/say/one
如果当前请求匹配此路由,将重定向到指定地址
7.删除请求头网关过滤器 RemoveRequestHeader
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- RemoveRequestHeader=fuck
如果当前请求匹配此路由将删除请求头中指定的请求头参数
请求对象中有请求头fuck,且值为you
但controller层接收的时候,已经没有了
8.删除响应头网关过滤器 RemoveResponseHeader
如果当前请求匹配此路由,将删除响应头中指定的头信息
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- RemoveResponseHeader=fuck
先不加此网关过滤器,访问 /say
@GetMapping("/say")
public String say(
)
{
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
HttpServletResponse response = servletRequestAttributes.getResponse();
response.setHeader("fuck","you");
return "HelloWord ";
}
响应头中有fuck,且有值
如果我们加上此过滤器,重启网关模块再次访问
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- RemoveResponseHeader=fuck
响应头中的fuck已经被删除了
9.删除请求参数网关过滤器 PrefixPath
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- RemoveRequestParameter=fuck
如果当前请求匹配此路由,请求参数中的fuck就被删除,如果有的情况下
10.路径重写网关过滤器 RewritePath
server:
port: 81
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8081 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- RewritePath=/say(?<segment>/?.*), $\{segment}
如果当前请求匹配此路由,将按照指定规则重写路径
如上的配置 我们访问 /say/fuck 将会被重写为 访问 /fuck
@GetMapping("/say")
public String say(
)
{
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
HttpServletResponse response = servletRequestAttributes.getResponse();
response.setHeader("fuck","you");
return "HelloWord ";
}
@GetMapping("/fuck")
public String fuck(){
return "RewritePath fuck";
}
11.模板重设路径网关过滤器 SetPath
如果请求匹配当前路由,将使用模板重新设置路径
什么意思呢 看下面这个配置
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:80 # 匹配后提供服务的路由地址
predicates:
- Path=/fuck/{segment}
filters:
- SetPath=/{segment}
如果我们访问 /fuck/say 路径将被重新设置为 /say
例如,我们访问的是 localhost:81/fuck/say 但实际上我们访问的 localhost:81/say
12.设置响应状态码网关过滤器 SetStatus
将响应的状态码修改为指定的值,注意,仅仅只是修改响应状态码状态码
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:80 # 匹配后提供服务的路由地址
predicates:
- Path=/say
filters:
- SetStatus=404
13.重试网关过滤器 Retry
retries
:应尝试的重试次数。statuses
:应重试的 HTTP 状态代码,使用 表示。org.springframework.http.HttpStatus
methods
:应重试的 HTTP 方法,通过使用 表示。org.springframework.http.HttpMethod
series
:要重试的一系列状态代码,使用 表示。org.springframework.http.HttpStatus.Series
exceptions
:应重试的引发的异常的列表。backoff
:为重试配置的指数退避。重试是在回退间隔为 之后执行的,其中迭代是。如果配置了 ,则应用的最大回退限制为 。如果为 true,则使用 计算回退。firstBackoff * (factor ^ n)``n``maxBackoff``maxBackoff``basedOnPreviousValue``prevBackoff * factor
spring:
cloud:
gateway:
routes: # 配置路由,是一个集合
- id: apptest1 # 路由的ID, 没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:80 # 匹配后提供服务的路由地址
predicates:
- Path=/say/**
filters:
- name: Retry
args:
retries: 30
statuses: NOT_FOUND
methods: GET,POST
backoff:
firstBackoff: 1000ms
maxBackoff: 5000ms
factor: 2
basedOnPreviousValue: false
如上面的配置 则效果为
请求的路径如果匹配当前路由( id: apptest1 ) 且返回的响应状态码为 NOT_FOUND (404) 则会重试30次
第一次重试间隔为 1秒 之后每次最大间隔为 5秒
为了看到测试效果 这里添加了全局过滤器
@Component
public class GlobalFilterConf implements GlobalFilter {
Long start = System.currentTimeMillis();
long end = 0L;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("收到请求 : "+exchange.getRequest().getPath().toString());
Long temp = end = System.currentTimeMillis();
System.out.println("间隔: "+ (end - start)/1000);
start = temp;
return chain.filter(exchange);
}
}
访问一个不存在的映射地址
- 点赞
- 收藏
- 关注作者
评论(0)