SpringCloudGateway 学习笔记 - 自定义过滤器 之 获取响应头

Posted 笑虾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloudGateway 学习笔记 - 自定义过滤器 之 获取响应头相关的知识,希望对你有一定的参考价值。


SpringCloudGateway支持两种过滤器, Global FiltersGatewayFilterFactories
同时还内置了 31GatewayFilterFactories常用实现。
我们自己需要自定时,基本照着改就行了。

下面我们就来实现一个获取响应头的自定义过滤器 。

规则

  1. 继承:AbstractGatewayFilterFactory<C>
public abstract class AbstractGatewayFilterFactory<C> extends AbstractConfigurable<C>
		implements GatewayFilterFactory<C>, ApplicationEventPublisherAware {...}
  1. 定义一个内部类接收参数。本例中直接用了 AbstractGatewayFilterFactory.NameConfig 它定义了一个名为 name 的参数
  2. 无参构造中将参数对象传给父类

注意:如果使用配置文件设置路由,有几点要注意。(下面会讲到)

自定义过滤器

直接复制RemoveResponseHeaderGatewayFilterFactory.java来改。
别看代码多,真正自己要写的业务逻辑只有这两行。其他都是拷过来的。

HttpHeaders headers = exchange.getResponse().getHeaders();
log.info("获得响应中的cookie: {}", headers.get(config.getName()));
package com.jerry.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator;

@Component
@Slf4j
public class CustomResponseHeaderGatewayFilterFactory
        extends AbstractGatewayFilterFactory<AbstractGatewayFilterFactory.NameConfig> {

    public CustomResponseHeaderGatewayFilterFactory() {
        super(NameConfig.class);
    }
        
    @Override
    public GatewayFilter apply(NameConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                return chain.filter(exchange)
                        .then(Mono.fromRunnable(
                                () -> {
                                    HttpHeaders headers = exchange.getResponse().getHeaders();
                                    log.info("获得响应中的cookie: {}", headers.get(config.getName()));
                                }
                            )
                        );
            }

            @Override
            public String toString() {
                return filterToStringCreator(CustomResponseHeaderGatewayFilterFactory.this)
                        .append("name", config.getName()).toString();
            }
        };
    }
}

设置路由,并指定过滤器

JavaConfig 实现

package com.jerry.config;

import com.jerry.filter.CustomResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class RoutesDemo {
   
    private static final String url = "http://127.0.0.1";

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(p -> p.path("/api/code") // 要过滤的地址
                		// 定义过滤器,同时通过 Lambda 设置了参数
                        .filters(f -> f.filter(new CustomResponseHeaderGatewayFilterFactory().apply(c -> c.setName("Set-Cookie"))))
                        .uri(url) // 转发到 url
                ).build();
    }
}

配置文件yml 实现

除了用上面的 javaConfig 方式配置路由,还可以使用配置文件配置,但有些需要注意的点:

注意 1、自定义过滤器命名规则

1.1. 默认规则

按照 SpringCloudGateway 默认命名规则,所有自定义过滤器要以GatewayFilterFactory结尾。
形式如:xxxxGatewayFilterFactory 这样在配置文件中使用 xxxx 作为过滤器名称。
比如本例要把过滤器名CustomResponseHeader 改为 CustomResponseHeaderGatewayFilterFactory

spring:
  cloud:
    gateway:
      routes: 
        - id: checkResponseHeader
          uri: http://127.0.0.1
          sensitiveHeaders: "*"
          predicates:
            - Path=/**
          filters:
            - CustomResponseHeader=Set-Cookie

1.2. 自定义规则

如果觉得默认规则太啰嗦,可以重写name()自定义。比如:

    @Override
    public String name() {
        return "CustomRH666";
    }
spring:
  cloud:
    gateway:
      routes: 
        - id: checkResponseHeader
          uri: http://127.0.0.1
          sensitiveHeaders: "*"
          predicates:
            - Path=/**
          filters:
            - CustomRH666=Set-Cookie

注意 2、配置文件参数规则

2.1. 完全参数名

在我们没有做短参数前,需要点名道姓的传参:

属性说明
filters指定过滤器
args接下来设置参数
name参数名 nameSet-Cookie
这里参数名叫name因为我们没自己定义参数对象,直接用的 AbstractGatewayFilterFactory.NameConfig 它的内容就是一个private String name;
spring:
  cloud:
    gateway:
      routes: 
        - id: checkResponseHeader
          uri: http://127.0.0.1
          sensitiveHeaders: "*"
          predicates:
            - Path=/**
          filters:
            - name: CustomRH666
              args:
                name: Set-Cookie
                # 参数名2: 参数值2
                # 参数名3: 参数值3

2.2. 短参数

参考 :4.1. Shortcut Configuration
短参数的格式:过滤器名=参数1,参数2,参数3

2.2.1. 单个参数

如果像如前面例子中那样使用短格式设置参数:CustomRH666=Set-Cookie 可以重写:

    /** 下面讲配置文件时会说明*/
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(NAME_KEY);
    }

这里直接使用了 GatewayFilterFactory 接口定义的参数名字。

	String NAME_KEY = "name"; // 我们用了这个
	String VALUE_KEY = "value";

2.2.2. 多个参数

这里的数组定义的就是参数顺序
注意这里的参数名:索引1这个位置的值,我把它传给param4

    /** 配置文件短参数 */
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(NAME_KEY, "param4", "param2", "param3");
    }

相应的AbstractGatewayFilterFactory.NameConfig现在不满足需求了。我们自己定义一个内部类CustomResponseHeaderGatewayFilterFactory.Config

    @Data
    public static class Config {
        private String name;
        private String param2;
        private String param3;
        private String param4;
    }

配置如下:

spring:
  cloud:
    gateway:
      routes: 
        - id: checkResponseHeader
          uri: http://127.0.0.1
          sensitiveHeaders: "*"
          predicates:
            - Path=/**
          filters: 
            - CustomRH666=Set-Cookie,我是老二,我是老三,我是老四

参考资料

SpringCloudGateway 官方文档
4.1. 短参数:Shortcut Configuration
6.13. 内置过滤器:RemoveResponseHeader GatewayFilter Factory
17.2. 自定义过滤器 Writing Custom GatewayFilter Factories

以上是关于SpringCloudGateway 学习笔记 - 自定义过滤器 之 获取响应头的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloudGateway 学习笔记 - 搭建项目

SpringCloudGateway 学习笔记 - 自定义过滤器 之 获取响应头

SpringCloudGateway 学习笔记 - yml 配置

SpringCloudGateway 学习笔记 - 使用内置过滤器添加请求头响应头

SpringCloudGateway 学习笔记 - 使用内置过滤器添加请求头响应头

SpringCloudGateway 学习笔记 - 使用内置过滤器添加请求头响应头