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

相关推荐
y5236482 分钟前
解决OpenJDK用maven构建项目,出现的SSL以及SpringBoot端口一直被占用问题
java·maven·ssl
桃花加酥20 分钟前
js笔记(二进制由0和1两个数字组成)
java·javascript
拾光师21 分钟前
POI操作EXCEL插入图片
java
Leighteen28 分钟前
Java8四大函数接口
java·开发语言
会洗碗的CV工程师32 分钟前
828华为云征文 | 使用Flexus X实例搭建Dubbo-Admin服务
java·linux·服务器·华为云·dubbo
cc77521034 分钟前
Tomcat后台弱口令部署war包
java·tomcat
聂 可 以34 分钟前
解决IDEA每次创建新项目时都要指定Maven仓库和Maven配置文件的问题
java·intellij-idea
BYSJMG1 小时前
计算机毕业设计推荐-基于python的白酒销售数据可视化分析
java·开发语言·数据库·python·信息可视化·毕业设计·课程设计
程序员阿鹏1 小时前
Map和Set有什么区别?
java·开发语言·数据结构·eclipse·intellij-idea
守护者1701 小时前
JAVA学习-练习试用Java实现“给表达式添加运算符”
java·学习