【SpringCloud】SpringCloud Gateway详解

本文介绍了SpringCloudGateway作为微服务网关的功能和工作原理,比较了不同类型的网关,如Gateway的响应式编程与Zuul的阻塞式编程。详细阐述了如何搭建Gateway网关,包括添加依赖和配置路由。同时,讲解了路由断言工厂(RoutePredicateFactory)的各种断言策略,以及路由过滤器和全局过滤器的用法,如添加请求头和身份验证。最后,提到了Gateway如何解决跨域问题,通过配置CORS来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

微服务分为多个服务,有很多服务是内部人员要用的,但是现在谁都可以访问到,那我们该怎么办呢?

Spring Cloud最新面试题
Spring Cloud Nacos详解之注册中心
Spring Cloud Nacos详解之配置中心
Spring Cloud Nacos详解之集群配置
Spring Cloud Eureka详解
Spring Cloud Frign详解
Spring Cloud Ribbon详解
Spring Cloud Hystrix详解

SpringCloud Gatewy网关

一.网关功能和工作原理

在这里插入图片描述

二.网关的类型

  • Gateway
    响应式编程,具有更好的性能。

  • Zuul
    阻塞式编程。

三.搭建网关

1.创建一个新的服务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.添加网关依赖和nacos服务发现依赖

		<!--nacos服务注册发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        
        <!--网关gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

3.编写yml配置文件

server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
       - id: order-service  # 订单服务
         uri: lb://orderservice
         predicates:
           - Path=/order/**

四.路由断言工厂(Route Predicate Factory)

官网示例

属性描述示例
After是某个时间点之后的请求-After=2023-01-01T17:42:47.789-07:00[America/Denver]
(必须在2023年1月1日17点42分47秒之后发的请求才能通过,根据美国丹佛[America/Denver]的时间算)
Before是某个时间点之前的请求-Before=2022-02-22T22:22:22.433+8:00[Asia/Shanghai]
(必须在2022年2月22日22时22分22秒之前发的请求才能通过,根据[Asia/Shanghai]上海时间算)
Between是某两个时间点之前的请求-Between=时间[时区],时间[时区]
Cookie请求必须包含某些cookie- Cookie=ikun, rap
Header请求必须包含某些header- Header=X-Request-Id,\d+
Host请求必须是访问某个host(域名)- Host=**.kunkun,**com.cn
Method请求方式必须是指定方式-Method=GETPOST
Path请求路径必须符合指定规则-path=user/**
Query请求参数必须包含指定参数Query=ikun
RemoteAddr请求者的ip必须是指定范围- RemoteAddr=192.168.1.1/24
Weight权重处理

五.路由过滤器(属于GatewayFilter)

对进入网关的请求和微服务返回的响应做处理。比如:添加请求头。
官网示例

1.配置网关服务yml文件

路由过滤器:对当前路由生效。
server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
		  filters:
        	- AddRequestHeader=Ikun,ji ni tai mei!  # 添加请求头,针对某个服务生效。

2.在添加请求头的服务编写代码

	在用户服务的controller里面写
	/**
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value = "Ikun", required = false) String ikun) {
        System.out.println("Ikun最喜欢的歌是什么:" + ikun);
        return userService.queryById(id);
    }

然后访问 localhost:10086/user/1,控制台就会打印 ikun 的值。
在这里插入图片描述

六.DefaultFilter过滤器(属于GatewayFilter)

DefaultFilter:对所有路由都生效。
server:
  port: 10086  #端口号
spring:
  application:
    name: gateway #服务名称
  cloud:
    gateway:
      routes: 
        - id: user-service # 路由id,必须唯一。  用户服务
          uri: lb://userservice # 路由的目标地址,lb是负载均衡。 
          # uri: http://127.0.0.1/user/1   也可以使用这种,但是这种就固定了路由地址,就不能负载均衡了。
          predicates: # 路由断言,判断请求是否符合规则,符合就转发到目的路由。可以配置多个规则
            - Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合。
	   default-filters:
        - AddRequestHeader=Ikun,ji ni tai mei!  #添加请求头,全局生效

七.全局过滤器(GlobalFilter)

对进入网关的请求和微服务返回的响应做处理。和GatewayFilter作用一样

因为GatewayFilter是基于配置实现,处理的逻辑是固定的,GlobalFilter基于代码逻辑实现,更加灵活一些,可以用于验证用户身份等功能。

1.实现GlobalFilter接口

验证身份信息,根据authorization的值是否是ikun
// @Order(-1) 注解方式实现,如果有多个过滤器,越小越早走。
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        // 2.获取参数中的 authorization 参数
        String auth = params.getFirst("authorization");
        // 3.判断参数值是否等于 ikun
        if ("ikun".equals(auth)) {
            // 4.是,放行
            return chain.filter(exchange);
        }
        // 5.否,拦截
        // 5.1.设置状态码,未登录
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 5.2.拦截请求
        return exchange.getResponse().setComplete();
    }

	/**
	* 代码方式实现,实现 Ordered 接口,多个过滤器,返回值越小,越早走。
	**/
    @Override
    public int getOrder() {
        return -1;
    }
}

2.验证身份

(1) 如果authorization 参数不等于ikun或没有都会报错。
在这里插入图片描述

(2) authorization 参数等于 ikun正常访问。
在这里插入图片描述

八.过滤器执行顺序

请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤链(集合)中,排序后依次执行每个过滤器**(DefaultFilter -> 路由过滤器 -> GlobalFilter)**。

1.为什么不是同一个过滤器可以放在一个过滤链中呢?由下面可得这三个过滤器本质上都是GatewayFilter

DefaultFilter 和 路由过滤器的实现都是 AddRequestHeaderGatewayFilterFactory 类,最后会生成一个真正的过滤器(GatewayFilter)。
在这里插入图片描述

GlobalFilter的实现是通过 GatewayFilterAdapter 适配器类实现了GatewayFilter,然后就可以把GlobalFilter适配成GatewayFilter
在这里插入图片描述

2.路由过滤器和DefaultFilter怎么设置@Order顺序呢?

由spring指定order,按声明顺序1开始递增。

在这里插入图片描述

扩展:

  • org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。
  • org.springframework.cloud.gateway.handler.FilteringlWebHandler#handle()方法会加载全局过滤器与前面的过滤器合并后根据order排序,组织过滤器链。

九.Gateway解决跨域问题

跨域: 浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题。
解决: 采用CORS方案,网关处理跨域采用的同样是CORS方案。(简单来说就是浏览器询问服务端让不让这个请求跨域,如果让会返回结果)。

在yml文件配置以下内容
spring:
  cloud:
	gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题(浏览器去询问服务端的请求就是options)
        corsConfigurations:
          '[/**]':
            allowedOrigins:  # 允许哪些网站的跨域请求
              -"http://localhost:8888"
              -"http://www.ikun.com"
            allowedMethods: # 允许的跨域ajax的请求方式          
              -"GET"
			  -"POST"
		      -"DELETE"
			  -"PUT"
			  -"OPTIONS"
			allowedHeaders: "*" # 允许请求头跨域
			allowCredentials: true # 是否允许携带cookie
			maxAge: 360000 # 这次跨域检测的有效期
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱穿背带裤的馫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值