目录
二说Gateway 路由配置
创建com/springcloud/config/GateWayRoutesConfig.java
测试
动态路由
示意图
代码实现
测试
注意事项和细节
代码
Predicate/断言
基本介绍
Route Predicate Factories
解读
Route Predicate 实例
After Route Predicate
测试
Before Route Predicate
Between Route Predicate
Cookie Route Predicate
Header Route Predicate
Host Route Predicate
编辑Method Route Predicate
Path Route Predicate
Query Route Predicate
RemoteAddr Route Predicate
Filter/过滤器
基本介绍
解读
类型
1 GatewayFilter
2 GlobalFilter
GatewayFilter 使用
编辑
2. 修改e-commerce-gateway-20000 的application.yml
3. 验证
自定义GlobalFilter
代码实现
测试
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 ,
@Configuration
public class GateWayRoutesConfig {
//配置注入路由
/**
* 在理解通过配置类注入/配置 路由,可以对照前面的application.yml来对比理解
* cloud:
* gateway:
* routes: #配置路由,可以配置多个路由 List 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 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 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 就是一组匹配规则,当请求匹配成功,就执行对应的Route, 匹配失败,放弃处理/转发
- 文档地址:
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请求的不同属性。多种谓词工厂可以组合
需求: 只有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
需求: 只有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]
测试步骤和前面的一样这个就不再冲重复了
需求: 只有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 键: 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 有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 是**.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.**
需求: 请求是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方式 所以会报错
1. 参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories
解读: Path 可以有多个, 使用逗号间隔
需求: 请求有参数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
需求: 请求的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
测试完毕,记得代码恢复到测试前
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的工厂类来产生
文档地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#global-filters
1 开发直接使用GatewayFilter 较少,一般是自定义过滤器
2 参考实例
参考文档地址:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#the-addrequestheader-gatewayfilter-factory
#- RemoteAddr=127.0.0.1
filters:
- AddRequestParameter=color, blue#过滤器工厂会在匹配的请求头加上一对请求头,名称为color 值为blue
- AddRequestParameter=age, 18#过滤器工厂会在匹配的请求头加上一对请求头,名称为age 值为18
修改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 + "不存在");
}
}
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 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
如果不通过就 显示这个
测试完毕,记得代码恢复到测试前