Spring Gateway自定义请求参数封装的实现示例

一、需求

在使用spring gateway作为网关时,我们需要在经过网关的请求中添加一些需要传递给后续服务的公共参数,这个时候就可以用到spring gateway提供的自定义请求参数功能了。

二、寻找解决途径

1、参考官方文档

我们可以猜测,spring gateway作为网关功能,肯定会提供很多处理请求参数的功能,于是我们查询文档得到如下内容:

2、探索GatewayFilterFactory实现规律

  • 通过查询spring官方文档可以看到,spring gateway为我们提供了很多xxxGatewayFilterFactory,而这些factory都有相同点,都是以GatewayFilterFactory结尾的。
  • 在类名中,我们可以根据类名进行大胆的猜测,前面的几个单词是描述他的功能的。
  • 右侧的yml配置文件可以看到,filter的配置也是呈现出一定的规律的。

3、从源码获取实现原理

既然我们是要解决自定义请求参数封装问题,那么我们通过上面描述规律,可以很大胆的猜测AddRequestParameteGatewayFilterFactory就是我们要找的目标。那么我们查看一下他的源码,看看他是如何实现的。

首先看看AddRequestParameteGatewayFilterFactory的继承关系,大概了解一下他的组成

从继承关系来看,还是比较复杂,有点懵逼,那直接进入代码看看他的实现。

我们只粘贴比较核心的代码进行分析,其他代码暂时不用关心。

@Override
	public GatewayFilter apply(NameValueConfig config) {
		return new GatewayFilter() {
			@Override
			public Mono<Void> filter(ServerWebExchange exchange,
					GatewayFilterChain chain) {
				URI uri = exchange.getRequest().getURI();
				StringBuilder query = new StringBuilder();
				//获取请求uri的请求参数(GET请求参数通过拼接key=value形式进行传参)
    String originalQuery = uri.getRawQuery(); 

				//判断最后一个字符是否是&,如果不是则拼接一个&,以备后续的参数进行连接
				if (StringUtils.hasText(originalQuery)) {
					query.append(originalQuery);
					if (originalQuery.charAt(originalQuery.length() - 1) != '&') {
						query.append('&');
					}
				}
				//获取config中的key、value,然后拼接到uri请求参数后面
				String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
				// TODO urlencode?
				query.append(config.getName());
				query.append('=');
				query.append(value);
				//把请求参数重新拼接回去,并放入request中传递到过滤链的下一个请求中去
				try {
					URI newUri = UriComponentsBuilder.fromUri(uri)
							.replaceQuery(query.toString()).build(true).toUri();

					ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri)
							.build();

					return chain.filter(exchange.mutate().request(request).build());
				}
				catch (RuntimeException ex) {
					throw new IllegalStateException(
							"Invalid URI query: \"" + query.toString() + "\"");
				}
			}

此方法是用于封装请求参数的具体实现,代码的具体实现步骤已经通过注释进行说明。

config中的key:value又是如何传递进来的呢?

4、filter的配置和参数传递

代码实现中出现了config参数的封装,那这个参数是如何获得的呢?这时候我们就要去查看这个filter是如何使用的了。

  • 从图中可以看到,我们的filter就是在这个配置文件中配置使用的。那为什么配置文件中只有AddRequestParameter配置,而不是AddRequestParameterGatewayFilterFactory呢???
  • 其实这是spring的一种约定,实现了GatewayFilterFactory接口的类在配置使用的时候,需要省略掉后面的GatewayFilterFactory,仅配置前缀即可。
  • 同时,配置文件中的red,blue又是做什么的???
  • 这就是我们需要传递的请求参数了,他以key=red,value=blue的方式进行配置。
  • 然后spring会帮我们把这个键值传入到上面的apply方法的config中。我们通过config的源码就能看到究竟:

可以看到,config类的实现就是一个namevalue,分别对应了配置文件中的两个参数。

三、基于官方实现进行自定义拓展

我们看到,spring利用同种方式,实现了各种filter。但如果这些都不能满足我们的要求,那该怎么办???

1、自定义参数惨景预设

我们现在看到的参数信息都是写死在配置文件中的,无法进行动态参数的传递。我们可以设想一个很普通的场景: 我们需要把用户的登录信息封装到请求参数中,供其他服务使用。那这又该如何实现呢???

2、参考官方实现进行自定义

其实如果我们只要模仿官方实现,在uri上拼接我们要传递的动态参数就可以了。具体实现如下:

 @Override
   public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    URI uri = exchange.getRequest().getURI();
    StringBuilder query = new StringBuilder();
    String originalQuery = uri.getRawQuery();

    if (StringUtils.hasText(originalQuery)) {
     query.append(originalQuery);
     if (originalQuery.charAt(originalQuery.length() - 1) != '&') {
      query.append('&');
     }
    }

    String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
    // TODO urlencode?
    query.append(config.getName());
    query.append('=');
    query.append(value);

    //获取redis中用户的缓存信息,拼接到请求参数后面
    String token = exchange.getRequest().getHeaders().getFirst("token");
    if (StringUtils.hasText(token)) {
     AccountEntity accountEntity = accountAdminApiService.loginAccountAdmin(token);
     //通过发射拿到bean的属性和值,以备后面进行传递参数拼接
     Map<String, Object> beanMap = beanValue(accountEntity);
     if (!CollectionUtils.isEmpty(beanMap)) {
      for (String key : beanMap.keySet()) {
       query.append('&').append(key).append('=').append(beanMap.get(key));
      }
     }
    }

    //以下与官方代码一样,省略...
   }

在固定传参参数拼接后面,直接通过token去获取缓存中的用户登陆信息,然后依次拼接对应的属性和值即可。

四、自定义filter的应用。

网上看了很多人写的自定义,其实和本文差不多。但是有点没有提到,定义好了怎么用啊???

通过使用注解@bean的方式进行配置,具体可以自己百度。

这里用一个简易的配置,套用yml配置的规律,直接在配置文件中配置。

default-filters:
  - AccountRequestParameter=k, v

因为我是全局使用的,所以使用的是default-filters进行配置

此外还应该注意,此时自定的filter并不会被spring boot加载,所以在启动的时候会报错。

解决办法:此时还要在对应的类上加上注解@Component,把bean交给spring管理。

至此,我们自定义请求参数封装完成!!!

到此这篇关于Spring Gateway自定义请求参数封装的实现示例的文章就介绍到这了,更多相关Spring Gateway自定义请求参数封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringCloud Gateway跨域配置代码实例

    这篇文章主要介绍了SpringCloud Gateway跨域配置代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Springboot版本:2.1.8.RELEASE SpringCloud版本:Greenwich.SR2 yml配置: spring: cloud: gateway: globalcors: cors-configurations: '[/**]': # 允许携带认证信息 # 允许跨域的源(网站域名/ip),设置*为全部

  • Spring Cloud Gateway全局通用异常处理的实现

    为什么需要全局异常处理 在传统 Spring Boot 应用中, 我们 @ControllerAdvice 来处理全局的异常,进行统一包装返回 // 摘至 spring cloud alibaba console 模块处理 @ControllerAdvice public class ConsoleExceptionHandler { @ExceptionHandler(AccessException.class) private ResponseEntity<String> handleAc

  • 详解SpringCloudGateway内存泄漏问题

    SpringCloudGateway内存泄漏问题 项目完善差不多,在进入压力测试阶段期间,发现了gateway有内存泄漏问题,问题发现的起因是,当时启动一台gateway,一台对应的下游应用服务,在压力测试期间,发现特别不稳定,并发量时高时低,而且会有施压机卡住的现象,然后找到容器对应的宿主机,并使用container stats命令观察内存,经过观察发现,压力测试时内存会暴涨,并由于超过限制最大内存导致容器挂掉(这里由于用的swarm所以会自动选择节点重启)最终发现由于之前测试服务器配置低,所

  • SpringCloudGateway开发过程解析

    路由简介: 1.SpringCloudGateWay 是用于替代zuul作为API网关,在gateway中有三个重要的名词:过滤器,断言,路由 过滤器与断言是路由的一部分,路由便是将请求进行一系列的处理后分发到各个服务的一个过程. 路由的过程:首先会加载断言以及路由,在接受到请求后根据断言加载的顺序会匹配到先加载的断言,只有与断言匹配了的请求才会进入路由,没有匹配到的服务会将请求当成普通的访问请求. 2:路由加载断言的方式: 断言加载的方式有四种,分别是配置文件,java编码,数据库以及注册中心

  • Spring Cloud Gateway重试机制原理解析

    重试,我相信大家并不陌生.在我们调用Http接口的时候,总会因为某种原因调用失败,这个时候我们可以通过重试的方式,来重新请求接口. 生活中这样的事例很多,比如打电话,对方正在通话中啊,信号不好啊等等原因,你总会打不通,当你第一次没打通之后,你会打第二次,第三次-第四次就通了. 重试也要注意应用场景,读数据的接口比较适合重试的场景,写数据的接口就需要注意接口的幂等性了.还有就是重试次数如果太多的话会导致请求量加倍,给后端造成更大的压力,设置合理的重试机制才是最关键的. 今天我们来简单的了解下Spr

  • Spring cloud gateway工作流程原理解析

    spring cloud gateway的包结构(在Idea 2019.3中展示) 这个包是spring-cloud-gateway-core.这里是真正的spring-gateway的实现的地方. 为了证明,我们打开spring-cloud-starter-gateway的pom文件 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId

  • spring-cloud-gateway降级的实现

    前言 本文主要研究一下 spring cloud gateway 如何集成 hystrix. 当下游接口负载很大,或者接口不通等其他原因导致超时,如果接口不熔断的话将会影响到下游接口得不到喘息,网关也会因为超时连接一直挂起,很可能因为一个子系统的问题导致整个系统的雪崩.所以我们的网关需要设计熔断,当因为熔断器打开时,网关将返回一个降级的应答. Maven 配置 添加 hystrix 依赖 pom.xml <dependency> <groupId>org.springframewo

  • Spring Gateway自定义请求参数封装的实现示例

    一.需求 在使用spring gateway作为网关时,我们需要在经过网关的请求中添加一些需要传递给后续服务的公共参数,这个时候就可以用到spring gateway提供的自定义请求参数功能了. 二.寻找解决途径 1.参考官方文档 我们可以猜测,spring gateway作为网关功能,肯定会提供很多处理请求参数的功能,于是我们查询文档得到如下内容: 2.探索GatewayFilterFactory实现规律 通过查询spring官方文档可以看到,spring gateway为我们提供了很多xxx

  • Java Spring Controller 获取请求参数的几种方法详解

    Java Spring Controller 获取请求参数的几种方法  1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交.若"Content-Type"="application/x-www-form-urlencoded",可用post提交 url形式:http://localhost:8080/SSMDemo/demo/addUser1?username=lixiaoxi&password=1

  • SpringBoot 如何自定义请求参数校验

    目录 一.Bean Validation基本概念 二.基本用法 三.自定义校验 3.1 自定义注解 3.2 自定义Validator 3.3 以编程的方式校验(手动) 3.4 定义分组校验 3.5 定制返回码和消息 3.6 更加细致的返回码和消息 四.小结 最近在工作中遇到写一些API,这些API的请求参数非常多,嵌套也非常复杂,如果参数的校验代码全部都手动去实现,写起来真的非常痛苦. 正好Spring轮子里面有一个Validation,这里记录一下怎么使用,以及怎么自定义它的返回结果. 一.B

  • Retrofit自定义请求参数注解的实现思路

    前言 目前我们的项目中仅使用到 GET 和 POST 两种请求方式,对于 GET 请求,请求的参数会拼接在 Url 中:对于 POST 请求来说,我们可以通过 Body 或表单来提交一些参数信息. Retrofit 中使用方式 先来看看在 Retrofit 中对于这两种请求的声明方式: GET 请求 @GET("transporter/info") Flowable<Transporter> getTransporterInfo(@Query("uid"

  • spring webflux自定义netty 参数解析

    目录 自定义 webflux 容器配置 解决方案 初识Spring WebFlux Spring Web新的改变 Spring WebFlux的特性 1.异步非阻塞 2.响应式(reactive)编程 3.适配多种web容器 Spring WebFlux简单实践 1.工程创建 2.Controller中与SpringMVC的对比 3.异步非阻塞的体现 4.添加数据库支持 5.Dao的编写 6.Controller的编写 7.响应式编程Handler的编写 8.响应式编程Route的编写 自定义

  • spring boot自定义404错误信息的方法示例

    前言 本文将给大家简单介绍一下,在springboot中怎么个性化404错误信息,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 返回json @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer(){ @Override public void customize(ConfigurableEmbe

  • spring cloud gateway中如何读取请求参数

    spring cloud gateway读取请求参数 1. 我的版本: spring-cloud:Hoxton.RELEASE spring-boot:2.2.2.RELEASE spring-cloud-starter-gateway 2. 请求日志 import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springfram

  • Spring MVC传递接收参数方式小结

    目录 一.通过实体Bean接收请求参数 二.通过处理方法的形参接收请求参数 三.通过HttpServletRequest接收请求参数 四.通过@PathVariable接收URL中的请求参数 五.通过@RequestParam接收请求参数 六.通过@ModelAttribute接收请求参数 大家在开发中经常会用到Spring MVC Controller来接收请求参数,主要常用的接收方式就是通过实体对象以及形参等方式.有些用于GET请求,有些用于POST请求,有些用于两者. 下面的几种常见的后台

  • Spring Boot 自定义数据源DruidDataSource代码

    这篇文章主要介绍了Spring Boot 自定义数据源DruidDataSource代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.添加依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.26</version> </depend

  • SpringMvc接受请求参数的几种情况演示

    说明: 通常get请求获取的参数是在url后面,而post请求获取的是请求体当中的参数.因此两者在请求方式上会有所不同. 1.直接将接受的参数写在controller对应方法的形参当中(适用于get提交方式) /** * 1.直接把表单的参数写在Controller相应的方法的形参中 * * @param username * @param password * @return */ @GetMapping("/addUser1") public String addUser1(Str

随机推荐