Spring Cloud Gateway--全局过滤器(GlobalFilter)--作用/使用

Posted IT利刃出鞘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Gateway--全局过滤器(GlobalFilter)--作用/使用相关的知识,希望对你有一定的参考价值。


简介

        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然后打断点

Spring

过滤器大全

  1. org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter, order = -2147483648
  1. 移除缓存中的请求体
  1. org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter, order = -2147482648
  1. 从exchange的attributes中获得cachedRequestBody属性值作为request的body
  2. 必须预设cachedRequestBody属性至attributes中,要手动设置,无法通过配置来设置。可以在优先级更高的filter中来设置cachedRequestBody。当然也可以自己写一个FilterFactory类来做成配置化。
  1. org.springframework.cloud.gateway.filter.NettyWriteResponseFilter, order = -1
  1. 将Netty代理调用的response数据流写入ServerHttpResponse的body中。当NettyRouting拿到远程调用的结果数据流之后会将其写入当前请求exchange的attributes中。
  1. org.springframework.cloud.gateway.filter.ForwardPathFilter, order = 0
  1. 条件过滤器,只有当请求的header scheme为forward的时候才会发生,否则会忽略没有任何作用,当有转发需求的时候会将request的请求path修改,从而修改了请求的目的地址。
  1. [[RewritePath /order/(?<remaining>.*) = /$remaining], order = 1
  2. org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter, order = 10000
  1. 将网关上的请求转为对应业务应用的真实ip的请求。
  2. 请求进来时path的前缀是gateway的地址(ip+port或域名),需要将其uri映射至服务id上;比如:将path的192.168.20.134:10080映射至服务lb://serviceId;对于绝对路径配置的服务,exchange的GATEWAY_ROUTE_ATTR属性将会是null,直接过滤到下一个过滤器,不会发生path的真实映射。
  1. org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter, order = 10150
  1. 负责服务真实ip的映射,对服务进行负载均衡,默认采用的netflix-ribbon作为负载均衡器。
  2. 如果scheme不是服务节点映射的话直接过滤,获取服务节点。里边的choose函数是核心负载均衡函数,获取一个实例(如果是单节点则不计算),然后将服务的真实ip+port替换掉path中的lb://serviceId前缀。
  1. org.springframework.cloud.gateway.filter.WebsocketRoutingFilter, order = 2147483646
  1. 实现了gateway对于websocket的支持,内部通过websocketClient实现将一个http请求协议换转成websocket,实现调用方无感知的请求websocket的服务,只需要将schme设置成ws或者wss这么简单。
  1. org.springframework.cloud.gateway.filter.NettyRoutingFilter, order = 2147483647
  2. org.springframework.cloud.gateway.filter.ForwardRoutingFilter, order = 2147483647
  1. 是一个结束操作,经过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;


以上是关于Spring Cloud Gateway--全局过滤器(GlobalFilter)--作用/使用的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Gateway 全局通用异常处理

Spring Cloud Gateway 全局通用异常处理

spring-cloud-gateway之GatewayFilterFactory

spring cloud gateway 修改responseBody全局过滤器

spring cloud gateway 修改responseBody全局过滤器

Spring Cloud Gateway--全局过滤器(GlobalFilter)--作用/使用