所有分类
  • 所有分类
  • 未分类

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

 原文网址: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然后打断点

过滤器大全

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

0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录