目录
创建com/springcloud/config/GateWayRoutesConfig.java
2. 修改e-commerce-gateway-20000 的application.yml
SpringCloud-Gateway的详细讲解以及完整的示意图和代码演示-下
二说Gateway 路由配置
1 方式1: application.yml 中配置-前面讲过
2 方式2: 编写配置类注入【了解】
先注销application.yml 对网关路由部分注销 网关部分只保留
spring:
application:
name: e-commerce-gateway
2. 重启e-commerce-gateway-20000, 再次测试,网关路由失效
3. 参考官方文档
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#spring-cloud-circuitbreaker-filter-factory ,
创建com/springcloud/config/GateWayRoutesConfig.java
@Configuration
public class GateWayRoutesConfig {
//配置注入路由
/**
* 在理解通过配置类注入/配置 路由,可以对照前面的application.yml来对比理解
* cloud:
* gateway:
* routes: #配置路由,可以配置多个路由 List<RouteDefinition> routes
* - id: member_route01 #路由的id, 程序员自己配置,要求唯一
* #gateway 最终访问的url 是 url=uri+Path
* #匹配后提供服务的路由地址: 也可以是外网 http://www.baidu.com
* #比如: 客户端/浏览器请求 url http://localhost:20000/member/get/1
* #如果根据Path匹配成功 最终访问的url/转发url 就是 url=http://localhost:10000/member/get/1
* #如果匹配失败, 则有gateway返回404信息
* #疑问: 这里配置的 uri 是固定,在当前这种情况其实可以没有有Eureka Server,后面会使用灵活方式
* # 配置,就会使用到Eureka Server
* uri: http://localhost:10000
* predicates: #断言,可以有多种形式
* - Path=/member/get/**
*/
@Bean
public RouteLocator myRouteLocator04(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
//方法写完
//梳理
//1. 下面的方法我们分别指定了id , uri 和path
//2. Function<PredicateSpec, Route.AsyncBuilder> fn
//(1) 是一个函数式接口
//(2) 接收的类型是 PredicateSpec ,返回的类型是 Route.AsyncBuilder
//(3) r -> r.path("/member/get/**")
// .uri("http://localhost:10000") 就是lambda表达式
//(4) 一会还要用代码进行说明-先使用-再理解
//3. 小伙伴们可以理解这是一个规定写法
return routes.route("member_route04", r -> r.path("/member/get/**")
.uri("http://localhost:10000"))
.build();
}
@Bean
public RouteLocator myRouteLocator05(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
return routes.route("member_route05", r -> r.path("/member/save")
.uri("http://localhost:10000"))
.build();
}
}
测试
1 启动e-commerce-eureka-server-9001
2 启动member-service-provider-10000
3 启动e-commerce-gateway-20000
4 浏览器:(通过网关访问) http://localhost:20000/member/get/1
结果和前面的一样这里就不再展示了
方别忘了,将代码恢复成yml 配置
动态路由
示意图
代码实现
1. 修改e-commerce-gateway-20000 的application.yml
spring:
application:
name: e-commerce-gateway
cloud:
gateway:
routes: #配置路由,可以配置多个路由 List<RouteDefinition> routes
- id: member_route01 #路由的id, 程序员自己配置,要求唯一
#gateway 最终访问的url 是 url=uri+Path
#匹配后提供服务的路由地址: 也可以是外网 http://www.baidu.com
#比如: 客户端/浏览器请求 url http://localhost:20000/member/get/1
#如果根据Path匹配成功 最终访问的url/转发url 就是 url=http://localhost:10000/member/get/1
#如果匹配失败, 则有gateway返回404信息
# 配置,就会使用到Eureka Server
#解读
#1. lb: 协议名 , member-service-provider 注册到eureka server 服务名(小写)
#2. 默认情况下,负载均衡算法是轮询
uri: lb://member-service-provider
predicates: #断言,可以有多种形式
- Path=/member/get/**
- id: member_route02 #路由的id, 程序员自己配置,要求唯一
uri: lb://member-service-provider
predicates: #断言,可以有多种形式
#这时如果客户端/浏览器 访问gateway 的url http://localhost:20000/member/save
#匹配Path成功 最终访问的url 就是 http://localhost:10000/member/save
- Path=/member/save
测试
1 启动e-commerce-eureka-server-9001
2 启动member-service-provider-10000
3 启动e-commerce-gateway-20000
4 浏览器:(通过网关访问) http://localhost:20000/member/get/1
Postman 测试添加(走网关, 前面演示过了这里就不再展示了)
注意事项和细节
1 配置好动态路由后Gateway 会根据注册中心上微服务名,为请求创建动态路由,实现动态路由功能
2 使用的lb 协议支持负载均衡-轮询算法
3 配置自己的负载均衡算法, 测试完毕恢复成原来的轮询算法
代码
/**
* RibbonRule: 配置类-配置自己的负载均衡算法
*/
@Configuration
public class RibbonRule {
//配置注入自己的负载均衡算法
@Bean
public IRule myRibbonRule() {
//这里老师返回的是RandomRule,当然小伙伴也可以自己指定
return new RandomRule();
}
}
Predicate/断言
基本介绍
一句话: Predicate 就是一组匹配规则,当请求匹配成功,就执行对应的Route, 匹配失败,放弃处理/转发
Route Predicate Factories
- 文档地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
解读
1. Spring Cloud Gateway包括许多内置的Route Predicate工厂, 所有这些Predicate都与HTTP请求的不同属性匹配, 可以组合使用.
2. Spring Cloud Gateway 创建Route 对象时,使用RoutePredicateFactory 创建Predicate对象,Predicate 对象可以赋值给Route。
3. 所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合
Route Predicate 实例
After Route Predicate
需求: 只有2022-11-18 12:35:50 之后的请求才进行匹配/转发, 不满足该条件的,不处理
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/
html/#gateway-request-predicates-factories
2. 修改e-commerce-gateway-20000 的application.yml
注意这里只展示需要修改的地方了全部配置上面有
predicates:
- Path=/member/get/** #断言,路径相匹配的进行路由
- After=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
3. 如何获取时间格式, 创建一个测试类,来获取当前时间,再根据需要修改
springcloud/T2.java
public class T2 {
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
}
}
测试
启动e-commerce-eureka-server-9001
启动member-service-provider-10000/10002
启动e-commerce-gateway-20000
浏览器:(通过网关访问) http://localhost:20000/member/get/1
Before Route Predicate
需求: 只有2022-11-18 12:35:50 之前的请求才进行匹配/转发, 不满足该条件的,不处理
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/
html/#gateway-request-predicates-factories
2. 修改e-commerce-gateway-20000 的application.yml
predicates:
- Path=/member/get/** #断言,路径相匹配的进行路由
#- After=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
- Before=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
测试步骤和前面的一样这个就不再冲重复了
Between Route Predicate
需求: 只有2020-11-18 12:35:50 和2022-11-18 12:35:50 之间的请求才进行匹配/转发, 不满足该条件的,不处理
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/
html/#gateway-request-predicates-factories
2. 修改e-commerce-gateway-20000 的application.yml
predicates:
- Path=/member/get/** #断言,路径相匹配的进行路由
#- After=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
#- Before=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
-
Between=2020-11-18T12:35:50.387+08:00[Asia/Shanghai],2022-11-18T12:35:50.387+0
8:00[Asia/Shanghai]
Cookie Route Predicate
需求: 请求带有cookie 键: user 值: nihao才匹配/断言成功
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/
html/#gateway-request-predicates-factories
解读:
chocolate 是cookie 名字ch.p 是cookie 的值,是按照正则表达式来匹配的
2. 修改e-commerce-gateway-20000 的application.yml
predicates:
- Path=/member/get/** #断言,路径相匹配的进行路由
#- After=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
#- Before=2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
#-Between=2020-11-18T12:35:50.387+08:00[Asia/Shanghai],2022-11-18T12:35:50.387+08:00[Asia/Shanghai]
- Cookie=user, nihao
这个有点特殊所以单独截图
如果和前面的一样这里就不在展示了
Header Route Predicate
需求: 请求头Header 有X-Request-Id, 并且值hello 才匹配/断言成功
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/
html/#gateway-request-predicates-factories
解读: X-Request-Id 是header 的名称, \d+ 是一个正则表达式
2. 修改e-commerce-gateway-20000 的application.yml
#- Cookie=key1, abc
- Header=X-Request-Id, hello
Host Route Predicate
需求: 请求Host 是**.wyxedu.** 才匹配/断言成功, 比如Host www.wyxedu.com
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
解读: Host 可以有多个, 使用逗号间隔
2. 修改e-commerce-gateway-20000 的application.yml
#- Header=X-Request-Id, hello
- Host=**.wyxedu.**
Method Route Predicate
需求: 请求是Get 方式才匹配/断言成功
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
解读: 请求方式可以有多个, 使用逗号间隔
2. 修改e-commerce-gateway-20000 的application.yml
#- Host=**.wyxedu.**
- Method=GET
注意 我们设置的GET方式 所以会报错
Path Route Predicate
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
解读: Path 可以有多个, 使用逗号间隔
Query Route Predicate
需求: 请求有参数email ,并且满足电子邮件的基本格式, 才能匹配/断言成功
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
解读: red 是参数名gree. 是值, 支持正则表达式
2. 修改e-commerce-gateway-20000 的application.yml
#- Host=**.wyxedu.**
#- Method=GET
- Query=email, [\w-]+@([a-zA-Z]+\.)+[a-zA-Z]+
注意启动哪些服务都是一样的
这里再提醒一下
启动e-commerce-eureka-server-9001
启动member-service-provider-10000/10002
启动e-commerce-gateway-20000
RemoteAddr Route Predicate
需求: 请求的IP 是127.0.0.1, 才能匹配/断言成功
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
2. 修改e-commerce-gateway-20000 的application.yml
#提示:通过http://127.0.0.1:20000/member/get/1 ,可以看到效果.
- RemoteAddr=127.0.0.1
注意因为本机默认ip是127.0.0.1 所以可以不用直接指定 但是如果是其他的ip就需要指定
如请求的是192.168.1.2 如果想要看到效果的话就 http://192.168.1.2:20000/member/get/1
测试完毕,记得代码恢复到测试前
Filter/过滤器
基本介绍
1. 文档地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories
解读
路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应
Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生
类型
1 GatewayFilter
2 GlobalFilter
文档地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#global-filters
GatewayFilter 使用
1 开发直接使用GatewayFilter 较少,一般是自定义过滤器
2 参考实例
参考文档地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#the-addrequestheader-gatewayfilter-factory
2. 修改e-commerce-gateway-20000 的application.yml
#- RemoteAddr=127.0.0.1
filters:
- AddRequestParameter=color, blue#过滤器工厂会在匹配的请求头加上一对请求头,名称为color 值为blue
- AddRequestParameter=age, 18#过滤器工厂会在匹配的请求头加上一对请求头,名称为age 值为18
3. 验证
修改member-service-provider-10000\src\main\java\com\springcloud\controller\MemberController.java
@GetMapping("/member/get/{id}")
public Result getMemberById(@PathVariable("id") Long id, HttpServletRequest request) {
String color = request.getParameter("color");
String address = request.getParameter("age");
Member member = memberService.queryMemberById(id);
//使用Result把查询到的结果返回
if (member != null) {
return Result.success("查询会员成功 member-service-provider-10000 " + color + "-" + age, member);
} else {
return Result.error("402", "ID= " + id + "不存在");
}
}
自定义GlobalFilter
1 需求分析/图解
1. 自定义全局GlobalFilter 过滤器
2. 如果请求参数user=wyxdu, pwd=123456 则放行, 否则不能通过验证
代码实现
1. 在e-commerce-gateway-20000 创建com/springcloud/filter/CustomGateWayFilter.java
@Component
public class CustomGateWayFilter implements GlobalFilter, Ordered {
//filter是核心的方法,将我们的过滤的业务,写在该方法中
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("------CustomGateWayFilter------");
//先获取到对应的参数值
//比如 http://localhost:20000/member/get/1?user=wyxedu&pwd=123456
String user =
exchange.getRequest().getQueryParams().getFirst("user");
String pwd = exchange.getRequest().getQueryParams().getFirst("pwd");
if(!("wyxdu".equals(user) && "123456".equals(pwd))) {//如果不满足条件
System.out.println("-----非法用户-----");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//回应
return exchange.getResponse().setComplete();
}
//验证通过, 放行
return chain.filter(exchange);
}
//order 表示过滤器执行的顺序, 数字越小, 优先级越高
@Override
public int getOrder() {
return 0;
}
}
测试
1 启动e-commerce-eureka-server-9001
2 启动member-service-provider-10000/10002
3 启动e-commerce-gateway-20000
4 浏览器:(通过网关访问) http://localhost:20000/member/get/1?user=wyxdu&pwd=123456
如果不通过就 显示这个
测试完毕,记得代码恢复到测试前