Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习
- 1、Spring Cloud Gateway介绍
- 2、在Spring Tool Suite4或者IDEA中创建Gateway工程
- 3、通过代码创建一个Router(路由)
- 4、运行测试
- 5、通过改进程序加深网关理解
- 6、使用配置方式代替代码实现路由
- 7、总结
1、Spring Cloud Gateway介绍
在SpringCloud微服务体系中,有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;但在2.x版本中SpringCloud自己研发了一个网关替代Zuul,那就是Spring Cloud Gateway。Spring Cloud Gateway官网介绍了如何构建一个路由的过程,虽然是英文的,但对程序员来说基本都能看懂。下面我就把练习过程介绍一下。(当然要捡有用的介绍)
2、在Spring Tool Suite4或者IDEA中创建Gateway工程
1、这里我用的Spring Tool Suite 4。首先鼠标点击File->New ->Spring Starter Project,出现新建工程向导对话框,如下图:

- Name栏输入Gateway
- Group栏输入wongoing(组织名)
- Artifact栏输入ms(你可以自己定)
- Package栏输入com.wongoing(自己指定报名)
2、点击[Next >]按钮,进入选择工程依赖对话框,如下图: - 当前最新的Spring Boot版本是:2.4.2(SNAPSHOT)。
- 勾选spring Cloud Routing->Gateway
3、点击[Finish]按钮,完成工程的创建。创建完毕后的pom.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http:///POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0 https:///xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>wongoing</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0-SNAPSHOT</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>关键依赖是
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>3、通过代码创建一个Router(路由)
1、找到程序入口com.wongoing.GatewayApplication.java,增加一段配置路由的代码,具体如下:
package com.wongoing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(p -> p
.path("/get")
.filters(f -> f.addRequestHeader("Hello", "World"))
.uri("http://httpbin.org:80")
).build();
}
}- Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。
- RouteLocatorBuilder用于构建Route。
- 上面路由的意思是把对http://网关地址:8080/get的请求转发至http://httpbin.org:80/get去处理同时在请求头中增加Hello参数,值为World。
其实就是http://localhost:8080/get->http://httpbin.org:80/get
4、运行测试
1、启动Gateway。鼠标右键com.wongoing.GatewayApplication.java的菜单中选择Run As->Spring Boot App。启动日期如下:

2、启动postmain,或者浏览器,在地址栏输入http://localhost:8080/get进行测试,输出如下:

5、通过改进程序加深网关理解
1、修改com.wongoing.GatewayApplication.java代码,增加一个路由,具体如下:
package com.wongoing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(p -> p
.path("/get")
.filters(f -> f.addRequestHeader("Hello", "World"))
.uri("http://httpbin.org:80")
)
.route(p -> p
.path("/test")
.filters(f -> f.addRequestHeader("Author", "CodingPioneer"))
.uri("http://localhost:8090")
).build();
}
}- 第2个.route是新增加的路由配置,意思就是把对http://localhost:8080/test的请求转发至http://localhost:8090/test,并且增加请求头参数Author,值为CodingPioneer。
完了重启一下Getway。
2、为了测试这个路由,我们需要在Spring Tool Suite4中再新建一个Spring Boot工程service1 ,只增加对Spring Web的依赖就行,具体pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http:///POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0 https:///xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>wongoing</groupId>
<artifactId>ms</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>service1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>关键依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>3、在service1工程中创建一个包com.wongoing.controller,在此包下创建一个控制器类HttpController.java,代码如下:
package com.wongoing.controller;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HttpController {
@RequestMapping(value="/test", method= RequestMethod.GET)
@ResponseBody
public Map<String, Object> getMethod(HttpServletRequest request, HttpServletResponse response) throws IOException {
Map<String, Object> result = new HashMap<String, Object>();
Enumeration<String> headers = request.getHeaderNames();
while(headers.hasMoreElements()) {
String headerName = headers.nextElement().toString();
result.put(headerName, request.getHeader(headerName));
}
return result;
}
}4、运行service1,然后在Postmain的地址栏输入http:/localhost:8080/test,运行结果如下:

6、使用配置方式代替代码实现路由
下面我们通过spring配置的方式实现路由配置,代替代码路由。
1、首先把Gateway项目中com.wongoingGatewayApplication.java路由的代码注释掉,如下:
package com.wongoing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
// @Bean
// public RouteLocator myRoutes(RouteLocatorBuilder builder) {
// return builder.routes()
// .route(p -> p
// .path("/get")
// .filters(f -> f.addRequestHeader("Hello", "World"))
// .uri("http://httpbin.org:80")
// )
// .route(p -> p
// .path("/test")
// .filters(f -> f.addRequestHeader("Author", "CodingPioneer"))
// .uri("http://localhost:8090")
// ).build();
// }
}2、把resources/application.properties重命名为resources/application.yml。
3、在resources/application.yml中增加以下内容:
server:
port: 8080 #指定当前服务的端口号
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #是否适用默认路由(通过gatewayUri:port/服务名/path直接访问服务接口)
lower-case-service-id: true #是否忽略服务名大小写
routes: #gateway配置多条路由规则时注意顺序问题
- id: service0 #路由规则ID在上下文中唯一
uri: http://httpbin.org:80 #路由目标服务地址
predicates: #路由条件:请求的路径为http://localhost:8080/get则自动转发至目标服务
- Path=/get
filters: #过滤器链
- AddRequestHeader=Hello, World #添加请求头
- id: service1
uri: http://localhost:8090
predicates:
- Path=/test
filters:
- AddRequestHeader=Author, CodingPioneer4、重启Gateway服务,在浏览器中或postman中重新测试,发现运行结果与代码路由的方式是一样的。
7、总结
通过这个练习实现了对网关不同地址的请求转发至不同服务站点去处理的功能。
- http://localhost:8080/get -> http://httpbin.org/get
- http://localhost:8080/test -> http://localhost:8090/test
















