Gateway--服务网关

本文深入探讨了Spring Cloud Gateway,包括创建API网关、配置Nacos服务发现、简化网关设置以及核心架构。重点介绍了路由、断言和过滤器的使用,如动态路由、基于时间、地址、Cookie、Header等的断言工厂,以及自定义断言和过滤器的实现。此外,还展示了全局过滤器在权限校验中的应用。
摘要由CSDN通过智能技术生成
      所谓的 API 网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服 务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控(黑白名单)、路 由转发等等。
1. 创建一个 api-gateway 的工程并加入依赖
 

2. 创建启动类
3.书写application.yml配置
4. 启动项目 , 并通过网关去访问微服务

5. 增强版网关
       现在在配置文件中写死了转发路径的地址, 前面我们已经分析过地址写死带来的问题, 接下来我
们从注册中心获取此地址。
1)加入 nacos 依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2)在主启动类上加入服务发现的注解 ----   @EnableDiscoveryClient
3)修改 application.yml 的配置文件

6. 简写版网关
1) 去掉关于路由的配置,修改配置为

2) 启动项目,并通过网关去访问微服务
按照网关地址/微服务/接口的格式去访问,就可以得到成功响应

 7.Gateway 核心架构

1)基本概念

路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面
的几个信息:
id:是路由标识符,区别于其他 Route。
uri:是路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
order:是用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。
predicate:是断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
filter:是过滤器用于修改请求和响应信息。
2) 执行流程

8.断言

  Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。  
断言就是说: 在什么条件下,才能进行路由转发。
基于 Datetime 类型的断言工厂
  此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
- After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
基于远程地址的断言工厂 RemoteAddrRoutePredicateFactory:  
  接收一个 IP 地址段,判断请求主机地址是否在地址段中  
- RemoteAddr=192.168.1.1/24
基于 Cookie 的断言工厂
  CookieRoutePredicateFactory:接收两个参数, cookie 名字和一个正则表达式。 判断请求
cookie 是否具有给定名称且值与正则表达式匹配。
- Cookie=chocolate, ch.
基于 Header 的断言工厂      
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求 Header 是否
具有给定名称且值与正则表达式匹配。 key value
- Header=X-Request-Id, \d+
基于 Host 的断言工厂 HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的  Host 是否满足匹配规则。
- Host=**.testhost.org
基于 Method 请求方法的断言工厂
MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。  
- Method=GET
  基于 Path 请求路径的断言工厂
PathRoutePredicateFactory:接收一个参数,判断请求的 URI 部分是否满足路径规则。
- Path=/foo/{segment} 基于 Query 请求参数的断言工厂
QueryRoutePredicateFactory :接收两个参数,请求 param 和正则表达式, 判断请求参数是否具有给定名称且值与正则表达式匹配。  
- Query=baz, ba.
基于路由权重的断言工厂
WeightRoutePredicateFactory:接收一个[组名 , 权重], 然后对于同一个组内的路由按照权重转发
routes:
- id: weight_route1 uri: host1 predicates:
- Path=/product/**
- Weight=group3, 1
- id: weight_route2 uri: host2 predicates:
- Path=/product/**
- Weight= group3, 9    

验证断言:

 8. 自定义路由断言工厂

1)在配置文件中,添加一个 Age 的断言配置

 2)自定义一个断言工厂, 实现断言方法

package com.yjq.apigateway.predicate;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

//泛型为自定义的一个配置类,该配置类用来存放配置文件中的值
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
    public AgeRoutePredicateFactory() {
        super(Config.class);
    }

    public List<String> shortcutFieldOrder() {
        return Arrays.asList("minAge", "maxAge");
    }

    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {
            public boolean test(ServerWebExchange serverWebExchange) {
                ServerHttpRequest request = serverWebExchange.getRequest();
                String age = request.getQueryParams().getFirst("age");

                if (StringUtils.isEmpty(age)){
                    return false;
                }else {
                    Integer a=Integer.parseInt(age);
                    if (a>=config.getMinAge()&&a<=config.getMaxAge()){
                        return true;
                    }else {
                        return false;
                    }
                }
            }
        };
    }

    @Validated
    public static class Config {
        @NotNull
        private Integer minAge;
        @NotNull
        private Integer maxAge;

        public Integer getMinAge() {
            return minAge;
        }

        public void setMinAge(Integer minAge) {
            this.minAge = minAge;
        }

        public Integer getMaxAge() {
            return maxAge;
        }

        public void setMaxAge(Integer maxAge) {
            this.maxAge = maxAge;
        }
    }
}

3)启动测试

 

 9.过滤器

三个知识点 :
1 作用 : 过滤器就是在请求的传递过程中 , 对请求和响应做一些手脚
2 生命周期: Pre Post (在 Gateway , Filter 的生命周期只有两个: “pre” “post”
PRE : 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选
择请求的微服务、记录调试信息等。
POST :这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP
Header 、收集统计信息和指标、将响应从微服务发送给客户端等。
3 分类 : 局部过滤器 ( 作用在某一个路由上 ) 全局过滤器 ( 作用全部路由上 )
1) 局部过滤器---内置局部过滤器
在配置文件中 , 添加 过滤器配置

测试:

截取

 修改状态:

  

2)全局过滤器----自定义全局过滤器

全局过滤器作用于所有路由 , 无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。
自定义一个 GlobalFilter ,去校验所有请求的请求参数中是否包含 “token” ,如何不包含请求参数“token” 则不转发路由,否则执行正常的逻辑
自定义全局过滤器的要求:必须实现 GlobalFilter,Order 接口:

package com.yjq.apigateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class LoginFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request= exchange.getRequest();

        String token=request.getHeaders().getFirst("token");
        if (!StringUtils.isEmpty(token)){
            if ("admin".equals(token)){
                return chain.filter(exchange);
            }
        }
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }

// 优先级 值越小优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}
使用postman测试:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值