欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
- 作为《Spring Cloud Gateway实战》系列的第十四篇,本文会继续发掘Spring Cloud Gateway的潜力,通过编码体验操控网关的乐趣,开发出一个实用的功能:让Spring Cloud Gateway应用在收到请求后,可以按照业务的需要跳转到任意的地址去
一般路由规则
- spring:
- application:
- name: hello-gateway
- cloud:
- gateway:
- routes:
- - id: path_route
- uri: http://127.0.0.1:8082
- predicates:
- - Path=/hello/**
复制代码
- 上述规则的功能如下图所示,假设这就是生产环境的样子,192.168.50.99:8082是提供服务的后台应用:

特殊规则
- 以上是常规情况,但也有些特殊情况,要求SpringCloud Gateway把浏览器的请求转发到不同的服务上去
- 如下图所示,在之前的环境中增加了另一个服务(即蓝色块),假设蓝色服务代表测试环境

- 浏览器发起的/hello/str请求中,如果header中带有tag-test-user,并且值等于true,此时要求SpringCloud Gateway把这个请求转发到测试环境
- 如果浏览器的请求header中没有tag-test-user,SpringCloud Gateway需要像以前那样继续转发到192.168.50.99:8082
- 很明显,上述需求难以通过配置来实现,因为转发的地址和转发逻辑都是围绕业务逻辑来定制的,这也就是本篇的目标:对同一个请求path,可以通过编码转发到不同的地方去
- 实现上述功能的具体做法是:自定义过滤器
设计
- 编码之前先设计,把关键点想清楚再动手
- 今天咱们要开发一个SpringCloud Gateway应用,里面新增一个自定义过滤器
- 实现这个功能需要三个知识点作为基础,也就是说,您会通过本篇实战掌握以下知识点:
- 自定义过滤器
- 自定义过滤器的配置参数和bean的映射
- 编码构造Route实例
- 用思维导图将具体工作内容展开,如下图所示,咱们就按部就班的实现吧:

源码下载
名称链接备注项目主页https://github.com/zq2599/blog_demos该项目在GitHub上的主页git仓库地址(https)https://github.com/zq2599/blog_demos.git该项目源码的仓库地址,https协议git仓库地址(ssh)git@github.com:zq2599/blog_demos.git该项目源码的仓库地址,ssh协议
- 这个git项目中有多个文件夹,本篇的源码在spring-cloud-tutorials文件夹下,如下图红框所示:
- spring-cloud-tutorials内部有多个子项目,本篇的源码在gateway-dynamic-route文件夹下,如下图红框所示:

编码
- 新建名为gateway-dynamic-route的maven工程,其pom.xml内容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>spring-cloud-tutorials</artifactId>
- <groupId>com.bolingcavalry</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>gateway-dynamic-route</artifactId>
- <dependencies>
- <dependency>
- <groupId>com.bolingcavalry</groupId>
- <artifactId>common</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-gateway</artifactId>
- </dependency>
- </dependencies>
- <build>
- <plugins>
-
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <configuration>
- <mainClass>com.bolingcavalry.gateway.GatewayDynamicRouteApplication</mainClass>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>repackage</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </project>
复制代码- package com.bolingcavalry.gateway;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- @SpringBootApplication
- public class GatewayDynamicRouteApplication {
- public static void main(String[] args) {
- SpringApplication.run(GatewayDynamicRouteApplication.class,args);
- }
- }
复制代码
- 接下来是本篇的核心,自定义过滤器类,代码中已经添加了详细的注释,有几处要注意的地方稍后会提到:
- BizLogicRouteConfig是过滤器的配置类,可以在使用过滤器时在配置文件中配置prodEnvUri和testEnvUri的值,在代码中可以通过这两个字段取得配置值
- 过滤器的工厂类名为BizLogicRouteGatewayFilterFactory,按照规则,过滤器的名字是BizLogicRoute
- 在apply方法中,重新创建ServerHttpRequest和Route对象,它们的参数可以按照业务需求随意设置,然后再将这两个对象设置给SpringCloud gateway的处理链中,接下来,处理链上的其他过滤拿到的就是新的ServerHttpRequest和Route对象了
配置
- server:
- #服务端口
- port: 8086
- spring:
- application:
- name: gateway-dynamic-route
- cloud:
- gateway:
- routes:
- - id: path_route
- uri: http://0.0.0.0:8082
- predicates:
- - Path=/hello/**
- filters:
- - name: BizLogicRoute
- args:
- prodEnvUri: http://127.0.0.1:8082
- testEnvUri: http://127.0.0.1:8087
复制代码 开发和启动后台服务,模拟生产和测试环境
- 接下来开始验证功能是否生效,咱们要准备两个后台服务:
- 模拟生产环境的后台服务是provider-hello,监听端口是8082,其/hello/str接口的返回值是Hello World, 2021-12-12 10:53:09
- 模拟测试环境的后台服务是provider-for-test-user,监听端口是8087,其/hello/str接口的返回值是Hello World, 2021-12-12 10:57:11 (from test enviroment)(和生产环境相比,返回内容多了个(from test enviroment)),对应Controller参考如下:
- package com.bolingcavalry.provider.controller;
- import com.bolingcavalry.common.Constants;
- import org.springframework.web.bind.annotation.*;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Map;
- @RestController
- @RequestMapping("/hello")
- public class Hello {
- private String dateStr(){
- return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
- }
- /**
- * 返回字符串类型
- * @return
- */
- @GetMapping("/str")
- public String helloStr() {
- return Constants.HELLO_PREFIX + ", " + dateStr() + " (from test enviroment)";
- }
- }
复制代码
- 以上两个服务,对应的代码都在我的Github仓库中,如下图红框所示:

- 启动gateway-dynamic-route、provider-hello、provider-for-test-user服务
- 此时,SpringCloud gateway应用和两个后台服务都启动完成,情况如下图,接下来验证刚才开发的过滤器能不能像预期那样转发:

验证
- 用postman工具向gateway-dynamic-route应用发起一次请求,返回值如下图红框所示,证明这是provider-hello的响应,看来咱们的请求已经正常到达:

- 再发送一次请求,如下图,这次在header中加入键值对,得到的结果是provider-for-test-user的响应

- 至此,过滤器的开发和验证已经完成,通过编码,可以把外部请求转发到任何咱们需要的地址去,并且支持参数配置,这个过滤器还有一定的可配置下,减少了硬编码的比率,如果您正在琢磨如何深度操控SpringCloud Gateway,希望本文能给您一些参考;
欢迎关注博客园:程序员欣宸
学习路上,你不孤单,欣宸原创一路相伴...
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |