一、Spring Cloud Gateway内置GatewayFilter
路由过滤器允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围是特定路由。Spring Cloud Gateway 包括许多内置的 GatewayFilter 工厂。
官网地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
| 过滤器工厂 | 作用 | 参数 | 
|---|---|---|
| AddRequestHeader | 为原始请求添加Header | Header的名称及值 | 
| AddRequestParameter | 为原始请求添加请求参数 | 参数名称及值 | 
| AddResponseHeader | 为原始响应添加Header | Header的名称及值 | 
| DedupeResponseHeader | 剔除响应头中重复的值 | 需要去重的Header名称及去重策略 | 
| Hystrix | 为路由引入Hystrix的断路器保护 | HystrixCommand的名称 | 
| FallbackHeaders | 为fallbackUri的请求头中添加具体的异常信息 | Header的名称 | 
| PrefixPath | 为原始请求路径添加前缀 | 前缀路径 | 
| PreserveHostHeader | 为请求添加一个preserveHostHeader=true 的属性,路由过滤器会检查该属性以决定是否要发送原始的Host | 无 | 
| RequestRateLimiter | 用于对请求限流,限流算法为令牌桶 | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus | 
| RedirectTo | 将原始请求重定向到指定的URL | http状态码及重定向的url | 
| RemoveHopByHopHeadersFilter | 为原始请求删除IETF组织规定的一系列Header | 默认就会启用,可以通过配置指定仅删除哪些Header | 
| RemoveRequestHeader | 为原始请求删除某个Header | Header名称 | 
| RemoveResponseHeader | 为原始响应删除某个Header | Header名称 | 
| RewritePath | 重写原始的请求路径 | 原始路径正则表达式以及重写后路径的正则表达式 | 
| RewriteResponseHeader | 重写原始响应中的某个Header | Header名称、值的正则表达式,重写后的值 | 
| SaveSession | 在转发请求之前,强制执行WebSession::save操作 | 无 | 
| secureHeaders | 为原始响应添加一系列起安全作用的响应头 | 无,支持修改这些安全响应头的值 | 
| SetPath | 修改原始的请求路径 | 修改后的路径 | 
| SetResponseHeader | 修改原始响应中某个Header的值 | Header名称,修改后的值 | 
| SetStatus | 修改原始响应的状态码 | HTTP 状态码,可以是数字,也可以是字符串 | 
| StripPrefix | 用于截断原始请求的路径 | 使用数字表示要截断的路径的数量 | 
| Retry | 针对不同的响应进行重试 | retries、statuses、methods、series | 
| RequestSize | 设置允许接收最大请求包的大 小。如果请求包大小超过设置的值,则返回 413 Payload Too Large | 请求包大小,单位为字节,默认值为5M | 
| ModifyRequestBody | 在转发请求之前修改原始请求体内容 | 修改后的请求体内容 | 
| ModifyResponseBody | 修改原始响应体的内容 | 修改后的响应体内容 | 
二、DefaultFilter
添加DefaultFilter将其应用于所有路由,您可以使用spring.cloud.gateway.default-filters,此属性配置采用DefaultFilter列表。
spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - StripPrefix=1
三、GlobalFilter
GlobalFilter接口与GatewayFilter接口具有相同特征。GlobalFilter是有条件地应用于所有路由的特殊过滤器。
Spring Cloud Gateway 内置的GatewayFilter:
 
 更多介绍请见官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters
以下为自定义GlobalFilter实现记录请求方状态及耗时:
ApiLoggingFilter.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;
@Slf4j
public class ApiLoggingFilter implements GlobalFilter, Ordered {
	private static final String START_TIME = "startTime";
	private static final String X_REAL_IP = "X-Real-IP";// nginx需要配置
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		if (log.isDebugEnabled()) {
			String info = String.format("Method:{%s} Host:{%s} Path:{%s} Query:{%s}",
					exchange.getRequest().getMethod().name(), exchange.getRequest().getURI().getHost(),
					exchange.getRequest().getURI().getPath(), exchange.getRequest().getQueryParams());
			log.debug(info);
		}
		exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
		return chain.filter(exchange).then(Mono.fromRunnable(() -> {
			Long startTime = exchange.getAttribute(START_TIME);
			if (startTime != null) {
				Long executeTime = (System.currentTimeMillis() - startTime);
				List<String> ips = exchange.getRequest().getHeaders().get(X_REAL_IP);
				String ip = ips != null ? ips.get(0) : exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
				String api = exchange.getRequest().getURI().getRawPath();
				int code = 500;
				if (exchange.getResponse().getStatusCode() != null) {
					code = exchange.getResponse().getStatusCode().value();
				}
				// 当前仅记录日志,后续可以添加日志队列,来过滤请求慢的接口
				if (log.isDebugEnabled()) {
					log.debug("来自IP地址:{}的请求接口:{},响应状态码:{},请求耗时:{}ms", ip, api, code, executeTime);
				}
			}
		}));
	}
	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE;
	}
}
配置使用ApiLoggingFilter:
GatewayConfiguration.java
@Configuration(proxyBeanMethods = false)
public class GatewayConfiguration {
    @Bean
    public ApiLoggingFilter apiLoggingFilter() {
        return new ApiLoggingFilter();
    }
}
四、过滤器的执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter。
请求路由后,会将 当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,按org.springframework.core.Ordered接口排序,排序后依次执行每个过滤器:

 排序的规则是什么呢?
- 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
- GlobalFilter通过实现- Ordered接口,或者添加- @Order注解来指定- order值,由我们自己指定。
- 路由过滤器和- defaultFilter的- order由- Spring指定,默认是按照声明顺序从- 1递增。
- 当过滤器的order值一样时,会按照defaultFilter>路由过滤器>GlobalFilter的顺序执行。
- 传入的 HTTP请求的第一个过滤器具有最高优先级。
- 传出的 HTTP响应的最后一个过滤器具有最高优先级。
详细内容,可以查看源码:
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。
private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {
    List<GatewayFilter> filters = new ArrayList();
    if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
        filters.addAll(this.loadGatewayFilters(routeDefinition.getId(), new ArrayList(this.gatewayProperties.getDefaultFilters())));
    }
    if (!routeDefinition.getFilters().isEmpty()) {
        filters.addAll(this.loadGatewayFilters(routeDefinition.getId(), new ArrayList(routeDefinition.getFilters())));
    }
    AnnotationAwareOrderComparator.sort(filters);
    return filters;
}
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链。
public Mono<Void> handle(ServerWebExchange exchange) {
    Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
    List<GatewayFilter> gatewayFilters = route.getFilters();
    List<GatewayFilter> combined = new ArrayList(this.globalFilters);
    combined.addAll(gatewayFilters);
    AnnotationAwareOrderComparator.sort(combined);
    if (logger.isDebugEnabled()) {
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }
    return (new DefaultGatewayFilterChain(combined)).filter(exchange);
}







![[计算机操作系统(第四版 汤小丹 汤子瀛)]第一章 操作系统引论(学习复习笔记)](https://img-blog.csdnimg.cn/d4506e7a01224a60938081edd7310231.png)











