Gateway学习笔记

目录

介绍:

核心概念

依赖

路由

断言

基本的断言工厂

自定义断言

过滤器

路由过滤器

过滤器工厂

自定义路由过滤器

全局过滤器

其他

过滤器执行顺序

前置后置(?)

跨域问题

[yaml 解决](#yaml 解决)

配置类解决


介绍:

Gateway网络为微服务架构提供简单且统一的API路由管理,作为系统的统一入口。

核心概念

路由 (route):路由是网关中最基础的部分,路由信息包括一个ID、一个URI、一组断言工厂、一组Filter组成。
断言 (predicates):断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。如果断言为真,则说明请求的URL和配置的路由匹配。
过滤器(Filter):Spring Cloud Gateway中的filter分为Gateway Filter和Global Filter。Filter可以对请求和响应进行处理。Filter只有pre和post两种。

依赖

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

路由

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.178.129:8848
    gateway:
      routes:
        - id: shop-user
          uri: lb://shop-user    # nacos 中注册的服务名
          predicates:
            - Path=/config/test
 
        - id: shop-user2
          uri: 192.168.178.128:111   #ip
          predicates:
            - Path=/config/test2

断言

基本的断言工厂

|------------|-------------------|---------------------------------------------------------------------------------------------------------|
| Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
| After | 是某个时间点后的请求 | - After=2012-01-20T17:42:47.789-07:00[America/Denver] |
| Before | 是某个时间点之前的请求 | - Before=2012-01-20T17:42:47.789+07:00[Asia/Shanghai |
| Between | 是某两个时间点之前的请求 | - Between=2012-01-20T17:42:47.789-07:00[America/Denver] ,2012-01-20T17:42:47.789+07:00[Asia/Shanghai |
| Cookie | 请求必须包含某些cookie | - Cookie=chocolate,ch.p |
| Header | 请求必须包含某些header | - Header=X-Request-ld, \d+ |
| Host | 请求必须是访问某个host(域名) | - Host=.something.org,.anotherhost.org |
| Method | 请求凡是必须是指定方式 | - Method=GEt,POST |
| Query | 请求参数必须包含指定参数 | - Query=name,kack或者- Query=name |
| RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |

官网: 路由谓词工厂

自定义断言

步骤:

  1. 开头任意取名,但是必须以RoutePredicateFactory后缀结尾

  2. 继承AbstractRoutePredicateFactory抽象类仿照这个源码写,这个源码的路由规则是根据时间来定义的

    public class AfterRoutePredicateFactory extends AbstractRoutePredicateFactory<Config> {
    public static final String DATETIME_KEY = "datetime";

     public AfterRoutePredicateFactory() {
         super(Config.class);
     }
     
     //支持shortcut 如果不重写 用简便形式写就会报错
     public List<String> shortcutFieldOrder() {
         return Collections.singletonList("datetime");
     }
    
     //ServerWebExchange这个类似与request,这个是判断是否让请求通过的规则
     public Predicate<ServerWebExchange> apply(final Config config) {
         return new GatewayPredicate() {
             public boolean test(ServerWebExchange serverWebExchange) {
                 ZonedDateTime now = ZonedDateTime.now();
                 return now.isAfter(config.getDatetime());
             }
    
             public Object getConfig() {
                 return config;
             }
    
             public String toString() {
                 return String.format("After: %s", config.getDatetime());
             }
         };
     }
     //路由规则
     public static class Config {
         private @NotNull ZonedDateTime datetime;
    
         public Config() {
         }
    
         public ZonedDateTime getDatetime() {
             return this.datetime;
         }
    
         public void setDatetime(ZonedDateTime datetime) {
             this.datetime = datetime;
         }
     }
    

    }

过滤器

路由过滤器

路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器仅适用于特定的路由。

过滤器工厂

|------------------------|------------------|------------------------------------------|
| AddRequestHeader | 给当前请求添加一个请求头 | - AddRequestHeader=X-Request-red, blue |
| RemoveRequestHeader | 移除请求头 | - RemoveRequestHeader=X-Request-Foo |
| SetRequestHeader | 标记请求头 | - SetRequestHeader=X-Request-Red, Blue |
| AddRequestParameter | 添加请求参数 | - AddRequestParameter=red, blue |
| RemoveRequestParameter | 删除请求参数 | - RemoveRequestParameter=red |
| RemoveResponseHeader | 从响应结果中移除一个响应头 | - RemoveResponseHeader=X-Response-Foo |
| SetResponseHeader | 编辑响应中的响应头 | - SetResponseHeader=X-Response-Red, Blue |
| RemoveResponseHeader | 删除响应中的响应头 | - RemoveResponseHeader=X-Response-Foo |
| PrefixPath | 这将作为所有匹配请求的路径的前缀 | - PrefixPath=/mypath |
| SetPath | 修改访问地址 | - SetPath=/segment |
| RedirectTo | 重定向 | - RedirectTo=302, https://acme.org |

全部:GatewayFilter 工厂

默认过滤器

server:
  port: 10010 # 网关端口
spring:
  application: 
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: 
        - id: user-service 
          # url: http://127.0.0.1:8081 
          url: lb//userservice 
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/usr/** # 这个是按照路径匹配,只要以/user/开头就符合要求
        - id: order-service 
          url: lb//orderservice
          predicates:
            - Path=/order/** 
       default-filters: # 默认过滤器,会对所有的路由请求都生效
         - AddRequestHeader=Truth,luxifa is  following her dream # 添加请求头

自定义路由过滤器

1、新建过滤器名称要以GatewayFilterFactory结尾

2、继承AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>重写其中的方法

@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>
{
    public MyGatewayFilterFactory()
    {
        super(MyGatewayFilterFactory.Config.class);
    }


    @Override
    public GatewayFilter apply(MyGatewayFilterFactory.Config config)
    {
        return new GatewayFilter()
        {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
            {
                ServerHttpRequest request = exchange.getRequest();
                System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:"+config.getStatus());
                if(request.getQueryParams().containsKey("atguigu")){
                    return chain.filter(exchange);
                }else{
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                    return exchange.getResponse().setComplete();
                }
            }
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("status");
    }

    public static class Config
    {
        @Getter@Setter
        private String status;//设定一个状态值/标志位,它等于多少,匹配和才可以访问
    }
}

全局过滤器

创建全局过滤器实现GlobalFilter, Ordered 接口,重写其中的方法

public class MyGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 在此处编写全局过滤器的逻辑
        return chain.filter(exchange);
    }

    /**
     * 数字越小优先级越高
     * @return
     */
    @Override
    public int getOrder()
    {
        return 1;
    }
}

其他

过滤器执行顺序

默认路由过滤器 --》路由过滤器 ---》 全局过滤器

前置后置(?)

前置过滤直接在**return chain.filter(exchange);**前写入前置逻辑

后置过滤器

 @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain, String name, String args) {
        Mono<Void> result = chain.filter(exchange);
        return result.then(Mono.fromRunnable(() -> {
            // 编写后置逻辑
        }));
    }

跨域问题

yaml 解决

spring:
  cloud:
    gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]': # 拦截所有请求
            allowedOrgins:  # 允许哪些网站的跨域请求
              - "http://localhost:8090"
              - "http://www.leyou.com"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求头携带的信息 * 代表允许所有请求头
            allowCredentials: true #是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

配置类解决

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);
 
        return new CorsWebFilter(source);
    }
}
相关推荐
虾球xz37 分钟前
游戏引擎学习第61天
java·学习·游戏引擎
qq_4305839739 分钟前
QT笔记- QTreeView + QFileSystemModel 当前位置的保存与恢复 #选中 #保存当前索引
开发语言·笔记·qt
小王爱吃月亮糖1 小时前
QT-QVariant类应用
开发语言·c++·笔记·qt·visual studio
三万棵雪松1 小时前
3.系统学习-熵与决策树
学习·算法·决策树
红色的山茶花1 小时前
YOLOv9-0.1部分代码阅读笔记-hubconf.py
笔记·深度学习·yolo
无涯学徒19981 小时前
J9学习打卡笔记
笔记·学习
软茸兔1 小时前
笔记:一次oracle 集群日志维护
数据库·笔记·oracle
AI敲代码的手套1 小时前
解读目前AI就业岗位——大语言模型(LLM)应用工程师学习路线、就业前景及岗位全解析
人工智能·学习·语言模型
张铁铁是个小胖子6 小时前
微服务学习
java·学习·微服务
AITIME论道7 小时前
论文解读 | EMNLP2024 一种用于大语言模型版本更新的学习率路径切换训练范式
人工智能·深度学习·学习·机器学习·语言模型