springboot使用Gateway做网关并且配置全局拦截器

一、为什么要用网关

统一入口:

  • 作用:作为所有客户端请求的统一入口。
  • 说明:所有客户端请求都通过网关进行路由,网关负责将请求转发到后端的微服务

路由转发:

  • 作用:根据请求的URL、方法等信息将请求路由到不同的微服务。
  • 说明:网关可以根据配置的路由规则,将请求转发到正确的微服务,实现请求的路由和负载均衡。

负载均衡:

  • 作用:实现请求的负载均衡。
  • 说明:网关可以集成负载均衡组件(如Ribbon),根据负载均衡策略将请求分发到不同的服务实例,提高系统的可用性和扩展性。

服务发现:

  • 作用:与服务注册中心集成,实现服务的自动发现。
  • 说明:网关可以与Eureka等服务注册中心集成,动态获取服务实例的信息,实现服务的自动发现和路由。

认证与授权:

  • 作用:提供统一的安全认证和授权机制。
  • 说明:网关可以集成认证和授权组件(如OAuth2、JWT),对所有进入的请求进行安全检查,确保只有合法的请求才能访问后端服务。

跨域资源共享(CORS):

  • 作用:处理跨域请求。
  • 说明:网关可以处理跨域请求,允许来自不同域的客户端访问后端服务,解决了浏览器的同源策略限制。

二、Gateway简单使用

第一步:引入Gateway的maven依赖到pom.xml文件

        <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>

第二步:编写配置文件application.yml文件,如下所示:

server:port: 10086   # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848    # nacos 地址gateway:routes:         # 网关路由配置- id: provider      # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:8081   # 路由的目标地址 (直接写死地址的方式,不推荐)uri: lb://provider    # 路由的目标地址 lb是负载均衡,后面跟服务名称(推荐)predicates:       # 路由断言,判断请求是否符合路由规则的条件- Path=/provider/**      # 按照路径匹配,以/user/开头的请求就符合要求

第三步:启动测试

当然要注意的是我们需要开启另一个服务provider服务,并且这个服务需要配置方法前缀/provider,当我们通过网关访问的时候就可以直接的访问到provider服务了。

三、Gateway断言工厂

路由断言主要用来判断路由的规则。

配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理。

例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理。

像这样的断言工厂在SpringCloudGateway还有十几个:

当然这个地方可能给的不是很全所以我贴出官网地址:大家需要的可以去看官网:Spring Cloud Gatewayicon-default.png?t=N7T8https://docs.spring.io/spring-cloud-gateway/docs/3.1.4-SNAPSHOT/reference/html/#gateway-request-predicates-factories

简单示例,下面我配置一个在访问之前需要到一定的时间才可以访问,并且看一下效果

server:port: 10086   # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848    # nacos 地址gateway:routes:         # 网关路由配置- id: provider      # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:8081   # 路由的目标地址 (直接写死地址的方式,不推荐)uri: lb://provider    # 路由的目标地址 lb是负载均衡,后面跟服务名称(推荐)predicates:       # 路由断言,判断请求是否符合路由规则的条件- Path=/provider/**      # 按照路径匹配,以/user/开头的请求就符合要求- After=2031-01-20T17:42:47.789-07:00[America/Denver]

因为我配置了需要在2031年1月20号后才可以访问明显现在是2024年不可以访问到,所以会报错404。

四、Gateway路由过滤器

客户端请求先找到路由,路由匹配时经过过滤器层层筛选,最终访问到微服务。

当然微服务的请求反悔时,也会经过过滤器的筛选,只不过我们一般只对请求过滤,而不会对响应过滤。

SpringCloudGateWay目前已经提供了34种不同的过滤器工厂。感兴趣的大家也可以去上面给出的官网地址查看。

下面我在路由过滤器中添加一个请求头,并且需要在provider请求中加入一个参数去拿到请求头中的参数

server:port: 10086   # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848    # nacos 地址gateway:routes:         # 网关路由配置- id: provider      # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:8081   # 路由的目标地址 (直接写死地址的方式,不推荐)uri: lb://provider    # 路由的目标地址 lb是负载均衡,后面跟服务名称(推荐)predicates:       # 路由断言,判断请求是否符合路由规则的条件- Path=/provider/**      # 按照路径匹配,以/user/开头的请求就符合要求filters: # 过滤器配置- AddRequestHeader=token, test # 添加请求头

provider请求变为,需要拿到请求头中的信息

    @GetMapping("/provider/t")public String t(@RequestHeader(value = "token",required = false)String token){return "恭喜您测试成功啦!"+token;}

测试

当然这是局部配置我们也可以针对所有的路由进行全局配置(但是这个配置是需要和路由s是同级的),如下所示:

server:port: 10086   # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848    # nacos 地址gateway:routes:         # 网关路由配置- id: provider      # 路由id,自定义,只要唯一即可# uri: http://127.0.0.1:8081   # 路由的目标地址 (直接写死地址的方式,不推荐)uri: lb://provider    # 路由的目标地址 lb是负载均衡,后面跟服务名称(推荐)predicates:       # 路由断言,判断请求是否符合路由规则的条件- Path=/provider/**      # 按照路径匹配,以/user/开头的请求就符合要求default-filters: # 默认过滤器配置- AddRequestHeader=token, test  # 添加请求头

五、Gateway全局过滤器

上面的gateway路由器可以配置全局的,为什么还需要有一个全局过滤器呢,因为上面的过滤器都是只可以针对与一些逻辑的拦截,但是不可以涉及到一些业务的处理,所以就有这个全局过滤器可以通过编写代码的方式来编写业务逻辑进行对用户访问的鉴权放行等等。

package com.example.demo.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.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
public class GateWayFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取请求参数//1.这里的request并不是servlet中的request//2.返回值是一个多键的map集合、也就是说这个map集合的键可以重复MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();// 2.获取userName参数String userName = params.getFirst("userName");// 3.校验if ("root".equals(userName)) {// 放行return chain.filter(exchange);}// 4.拦截// 4.1.禁止访问,设置状态码exchange.getResponse().setStatusCode(HttpStatus.valueOf(500));// 4.2.结束处理return exchange.getResponse().setComplete();}//过滤器优先级,数字越小优先级越高@Overridepublic int getOrder() {return -1;}
}

测试:

我们先正常的访问之前的请求,会发现无法使用此页面也就是被拒绝访问了

当我们加上一个参数后把userName=root加上之后就可以正确的访问到请求了

过滤器链执行顺序

SpringCloudGateWay中,有三种过滤器:

  • 默认过滤器default-filters

  • 只对具体某个路由生效的局部过滤器filters

  • 使用java代码编写的全局过滤器GlobalFilter

过滤器最终都会转化成GlobalFilter(使用的是适配器模式)所以我们就可以把这三种过滤器看成一个整体而顺序也入下图显示的一致。

由上图知过滤器的执行顺序为:默认过滤器 → 当前路由过滤器 → 全局过滤器。

六、Gateway跨域请求配置

1.跨域请求定义

跨域:请求位置和被请求位置不同源就会发生跨域。

这里的不同源包括两个点:

  • 域名不同:www.baidu.com 和 www.taobao.com。(IP不同也是相同道理)

  • 端口不同:127.0.0.1:8080和127.0.0.1:8081。

而浏览器又会禁止请求的发起者与服务端发生跨域AJAX请求。

如果发生了跨域请求,服务器端是能够正常响应的,但是响应的结果会被浏览器拦截。

2.跨域常见解决方案

使用CORS方式。

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

3.跨域请求解决方案

方式一:配置application.yml文件:

spring:cloud:gateway:globalcors: # 全局的跨域配置add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题# options请求 就是一种询问服务器是否浏览器可以跨域的请求# 如果每次跨域都有询问服务器是否浏览器可以跨域对性能也是损耗# 可以配置本次跨域检测的有效期maxAge# 在maxAge设置的时间范围内,不去询问,统统允许跨域corsConfigurations:'[/**]':allowedOrigins:   # 允许哪些网站的跨域请求 - "http://localhost:8090"allowedMethods:   # 允许的跨域ajax的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*"  # 允许在请求中携带的头信息allowCredentials: true # 允许在请求中携带cookiemaxAge: 360000    # 本次跨域检测的有效期(单位毫秒)# 有效期内,跨域请求不会一直发option请求去增大服务器压力

方式二:使用编码方式定义配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;@Configuration
public class CorsConfig {private static final String MAX_AGE = "18000L";@Beanpublic WebFilter corsFilter() {return (ServerWebExchange ctx, WebFilterChain chain) -> {ServerHttpRequest request = ctx.getRequest();// 使用SpringMvc自带的跨域检测工具类判断当前请求是否跨域if (!CorsUtils.isCorsRequest(request)) {return chain.filter(ctx);}HttpHeaders requestHeaders = request.getHeaders();                                  // 获取请求头ServerHttpResponse response = ctx.getResponse();                                    // 获取响应对象HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();          // 获取请求方式对象HttpHeaders headers = response.getHeaders();                                        // 获取响应头headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());   // 把请求头中的请求源(协议+ip+端口)添加到响应头中(相当于yml中的allowedOrigins)headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());if (requestMethod != null) {headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());    // 允许被响应的方法(GET/POST等,相当于yml中的allowedMethods)}headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");          // 允许在请求中携带cookie(相当于yml中的allowCredentials)headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");                // 允许在请求中携带的头信息(相当于yml中的allowedHeaders)headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);                           // 本次跨域检测的有效期(单位毫秒,相当于yml中的maxAge)if (request.getMethod() == HttpMethod.OPTIONS) {                                    // 直接给option请求反回结果response.setStatusCode(HttpStatus.OK);return Mono.empty();}return chain.filter(ctx);                                                           // 不是option请求则放行};}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3269531.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp中出现图片过小会与盒子偏离

结论&#xff1a;在image的父盒子中加上display: flex&#xff0c;原因不清楚 出问题的代码和图片如下&#xff1a; <template><view style" background-color: greenyellow; height: 10rpx;width: 10rpx;"><image :src"imgSrc.seatnull" …

《破解验证码:用Requests和Selenium实现模拟登录的终极指南》

两种模拟登录方式(图形验证码) 超级鹰 打码平台&#xff0c;用于识别验证码 requests模拟登录 from chaojiying import Chaojiying_Client import requests from requests import Session from lxml import etree #获取图片信息 def get_pic_info(img_name):chaojiying Ch…

全周期项目管理工具大公开:2024年10大热门选择

本文将分享10款优质全生命周期项目管理系统&#xff1a;PingCode、Worktile、Teambition、禅道、Tapd、Basecamp、ClickUp、ProofHub、Microsoft Project、Asana。 在项目管理领域&#xff0c;找到一个能够覆盖项目全生命周期的管理工具是许多团队面临的常见挑战。这种工具不仅…

【C++】循环结构-while语句

while 语句的语法格式&#xff1a; while (循环条件) {在满足循环条件下执行的操作} 注意要留有跳出循环的方式&#xff0c;避免死循环 1、不写 whlie (1)&#xff0c;写具体的循环条件 2、写while(1)&#xff0c;用 break 跳出循环 下面是一个实例 #include<iostream…

Vue3二次封装axios

官网: https://www.axios-http.cn/docs/interceptors steps1: 安装 npm install axios -ssteps2: /src/api/request.js 文件 >>> 拦截器 import axios from axios // 如果没用element-plus就不引入 import { ElMessage } from element-plusconst service axios.cre…

身份认证(session + token)

web 开发模式 服务端渲染 前后端分离 如何选择 前后端身份验证 session 原理 什么是 cookie cookie 安全性 提高cookie 安全性 配置 session 中间件 注意 只会清除当前用户的 session JWT 认证机制 express 中使用 JWT JWT 字符串 还原为 JSON 对象 一般 约定 api 开头的都…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十八章 中断下文之tasklet

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

简过网:大学生考公,一定要先好好看看这篇文章!

大家好&#xff0c;我是简过网&#xff0c;今天这篇文章我们来聊聊关于大学生考公的那些事儿&#xff0c;希望能给大学生们一点点的帮助&#xff01; 首先&#xff0c;可能有朋友会问了&#xff0c;大学生一般从什么时候开始备考公务员呢&#xff0c;在这里小编建议大家从大三…

electron调试

electron 调试 electron 的调试分两步&#xff0c;界面的调试&#xff0c;和主进程的调试。 界面调试类似浏览器F12&#xff0c;可是调试不到主进程。 主进程调试有vscode、命令行提示和外部调试器调试。 本篇记录的练习是vscode调试。命令行和外部调试器的方式可以参考官网&a…

数据中心同步指南 : 数据中心架构师和其他网络专家需要了解有关 5G 同步的知识

随着 5G 的推出&#xff0c;电信基础设施的设计方式正在发生巨大变化。由于网络运营商希望创建更开放的网络基础设施生态系统&#xff0c;部分基础设施&#xff08;如基带处理&#xff09;被虚拟化并移至电信数据中心。影响数据中心架构的另一个与 5G 相关的趋势是移动边缘计算…

shell脚本相关应用

编写一个简单的脚本&#xff0c;以及运行脚本 301 vim helloworld.sh #!/bin/bash echo "hello world!" ls -lh /etc/ 执行的方式如下&#xff1a; 302 bash helloworld.sh 303 sh helloworld.sh 304 chmod x helloworld.sh 305 ./helloworld.sh…

vue中scoped详解以及样式穿透>>>、/deep/、::v-deep

1、scoped scoped属性用于限制样式仅应用于当前组件。当一个style标签拥有scoped属性时&#xff0c;它的CSS样式就只能作用于当前的组件&#xff0c;通过该属性&#xff0c;可以使得组件之间的样式不互相污染。 原理&#xff1a;当样式中加了scoped属性时候&#xff0c;编译的…

QT自定义无边框窗口(可移动控制和窗口大小调整)

QT是一个功能强大的跨平台开发框架&#xff0c;它提供了丰富的界面设计工具和组件。在界面开发中&#xff0c;QT窗口自带的标题栏无法满足我们的需求。我们就需要自定义无边框窗口&#xff0c;包括自定义标题栏和窗口大小调整功能。本文将介绍如何在QT中实现这些功能。 一、简…

【五】MySql8基于m2芯片arm架构Ubuntu24虚拟机安装

文章目录 1. 更新系统包列表2. 安装 MySQL APT Repository3. 更新系统包列表4. 安装 MySQL Server5. 运行安全安装脚本6. 验证 MySQL 安装7. 配置远程连接7.1 首先要确认 MySQL 配置允许远程连接&#xff1a;7.2 重启 MySQL 服务&#xff1a;7.3 检查 MySQL 用户权限&#xff1…

**往届快至会后2个月完成检索,刊后1个月完成检索,第四届电子信息工程与计算机科学国际会议(EIECS 2024)火热征稿中!

2024年第四届电子信息工程与计算机科学国际会议(EIECS 2024) 2024 4th International Conference on Electronic Information Engineering and Computer Science 中国延吉 | 2024年9月27-29日 二轮截稿日期&#xff1a;2024年8月9日 收录检索&#xff1a;EI Compendex, Sc…

qt初入门9:qt记录日志的方式,日志库了解练习(qInstallMessageHandler,qslog, log4qt)

项目中用到qt&#xff0c;考虑有需要用到去记录日志&#xff0c;结合网络&#xff0c;整理一下&#xff0c;做记录。 简单了解后&#xff0c;qt实现日志模块思考&#xff1a; 1&#xff1a;借助qt自带的qInstallMessageHandler重定向到需要的目的地。 2&#xff1a;自己封装一…

pageoffice常见问题处理

pageoffice是由卓正软件公司开发的一套在线编辑office的插件。要在自己的系统中使用&#xff0c;需要进行集成开发&#xff0c;把pageoffice嵌入到自己的系统中。以下记录在使用过程中常见的问题和解决方法&#xff1a; 1.PageOffice对客户端的要求 office 不能是家庭版&#x…

2. 卷积神经网络无法绕开的神——LeNet

卷积神经网络无法绕开的大神——LeNet 1. 基本架构2. LeNet 53. LeNet 5 代码 1. 基本架构 特征抽取模块可学习的分类器模块 2. LeNet 5 LeNet 5: 5 表示的是5个核心层&#xff0c;2个卷积层&#xff0c;3个全连接层.核心权重层&#xff1a;卷积层、全连接层、循环层&#xff…

093、Python操作Excel生成统计图表

在Excel里做统计表是我们经常会做的一件事情。我们也可以通过编程的方式操作Excel生成统计图表。 下面是官方的一个很有参考价值的案例&#xff1a; from openpyxl import Workbook from openpyxl.chart import BarChart, Reference from copy import deepcopywb Workbook(w…

生活实用英语口语“拆迁”用英文怎么说?柯桥成人学英语到蓝天广场

● 1. “拆迁”英语怎么说&#xff1f; ● 01. 其实国外也有拆迁 但国外的拆迁&#xff0c;只管拆 不管安置&#xff0c;你爱去哪去哪 英文可以说 housing removal 02. 但我们中国的“拆迁” 既管“拆”也管“迁” &#xff08;还是中国人幸福~&#xff09; 英文可以说 housin…