1.实现自己的Filter
public class MyFilter implements GatewayFilter, Ordered {
private static final Log log = LogFactory.getLog(GatewayFilter.class);
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest req = exchange.getRequest();
HttpHeaders httpHeaders = req.getHeaders();
ServerHttpRequest.Builder requestBuilder = req.mutate();
Long timestamp = (new Date().getTime() / 1000);
System.out.println(timestamp);
requestBuilder.headers(k -> k.remove("x-tif-timestamp"));
requestBuilder.header("x-tif-timestamp", timestamp.toString());
ServerHttpRequest request = requestBuilder.build();
exchange.mutate().request(request).build();
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
2.注册到Filter链里面
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r -> r.path("/get")
.uri("http://httpbin.org"))
.route("host_route", r -> r.path("/ebus")
.filters(f -> f.filter(
new SignatrueFilter())
.filter(new MyFilter())
)
.uri(""))
.build();
}
3.总结
需要注意的是这里面的几个函数式写法。
filters()接受的参数是一个Function<GatewayFilterSpec, UriSpec> ;
GatewayFilterSpec是重点,GatewayFilterSpec的方法呢都是返回的本身调用。所以可以一直调用下去。这种设计方式叫啥名忘了,有朋友知道回复一下。
GatewayFilterSpec里面有一个很重要的方法需要注意就是filter方法,他是一个构造函数哈,看一下它的实现
public GatewayFilterSpec filter(GatewayFilter gatewayFilter) {
if (gatewayFilter instanceof Ordered) {
this.routeBuilder.filter(gatewayFilter);
return this;
} else {
return this.filter(gatewayFilter, 0);
}
}
把一个GatewayFilter类型包装成GatewayFilterSpec。这就是自定义GatewayFilterSpec的整个流程哈。本来是为了增加一个时间戳请求头的。使用addRequestHeader方法添加的时间戳初始化后就不变了。看下它的代码,接受的就是两个String。没办法传递function就去。所以暂时只想到了重写自定义GatewayFilterSpec ,这个方法。
public GatewayFilterSpec addRequestHeader(String headerName, String headerValue) {
return this.filter(((AddRequestHeaderGatewayFilterFactory)this.getBean(AddRequestHeaderGatewayFilterFactory.class)).apply((c) -> {
c.setName(headerName).setValue(headerValue);
}));
}