前言
Spring Cloud Gateway 基于 Spring Boot 2,是 Spring Cloud 的全新项目。Gateway 旨在提供一种简单而有效的途径来转发请求,并为它们提供横切关注点。
gateway相当于所有服务的门户,将客户端请求与服务端应用相分离,客户端请求通过gateway后由定义的路由和断言进行转发,路由代表需要转发请求的地址,断言相当于请求这些地址时所满足的条件,只有同时符合路由和断言才给予转发。
本篇博客介绍Spring Cloud Gateway 的基本概念,引入依赖需要注意的事项,以及解决方案;还有全局网关的入门使用案例。
目录
- 前言
- 引出
- 网关gateway
- 网关是啥
- 引入依赖和基本运作模式
- 如果用springmvc需要设置一下
- 方式一:配置文件
- 方式二:排除tomcat
- 全局网关
- 网关的相关代码
- 1.导入依赖
- 2.配置config
- 3.网关AuthGateway
- 4.主启动类
- 总结
引出
1.Spring Cloud Gateway 的基本概念;
2.引入依赖需要注意的事项,以及解决方案;
3.全局网关的入门使用案例;
网关gateway
网关是啥
API 网关是一个服务,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API 网关封装了系统内部架构,为每个客户端提供一个定制的 API 。它可能还具有其它职责,如身份验证、监控、负载均衡、限流、降级与应用检测。
Spring Cloud Gateway 基于 Spring Boot 2,是 Spring Cloud 的全新项目。Gateway 旨在提供一种简单而有效的途径来转发请求,并为它们提供横切关注点。
Spring Cloud Gateway 中最重要的几个概念:
-
路由 Route:路由是网关最基础的部分,路由信息由一个 ID 、一个目的 URL 、一组断言工厂和一组 Filter 组成。如果路由断言为真,则说明请求的 URL 和配置的路由匹配。
-
断言 Predicate:Java 8 中的断言函数。Spring Cloud Gateway 中的断言函数输入类型是 Spring5.0 框架中的 ServerWebExchange 。Spring Cloud Gateway 中的断言函数允许开发者去定义匹配来自 Http Request 中的任何信息,比如请求头和参数等。
-
过滤器 Filter:一个标准的 Spring Web Filter。Spring Cloud Gateway 中的 Filter 分为两种类型:Gateway Filter 和 Global Filter。过滤器 Filter 将会对请求和响应进行修改处理。
zuul---->SpringCloud,gateway---->zuul2.0
过去做法:Eureak + zuul2.0 + config
现在做法:SpringCloud-nacos + gateway,rocketMQ/RabbitMQ/ActiveMQ
引入依赖和基本运作模式
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置文件访问流程的分析
参数解释
如果用springmvc需要设置一下
方式一:配置文件
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tianju</groupId>
<artifactId>spring-cloud-move</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.tianju.gateway</groupId>
<artifactId>movie-gateway</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 如果需要用web,则需要排除一下tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包成可运行的jar包-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置文件的解决方案
spring:
cloud:
# nacos的部分
nacos:
discovery: # 注册中心
server-addr: http://192.168.111.130:8848/
register-enabled: true
# 网关部分
gateway:
discovery:
locator:
enabled: true # 允许定位
routes: # 路由
- id: my-hello-id # id要唯一
uri: lb://movie-cinema/api # 在nacos里根据服务名称找
predicates:
# http://localhost:18888/hello-wx/api/cinema/checkGenreInThisCinema
- Path=/hello-wx/** # 比如输了 ip+端口/hello-wx/** 然后在nacos找真的路径
filters:
- StripPrefix=1 # 替换第一个,内置的filter过滤器
- id: my-hello-baidu # id要唯一
uri: https://www.sohu.com
predicates:
# http://localhost:18888/hello-ly
- Path=/hello-ly/**
# 如要要用spring web,则把tomcat排除一下
main:
web-application-type: reactive
启动的是tomcat
方式二:排除tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
全局网关
package com.tianju.gateway.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class AuthGateway implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.debug("我是全局过滤器>>>>>>>>>>");
return null;
}
@Override
public int getOrder() {
return 0;
}
}
package com.tianju.gateway.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class AuthGateway implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.debug("我是全局过滤器>>>>>>>>>>");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
网关的相关代码
1.导入依赖
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tianju</groupId>
<artifactId>spring-cloud-move</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.tianju.gateway</groupId>
<artifactId>movie-gateway</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 如果需要用web,则需要排除一下tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.tianju.common</groupId>
<artifactId>movie-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包成可运行的jar包-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.配置config
bootstrap.yml文件
spring:
cloud:
# nacos的部分
nacos:
discovery: # 注册中心
server-addr: http://192.168.111.130:8848/
register-enabled: true
# 网关部分
gateway:
discovery:
locator:
enabled: true # 允许定位
routes: # 路由
- id: my-hello-id # id要唯一
uri: lb://movie-cinema/api # 在nacos里根据服务名称找
predicates:
# http://localhost:18888/hello-wx/api/cinema/checkGenreInThisCinema
- Path=/hello-wx/** # 比如输了 ip+端口/hello-wx/** 然后在nacos找真的路径
filters:
- StripPrefix=1 # 替换第一个,内置的filter过滤器
- id: my-hello-baidu # id要唯一
uri: https://www.sohu.com
predicates:
# http://localhost:18888/hello-ly
- Path=/hello-ly/**
# 如要要用spring web,则把tomcat排除一下
main:
web-application-type: reactive
application.yml
server:
port: 18888
spring:
application:
name: movie-gateway
logging:
level:
com.tianju.gateway: debug
3.网关AuthGateway
package com.tianju.gateway.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tianju.common.result.HttpResp;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
@Component
@Slf4j
// http://localhost:18888/hello-wx/api/cinema/checkGenreInThisCinema
public class AuthGateway implements GlobalFilter, Ordered {
@Override
@SneakyThrows
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.debug("我是全局过滤器>>>>>>>>>>");
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
// 请求request 的URL:http://localhost:18888/hello-wx/api/cinema/checkGenreInThisCinema
log.debug("请求request 的URL:"+request.getURI());
log.debug("请求request 数据"+request.getHeaders().get("jwt"));
// String jwt = "请求request 数据" + request.getHeaders().get("jwt").get(0);
if (Objects.isNull(request.getHeaders().get("jwt"))){ // 如果没有携带token
response.setStatusCode(HttpStatus.UNAUTHORIZED);
ObjectMapper objectMapper = new ObjectMapper();
DataBuffer buffer = response.bufferFactory()
.wrap(objectMapper.writeValueAsString(HttpResp.failed("没有jwt"))
.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(buffer));
}else {
return chain.filter(exchange);
}
}
@Override
public int getOrder() {
return 0;
}
}
4.主启动类
package com.tianju.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApp {
public static void main(String[] args) {
SpringApplication.run(GatewayApp.class);
}
}
总结
1.Spring Cloud Gateway 的基本概念;
2.引入依赖需要注意的事项,以及解决方案;
3.全局网关的入门使用案例;