SpringCloud06_Gateway的概述工程案例代码微服务动态路由Predicate的使用详解Filter(建议收藏)
Posted 所得皆惊喜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud06_Gateway的概述工程案例代码微服务动态路由Predicate的使用详解Filter(建议收藏)相关的知识,希望对你有一定的参考价值。
文章目录
①. gateway的概述
-
①. SpringCloud Gateway是SpringCloud的一个全新项目,基于spring5.0 + spring boot2.0+Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式
-
②. SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty
-
③. SpringCloud Gateway的目标提供统一的路由方式且基于Filter键的方式提供了网关基本的功能,例如:安全 | 监控 | 指标和限流(动态路由、认证授权、令牌限流)
②. 路由、断言、过滤器
-
①. 路由(route) 路由信息的组成:由一个ID、一个目的URL、一组断言工厂、一组Filter组成。如果路由断言为真,说明请求URL和配置路由匹配
-
②. 断言(Predicate) 参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
-
③. 过滤器(Filter) 一个标准的Spring WebFilter。 Spring Cloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理
③. 新建module9527 yml的配置方式
-
①. cloud-gateway-gateway9527
-
②. pom
注意:要移除web和boot防止报错
<dependencies>
<!--新增gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--
移除这两个
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>-->
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- ③. 主启动类
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GateWayMain9527.class, args);
}
}
- ④. yml配置(重点)
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh2
uri: http://localhost:8001
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
④. 硬编码 注入RouteLocator的Bean
- ①. 当我们访问http://localhost:9527/guonei 会跳转到http://news.baidu.com/guonei(了解)
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
/*
id相当于yml中配置的唯一标识
当你访问http://localhost:9527/guonei
就会跳转到http://news.baidu.com/guonei
*/
routes.route("path_rote_xiaozhi",
r -> r.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
@Bean
public RouteLocator customRouteLocator2(RouteLocatorBuilder builder) {
RouteLocatorBuilder.Builder routes = builder.routes();
routes.route("path_route_xiaozhi2", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
return routes.build();
}
}
⑤. 通过微服务名实现动态路由
-
①. 默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
-
②. 一个eureka7001 + 两个服务提供者8001/8002
-
③. YML 掌握
- 需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能
- lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://CLOUD-PAYMENT-SERVICE #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
- ④. 测试:http://localhost:9527/payment/lb (8001/8002两个端口切换)
⑥. Predicate的使用
①. Predicate的概述
-
①. Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理
-
②. Predicate的介绍(启动我们的gatewat9527)
-
③. Route Predicate Factories这个是什么东东?
-
③. 常用的Route Predicate
下面代码非常重要,需要重点掌握
//常用的时间串串
public class ZonedDateTimeDemo {
public static void main(String[] args) {
ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
System.out.println(zbj);//2021-07-16T19:39:36.874+08:00[Asia/Shanghai]
ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
//2021-07-16T07:39:36.876-04:00[America/New_York]
System.out.println(zny);
}
}
②. 常用的Route Predicate
- ①. After Route Predicate
//常用的时间串串
public class ZonedDateTimeDemo {
public static void main(String[] args) {
ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
System.out.println(zbj);//2021-07-16T19:39:36.874+08:00[Asia/Shanghai]
ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
//2021-07-16T07:39:36.876-04:00[America/New_York]
System.out.println(zny);
}
}
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能
routes:
- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
# 断言,路径相匹配的进行路由
- Path=/payment/lb/**
# 断言,路径相匹配的进行路由
- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]
- ②. Before Route Predicate
- ③. Between Route Predicate
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能
routes:
- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,路径相匹配的进行路由
#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai] # 断言,路径相匹配的进行路由
#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai] # 断言,路径相匹配的进行路由
- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]
- ④. Cookie Route Predicate
加入curl返回中文乱码
- ⑤. Header Route Predicate
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://CLOUD-PAYMENT-SERVICE #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- After=2021-07-28T10:59:34.102+08:00[Asia/Shanghai]
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
#- Before=2021-07-28T10:59:34.102+08:00[Asia/Shanghai]
#- Cookie=username, TANGZHI
- Header=X-Request-Id, \\d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
- ⑥. Host Route Predicate
正确:curl http://localhost:9527/payment/lb -H “Host: www.tangzhi.com”
正确:curl http://localhost:9527/payment/lb -H “Host: java.tangzhi2.com”
错误:curl http://localhost:9527/payment/lb -H “Host: java.tangzhi2.net”
- Host=**.tangzhi.com,**.tangzhi2.com
- ⑦. Method Route Predicate
- Method=GET
- ⑧. Path Route Predicate
# 断言,路径相匹配的进行路由
- Path=/payment/lb/**
- ⑨. Query Route Predicate
- Query=username, \\d+ # 要有参数名username并且值还要是整数才能路由
- ⑩. All code如下:
spring
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh2
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
#- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
#- Cookie=username,zhangshuai #并且Cookie是username=zhangshuai才能访问
#- Header=X-Request-Id, \\d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.tangzhi.com
#- Method=GET
#- Query=username, \\d+ #要有参数名称并且是正整数才能路由
⑦. Filter的使用
①. Filter的概述
-
①. 路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用
-
②. Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生
②. Spring Cloud Gateway的Filter
-
①. 生命周期,Only Two(pre、post)
-
②. 种类,Only Two(GatewayFilter、GlobalFilter)
③. 自定义过滤器(自定义全局GlobalFilter)
- ①. 在com.atguigu.springcloud.filter创建MyLogGateWayFilter类
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: "+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("username");
if(StringUtils.isEmpty(username)){
log.info("*****用户名为Null 非法用户,(┬_┬)");
//设置响应状态码为未授权
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//给人家一个回应
return exchange.getResponse().setComplete();
}
return chain.filter(exchange以上是关于SpringCloud06_Gateway的概述工程案例代码微服务动态路由Predicate的使用详解Filter(建议收藏)的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud --- 服务网关 (Gateway)