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

相关推荐
鸽鸽程序猿17 分钟前
【算法】【优选算法】二分查找算法(下)
java·算法·二分查找算法
瓜牛_gn22 分钟前
Spring Security概述
spring
遇见你真好。32 分钟前
自定义注解进行数据脱敏
java·springboot
NMBG2236 分钟前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
像污秽一样1 小时前
Spring MVC初探
java·spring·mvc
计算机-秋大田1 小时前
基于微信小程序的乡村研学游平台设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
LuckyLay1 小时前
Spring学习笔记_36——@RequestMapping
java·spring boot·笔记·spring·mapping
醉颜凉2 小时前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
阿维的博客日记2 小时前
java八股-jvm入门-程序计数器,堆,元空间,虚拟机栈,本地方法栈,类加载器,双亲委派,类加载执行过程
java·jvm
qiyi.sky2 小时前
JavaWeb——Web入门(8/9)- Tomcat:基本使用(下载与安装、目录结构介绍、启动与关闭、可能出现的问题及解决方案、总结)
java·前端·笔记·学习·tomcat