SpringCloud之Gateway

发布时间 2023-09-25 19:35:36作者: 九极致之术

1. 什么是Gateway

Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。

优点:

l 性能强劲:是第一代网关Zuul的1.6倍

l 功能强大:内置了很多实用的功能,例如转发、监控、限流等

l 设计优雅,容易扩展

缺点:

l 其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高

l 不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行

l 需要Spring Boot 2.0及以上的版本,才支持

 

2. Gateway--服务网关

大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。

 

这样的架构,会存在着诸多的问题:

l 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性

l 认证复杂,每个服务都需要独立认证。

l 存在跨域请求,在一定场景下处理相对复杂。

上面的这些问题可以借助API网关来解决。

所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服 务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。 添加上API网关之后,系统的架构图变成了如下所示:

 

 3. 使用Gateway

 单独创建GatewayMaven工程

【注:Gateway本质来说也是一个子服务模块】

【注:Gateway是和xw-serve、xw-comm服务模块同级】

在其pom文件加入依赖:

<!--加入gateway的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

【注:还有在工程中创建启动类】

 

 3.1 进行Gateway配置

创建application.yml配置文件在其中配置子服务模块信息:

【注:可以是yml后缀的配置文件,因为用properties后缀的配置文件比较麻烦】

 

3.1.1 复杂配置设置:

server:
  port: 8851
spring:
  application:
    name: gateway    #服务名称
  # 配置子服务模块api
  #【注:可以配置多个子服务模块】
  cloud:
    gateway:
      routes:
        - id: order   # 路由的唯一标识,只要不重复都可以,如果不写默认会通过UUID产生,一般写成被路由的服务名称
          uri: http://localhost:8082/  # 被路由的地址(去向子服务模块的地址+端口)
          order: 1                     #表示优先级  数字越小优先级越高
          predicates:                  #断言: 执行路由的判断条件
            - Path=/product_serv/**
          filters:                     # 过滤器: 可以在请求前或请求后作一些手脚
            - StripPrefix=1

 

3.1.2 简单配置设置及Gateway前后端跨域:

server:
  port: 8851
spring:
  application:
    name: gateway
  # 配置api
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOriginPatterns: "*"
            allowedHeaders: "*"
            allowedMethods: "*"
            allowCredentials: true
#        default-filters:
#          - DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
      discovery:
        locator:
          enabled: true

 【注:使用Gateway本身不能跟web依赖共存】

【注:使用Gateway只需要其本身配置跨域信息即可,子服务模块不需要配置跨域信息】

【注:一切都以通过Gateway去访问子服务模块】

 访问路径:ip地址:Gateway端口号/子服务模块微服务微服务名称/要访问的子服务路径

 3.1 自定义Gateway全局拦截器

创建com.aaa包下config包下AuthGlobalFilter 配置类:

com -> aaa -> congif -> AuthGlobalFilter

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求头中的token值
        ServerHttpRequest request = exchange.getRequest();
        String token = request.getHeaders().getFirst("token");
        //判断token是否为空
        if (StringUtils.isEmpty(token)){
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
        }else {
            //不为空则校验token,校验通过将token存入Redis中
            try {
                Claims claims = JwtUtils.parseJWT(token);
                return chain.filter(exchange);
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("token非法");
            }
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

【注:此配置文件作为Gateway检测前端每次发起请求是否携带token】

【注:此配置文件后期可根据业务需求进行更改拦截条件】

 

 4. 将heads注入容器获取token

注:【假如有需求需要使用到用户id或用户信息从token中解析取值】

该如何?

通过注入HTTPServletRequest 来获取request 对象:

@Resource
private HttpServletRequest request;
String token = request.getHeader("token");//从请求头中获取token
Claims claims = JwtUtils.parseJWT(token);//解析token
    // 将这个map转化为对象
    List token1 = (List) claims.get("token");
    Map o = (Map) token1.get(0);
    user user = BeanUtil.fillBeanWithMap(o, new user(), false);//将集合转换对象
    int id = user.getId();//获取到了用户id

 

   


 

以上便是SpringCloud之Gateway中的内容,如有漏缺请在下方留言告知,我会及时补充