原文网址:Spring Cloud Gateway–全局过滤器(GlobalFilter)–作用/使用_IT利刃出鞘的博客-CSDN博客
简介
SpringCloud Gateway支持自定义过滤器,可以很灵活的进行请求或者响应的控制。
自定义过滤器的方法是实现GlobalFilter接口、实现Ordered接口。这两个接口的全路径为:
- org.springframework.cloud.gateway.filter.GlobalFilter
- org.springframework.core.Ordered
默认的过滤器
本文对应的spring cloud gateway版本为:spring-cloud-starter-gateway:3.0.1
可以通过两种方式查看所有过滤器
法1:访问actuar接口
可以通过gateway内嵌的endpoint来查看GlobalFilter列表(网关ip:端口号/actuator/gateway/globalfilters):
法2:自定义GlobalFilter然后打断点
过滤器大全
- org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter, order = -2147483648
- 移除缓存中的请求体
- org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter, order = -2147482648
- 从exchange的attributes中获得cachedRequestBody属性值作为request的body
- 必须预设cachedRequestBody属性至attributes中,要手动设置,无法通过配置来设置。可以在优先级更高的filter中来设置cachedRequestBody。当然也可以自己写一个FilterFactory类来做成配置化。
- org.springframework.cloud.gateway.filter.NettyWriteResponseFilter, order = -1
- 将Netty代理调用的response数据流写入ServerHttpResponse的body中。当NettyRouting拿到远程调用的结果数据流之后会将其写入当前请求exchange的attributes中。
- org.springframework.cloud.gateway.filter.ForwardPathFilter, order = 0
- 条件过滤器,只有当请求的header scheme为forward的时候才会发生,否则会忽略没有任何作用,当有转发需求的时候会将request的请求path修改,从而修改了请求的目的地址。
- [[RewritePath /order/(?<remaining>.*) = ‘/${remaining}’], order = 1
- org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter, order = 10000
- 将网关上的请求转为对应业务应用的真实ip的请求。
- 请求进来时path的前缀是gateway的地址(ip+port或域名),需要将其uri映射至服务id上;比如:将path的192.168.20.134:10080映射至服务lb://{serviceId};对于绝对路径配置的服务,exchange的GATEWAY_ROUTE_ATTR属性将会是null,直接过滤到下一个过滤器,不会发生path的真实映射。
- org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter, order = 10150
- 负责服务真实ip的映射,对服务进行负载均衡,默认采用的netflix-ribbon作为负载均衡器。
- 如果scheme不是服务节点映射的话直接过滤,获取服务节点。里边的choose函数是核心负载均衡函数,获取一个实例(如果是单节点则不计算),然后将服务的真实ip+port替换掉path中的lb://{serviceId}前缀。
- org.springframework.cloud.gateway.filter.WebsocketRoutingFilter, order = 2147483646
- 实现了gateway对于websocket的支持,内部通过websocketClient实现将一个http请求协议换转成websocket,实现调用方无感知的请求websocket的服务,只需要将schme设置成ws或者wss这么简单。
- org.springframework.cloud.gateway.filter.NettyRoutingFilter, order = 2147483647
- org.springframework.cloud.gateway.filter.ForwardRoutingFilter, order = 2147483647
- 是一个结束操作,经过filter chain的链式调用,最终将exchange交还给web handler做http请求处理。
自定义过滤器实例
package com.knife.gateway.dynamic;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.Map;
import java.util.Objects;
/**
* 动态路由
*/
@Slf4j
@Component
public class Router4jFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest originalRequest = exchange.getRequest();
// 可获得所有请求参数
// Map<String, String> cachedRequestBody = exchange
// .getAttribute(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR);
//获取域名+端口后的path
String rawPath = originalRequest.getURI().getRawPath();
// todo 从redis中取出所有url,然后用rawPath去匹配
String host = "localhost";
int port = 9012;
URI originUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
URI newUri = UriComponentsBuilder.fromUri(originUri)
.host(host)
.port(port)
.build()
.toUri();
//重新封装request对象
ServerHttpRequest newRequest = originalRequest.mutate().uri(newUri).build();
// NettyRoutingFilter 最终从GATEWAY_REQUEST_URL_ATTR 取出uri对象进行http请求
// 所以这里要将新的对象覆盖进去
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, newUri);
return chain.filter(exchange.mutate().request(newRequest).build());
// 也可以加回调方法
// return chain.filter(exchange.mutate().request(newRequest).build())
// .then(Mono.fromRunnable(() -> {
// //请求完成回调方法 可以在此完成计算请求耗时等操作
// }));
}
/**
* 这里不能用@Order,必须实现Ordered接口
* 值必须大于10150。原因:Gateway有自己的过滤器,两个比较重要的如下:
* RouteToRequestUrlFilter:将根据Route将网关请求转为真实的请求。order = 10000
* ReactiveLoadBalancerClientFilter:负载均衡。order = 10150
*/
@Override
public int getOrder() {
return 15000;
}
}
请先
!