Spring-Cloud-Gateway如何自定义路由过滤器?

遇到这么一个面试题:自定义网关过滤器实现把url中的请求参数放到http的header中传递给微服务。

我们知道网关的一个重要的作用就是路由转发,路由表的配置大概是这个样子:

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: http://localhost:8081
          predicates:
            - Path=/user/*
          filters:
            - QueryToHeader=authorization,auth

其中的filters就是配置的路由过滤器,Spring已经内置了31个路由的过滤器,这些过滤器都是org.springframework.cloud.gateway.filter.GatewayFilter的子类,每一种过滤器都是由一种实现了org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory接口的过滤器工厂来生成的,比如:

  • AddRequestHeaderGatewayFilterFactory生成AddRequestHeader的过滤器
  • AddRequestParameterGatewayFilterFactory生成AddRequestParameter的过滤器
  • StripPrefixGatewayFilterFactory生成StripPrefix的过滤器.
    我们现在就需要自定义一个这样的路由过滤器,实现把url中的请求参数放到http的header中传递给微服务,比如:
yml 复制代码
  filters:
      - QueryToHeader=authorization,auth

首先,我们要写一个GatewayFilterFactory的实现类,这里我们选择继承AbstractGatewayFilterFactory:

java 复制代码
@Component
public class QueryToHeaderGatewayFilterFactory extends
        AbstractGatewayFilterFactory<QueryToHeaderGatewayFilterFactory.QueryToHeaderConfig> {

    public QueryToHeaderGatewayFilterFactory() {
        super(QueryToHeaderConfig.class);
    }

	/**定义路由过滤器的参数的顺序*/
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("queryName", "headerName");
    }

    @Override
    public GatewayFilter apply(final QueryToHeaderConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                // 根据请求参数的名字,获取参数的值
                String queryValue = request.getQueryParams().getFirst(config.getQueryName());
                // 如果没有值,直接放行
                if(!StringUtils.hasLength(queryValue)){
                    return chain.filter(exchange);
                }
                // 把参数重新放到header中,header的key是在配置中配置好的
                request.mutate().header(config.getHeaderName(), queryValue);
                return chain.filter(exchange);
            }
        };
    }
    /**封装路由过滤器的参数*/
    @Validated
    public static class QueryToHeaderConfig {
        protected @NotEmpty String queryName;
        protected @NotEmpty String headerName;
        public QueryToHeaderConfig() {
        }
        public String getQueryName() {
            return this.queryName;
        }
        public QueryToHeaderConfig setQueryName(String queryName) {
            this.queryName = queryName;
            return this;
        }
        public String getHeaderName() {
            return this.headerName;
        }
        public QueryToHeaderConfig setHeaderName(String headerName) {
            this.headerName = headerName;
            return this;
        }
        @Override
        public String toString() {
            return (new ToStringCreator(this)).append("headerName", this.headerName).append("queryName", this.queryName).toString();
        }
    }
}

打开浏览器,测试一下,比如输入:http://localhost:8080/user/2?authorization=456

微服务中可以从header中读取到auth的值是456。

源码下载:https://github.com/xjs1919/enumdemo/tree/master/gateway-filter-demo

相关推荐
想不明白的过度思考者6 分钟前
SpringAOP:Java 三大代理模式:从静态代理到 JDK & CGLIB 动态代理
java·开发语言·代理模式
yaoyouzhong8 分钟前
MySQL中DROP、TRUNCATE和DELETE
java
Meepo_haha8 分钟前
Spring boot 3.3.1 官方文档 中文
java·数据库·spring boot
__土块__11 分钟前
一次 Spring 循环依赖源码走读:从三级缓存误用到 Bean 生命周期深度解析
java·spring·源码分析·aop·bean生命周期·循环依赖·三级缓存
妙蛙种子31111 分钟前
【Java设计模式 | 创建者模式】单例模式
java·开发语言·后端·单例模式·设计模式
种时光的人13 分钟前
Spring AI 工具调用(ToolCalling)完整使用教程
java·人工智能·后端·spring·ai·java开发·spring ai
立莹Sir2 小时前
Spring Bean 生命周期详解
java·python·spring
uElY ITER2 小时前
Spring全家桶简介
java·后端·spring
lay_liu8 小时前
springboot 文件下载
java·spring boot·后端
Flittly8 小时前
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
java·笔记·spring·ai·springboot