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

相关推荐
Q_192849990618 分钟前
基于Spring Boot的个人健康管理系统
java·spring boot·后端
Q_192849990625 分钟前
基于Springcloud的智能社区服务系统
后端·spring·spring cloud
m0_748245171 小时前
Web第一次作业
java
小码的头发丝、1 小时前
Java进阶学习笔记|面向对象
java·笔记·学习
m0_548514771 小时前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
坊钰2 小时前
【Java 数据结构】移除链表元素
java·开发语言·数据结构·学习·链表
chenziang12 小时前
leetcode hot100 LRU缓存
java·开发语言
会说法语的猪2 小时前
springboot实现图片上传、下载功能
java·spring boot·后端
码农老起2 小时前
IntelliJ IDEA 基本使用教程及Spring Boot项目搭建实战
java·ide·intellij-idea