简单网关演示
Spring Gateway不是一个软件,而是一个依赖,所以我们要使用它需要创建一个Spring Boot项目
这个项目也要注册到注册中心,因为网关项目也是微服务项目的一部分
beijing和shanghai的项目,这个就是简单的Spring Boot项目也需要注册到注册中心,但是只需要控制层即可
创建gateway项目
gateway项目就是网关项目,需要添加配置
pom.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.tedu</groupId> <artifactId>csmall</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath/> </parent> <groupId>cn.tedu</groupId> <artifactId>gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>gateway</name> <description>Demo project for Spring Boot</description>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </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> </plugin> </plugins> </build>
</project>
|
application.yml配置
1 2 3 4 5 6 7 8 9 10 11
| server: port: 10000
spring: application: name: gateway-server
cloud: nacos: discovery: server-addr: localhost:8848
|
创建beijing项目
接下来创建beijing项目
pom文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.tedu</groupId> <artifactId>csmall</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath/> </parent> <groupId>cn.tedu</groupId> <artifactId>gateway-beijng</artifactId> <version>0.0.1-SNAPSHOT</version> <name>gateway-beijng</name> <description>Demo project for Spring Boot</description> <properties> <java.version>8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies> </project>
|
application.yml文件
1 2 3 4 5 6 7 8 9 10 11 12
| server: port: 9001
spring: application: name: beijing
cloud: nacos: discovery: server-addr: localhost:8848
|
创建controller层,提供访问以及返回的信息
1 2 3 4 5 6 7 8
| @RestController @RequestMapping("/bj") public class BeiJingController { @GetMapping("/show") public String show(){ return "这里是北京~"; } }
|
创建shanghai项目
接下来创建shanghai项目
pom文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>cn.tedu</groupId> <artifactId>csmall</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath/> </parent> <groupId>cn.tedu</groupId> <artifactId>gateway-beijng</artifactId> <version>0.0.1-SNAPSHOT</version> <name>gateway-shanghai</name> <description>Demo project for Spring Boot</description> <properties> <java.version>8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies> </project>
|
application.yml文件
1 2 3 4 5 6 7 8 9 10 11 12
| server: port: 9002
spring: application: name: shanghai
cloud: nacos: discovery: server-addr: localhost:8848
|
创建controller层,提供访问以及返回的信息
1 2 3 4 5 6 7 8
| @RestController @RequestMapping("/sh") public class BeiJingController { @GetMapping("/show") public String show(){ return "这里是上海~"; } }
|
通过gateway项目访问其他服务
我们想要实现的目标是
通过10000端口访问beijing和shanghai这两个服务
从而实现gateway成为项目的统一入口的效果,需要添加SpringMVC的依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
|
配置application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| server: port: 10000
spring: application: name: gateway-server
cloud: nacos: discovery: server-addr: localhost:8848 gateway: routes: - id: beijing uri: lb://beijing predicates: - Path=/bj/** - id: shanghai uri: lb://shanghai predicates: - Path=/sh/**
|
测试
首先启动nacos服务
然后顺序启动beijing、shanghai、gateway服务
访问路径为: http://localhost:10000/bj/show
http://localhost:10000/sh/show
我们在启动gateway项目时,报错,提示以下内容
1 2 3 4 5 6 7
| Description:
Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway.
Action:
Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.
|
在同一个项目中引入Spring MVC和Gateway的依赖,默认情况下启动会报错
原因是Spring MVC框架中自带一个Tomcat服务器
而Gateway框架中自带一个Netty的服务器
在项目启动时,两个框架中包含的服务器都想占用相同的端口,因为争夺端口号和主动权而发生冲突,导致服务启动异常
Action中给出了解决方案,可以通过spring.main.web-application-type=reactive启动netty服务器,或者移除web依赖
gateway内置断言
除了使用的Path
还有很多其他的断言,比如
after
before
between
cookie
header
host
method
query
remoteaddr
时间相关的断言
after
、before
、between
判断当前时间在指定时间之后、之前、之间的操作
如果条件满足可以执行路由操作,否则拒绝访问
利用代码获得当前时间格式
时间格式可能是这样
1
| 2023-01-04T21:16:42.213+08:00[Asia/Shanghai]
|
使用after断言,在指定时间之后才能访问
1 2 3
| predicates: - Path=/sh/** - After=2023-01-04T21:22:42.213+08:00[Asia/Shanghai]
|
使用before断言,指定时间之前才能访问
1
| - Before=2023-01-04T21:16:42.213+08:00[Asia/Shanghai]
|
使用between断言,在指定时间之间才能访问
1
| - Between=2023-01-04T21:16:42.213+08:00[Asia/Shanghai],2023-01-04T21:24:42.213+08:00[Asia/Shanghai]
|
要求指定请求参数
query断言,判断是否包含指定的参数名称,包含指定参数名称才能通过路由
1
| - Query=name #检查请求中是否包含name参数(可以没有值),包含才能路由
|
内置过滤器
Gateway还提供了内置的过滤器
内置过滤器允许我们在路由请求到目标的同时,对这个请求进行一些加工或处理
演示AddRequestParameter过滤器,他的作用在请求中添加参数
1 2 3 4 5
| filters: - AddRequestParameter=age,80 predicates: - Path=/sh/** - Query=name
|
在shanghai的控制器方法中添加接收name和age参数的代码
1 2 3 4 5 6 7 8 9
| @RestController @RequestMapping("/sh") public class ShangHaiController { @GetMapping("/show") public String show(String name,Integer age){ System.out.println(ZonedDateTime.now()); return "这里是上海~"+name+","+age; } }
|
动态路由
网关项目随着微服务数量的增多,gateway项目的yml文件配置会越来越多,维护的工作量也会越来越大
所以我们希望gateway能够自动路由到每个模块,也就是有默认的路由规则生成
这样的话,我们不管当前项目有多少个路由目标,都不需要维护yml文件了
这个就是Spring Gateway的动态路由功能,可以通过以下配置开启
1 2 3 4 5 6 7 8
| spring: cloud: gateway: discovery: locator: enabled: true
|
注意:gateway项目要从注册中心中获得服务名称,所以一定要在gateway服务启动之前就保证注册中心中的服务列表完整,意思就是gateway服务最后启动