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

相关推荐
Struggle Sheep9 分钟前
容器化部署tomcat
java·tomcat
爱吃南瓜的北瓜1 小时前
Maven之jjwt依赖爆红
java·pycharm·maven
土豆儿@1 小时前
java之泛型
java·开发语言
橘猫云计算机设计1 小时前
基于SSM的《计算机网络》题库管理系统(源码+lw+部署文档+讲解),源码可白嫖!
java·数据库·spring boot·后端·python·计算机网络·毕设
菜鸟一枚在这2 小时前
深度解析建造者模式:复杂对象构建的优雅之道
java·开发语言·算法
gyeolhada2 小时前
2025蓝桥杯JAVA编程题练习Day5
java·数据结构·算法·蓝桥杯
菜鸟一枚在这2 小时前
深入理解设计模式之代理模式
java·设计模式·代理模式
剑走偏锋o.O3 小时前
Spring MVC 框架学习笔记:从入门到精通的实战指南
学习·spring·springmvc
小天努力学java3 小时前
【面试系列】Java开发--AI常见面试题
java·人工智能·面试
river663 小时前
java开发——为什么要使用动态代理?
java