SpringCloud-Gateway的详细讲解以及完整的示意图和代码-下

目录

二说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

代码实现

测试


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

如果不通过就 显示这个

 

 测试完毕,记得代码恢复到测试前

猜你喜欢

转载自blog.csdn.net/apple_67445472/article/details/131115882