从零搭建微服务项目Base(第7章——微服务网关模块基础实现)

前言:

在前面6章的学习中已经完成了服务间的调用实现,即各微服务通过nacos或eureka服务器完成服务的注册,并从nacos中拉取配置实现热更新。当某个服务接口需要调用其他服务时,通过feign定义接口,并通过注解配置服务名称,在nacos或eureka服务器中找到对应服务端口完成调用。

但实际应用中,用户不可能直接访问这些服务端口,因为每个服务对应一个端口,当服务拆分很多时,会有大量端口,前端开发人员不可能针对每次调用看文档找对应端口,因此引入网关模块,用户只需要访问网关模块端口,网关模块自动转发,且网关模块也能实现服务聚合、负载均衡、用户鉴权等功能。为此,本章实现基础的网关模块,包括网关服务模块创建、路由断言、过滤器配置

本章代码基于第6章项目,前置源码可在第6章博客下载,博客链接如下:

从零搭建微服务项目(第6章——Feign性能优化以及模块抽取)-CSDN博客https://blog.csdn.net/wlf2030/article/details/145649565简要介绍前置项目流程:order-service以及user-service两服务分别连接order-db以及user-db两数据库,order-db中仅有user-id,user-info存在user-db中,为提供完整order-info,order-service通过nacos发现user-service服务地址并使用Feign调用服务端口拿取user-info结合从order-db中拿取的信息返回给前端。同时项目自定义日志输出。

本项目源码链接如下:

wlf728050719/SpringCloudBase7https://github.com/wlf728050719/SpringCloudBase7以及本专栏会持续更新微服务项目,每一章的项目都会基于前一章项目进行功能的完善,欢迎小伙伴们关注!同时如果只是对单章感兴趣也不用从头看,只需下载前一章项目即可,每一章都会有前置项目准备部分,跟着操作就能实现上一章的最终效果,当然如果是一直跟着做可以直接跳过这一部分。


一、前置项目准备

1.从github下载前一章的项目解压,重命名为Base7打开。

2.重命名模块为Base7.

3.父工程pom.xml中<name>改成Base7。

4.选择环境为dev,并重新加载maven

5.启动nacos(安装和启动见第三章)

6.进入nacos网页 配置管理->配置列表确认有这些yaml文件。

(如果不是一直跟着专栏做自然是没有的,需要看第四章的环境隔离和配置拉取,记得把父工程pom文件中namespace的值与nacos中命名空间生成的保持一致)

7.配置数据源,更换两服务的resources下yml文件的数据库配置,数据库sql见第一章数据库准备部分。

.测试数据库连接 属性->点击数据源->测试连接->输入用户名密码

8.添加运行配置 服务->加号->运行配置类型->spring boot。

启动服务,测试接口。

能够在日志文件中看到最新的日志记录。


二、网关服务模块创建以及配置

1.新建SpringBoot模块,配置如下。

2.不添加任何依赖

3.删除不必要文件和目录,最终结构如下。

4.将gateway模块的pom文件替换为下面内容。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.bit</groupId><artifactId>Base7</artifactId><version>1.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><artifactId>gateway</artifactId><version>0.0.1-SNAPSHOT</version><name>gateway</name><description>gateway</description><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>2.2.5.RELEASE</version></dependency><!-- nacos客户端依赖包 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

4.修改父文件pom,即将gateway模块声明为父模块的子模块,重新加载maven模块。

5.重新加载maven文件后,查看maven结构是否如下,如果不是见本专栏第0章第三节部分有对应解决方法。

6.在父文件pom中为gateway在各配置环境下设置端口。

7.在gateway的application中排除默认数据源,否则需要在application中配置数据源,后续动态路由时需要使用数据库时再恢复。

8.为gateway在resources目录下创建application.yml配置文件,内容如下:

server:port: @gateway.port@
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848discovery:namespace: @namespace@gateway:routes:- id: user-serviceuri:lb://user-servicepredicates:- Path=/user/**- id: order-serviceuri:lb://order-servicepredicates:- Path=/order/**

9.启动服务

通过在网关端口输入路径即可通过断言调取对应服务的接口。


三、路由断言

目前是通过application.yml配置路由工厂。但使用动态路由需要重写实现路由工厂类,以及使用统一的格式便于规范数据库中路由信息,即使用args+name,为方便后续章节理解,使用args+name替换gateway的application.yml,内容如下:

server:port: @gateway.port@
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848discovery:namespace: @namespace@gateway:routes:- id: user-serviceuri:lb://user-servicepredicates:- name: Pathargs:_genkey_0: /user/**- id: order-serviceuri:lb://order-servicepredicates:- name: Pathargs:_genkey_0: /order/**

测试通过


四、路由过滤器

后续鉴权模块需要配合网关的过滤器一起搭配使用才能实现不同角色不同权限访问对应服务/端口,需要手写代码实现 AbstractGatewayFilterFactory,目前先通过yml配置文件为网关添加过滤器方便后续理解。

修改网关模块的yml文件如下:(现在的yml其实就已经很长了,后续必然需要使用代码结合数据库代替配置文件)

server:port: @gateway.port@
spring:application:name: gatewaycloud:nacos:server-addr: localhost:8848discovery:namespace: @namespace@gateway:routes:- id: user-serviceuri:lb://user-servicepredicates:- name: Pathargs:_genkey_0: /user/**filters:- name: AddRequestHeaderargs:name: sourcevalue: request user from gateway- id: order-serviceuri:lb://order-servicepredicates:- name: Pathargs:_genkey_0: /order/**filters:- name: AddRequestHeaderargs:name: sourcevalue: request order from gateway

为了获取请求头内容,对OrderController和UserController进行修改。直接替换成下面内容即可。

package cn.bit.orderservice.controller;import cn.bit.common.pojo.vo.OrderInfoVO;
import cn.bit.common.pojo.vo.R;
import cn.bit.orderservice.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("/test/{id}")public String test(@PathVariable Integer id) {System.out.println(id);return id.toString();}@GetMapping("/info/{id}")public R getOrderInfoById(@PathVariable Integer id, @RequestHeader(value = "source",required = false) String source) {log.debug("debug");log.info("info");log.warn("warning");System.out.println(source);OrderInfoVO orderInfoVO = orderService.getOrderInfoById(id);if (orderInfoVO == null) {return R.failed("订单不存在");}elsereturn R.ok(orderInfoVO);}
}
package cn.bit.userservice.controller;import cn.bit.common.pojo.dto.UserBaseInfoDTO;
import cn.bit.common.pojo.vo.R;
import cn.bit.common.pojo.vo.UserFavorVO;
import cn.bit.userservice.config.PatternProperties;
import cn.bit.userservice.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate PatternProperties patternProperties;@GetMapping("/test/{id}")public String test(@PathVariable Integer id) {System.out.println(id);return id.toString()+" "+LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));}@GetMapping("/favor/{id}")public R getUserFavorById(@PathVariable Integer id) {UserFavorVO vo = userService.getUserFavorById(id);if(vo != null) {return R.ok(vo);}elsereturn R.failed("用户不存在");}@GetMapping("/baseInfo/{id}")public R getUserBaseInfoById(@PathVariable Integer id, @RequestHeader(value = "source",required = false) String source) {System.out.println("get request");System.out.println(source);UserBaseInfoDTO dto = userService.getUserBaseInfoById(id);if(dto != null) {return R.ok(dto);}elsereturn R.failed("用户不存在");}
}

启动服务

先访问user接口即localhost:1233/user/baseInfo/1

能够验证确实添加了请求头

再访问order接口即localhost:1233/order/info/1

发现order-service获取到请求头,user-service为null,因为网关只对访问order-service的request添加了请求头,order-service之后使用feign访问的user-service,自然没有请求头。

为了实现调用朔源可以修改UserClient的接口方法

以及其调用

再次启动服务调用


五、全局过滤器

之前的过滤器为每个路由的过滤器,而全局过滤器无论使用哪条路由均需要使用。配置如下:

在网关模块创建filter包以及AuthorizeFilter类,内容如下:

package cn.bit.gateway.filter;import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();MultiValueMap<String, String> queryParams = request.getQueryParams();String token = queryParams.getFirst("token");if("admin".equals(token)) {return chain.filter(exchange);}exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}
}

重启后发现只有请求参数包含token字段且值为token才能访问对应服务。


六、过滤器执行顺序


最后:

黑马课程关于网关模块讲解还是比较浅显,和企业实际应用有较大出入,后续会研究动态路由实现以及鉴权模块,这两模块比较复杂所以后续更新会慢些。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【异常错误】pycharm debug view变量的时候显示不全,中间会以...显示

异常问题&#xff1a; 这个是在新版的pycharm中出现的&#xff0c;出现的问题&#xff0c;点击view后不全部显示&#xff0c;而是以...折叠显示 在setting中这么设置一下就好了&#xff1a; 解决办法&#xff1a; https://youtrack.jetbrains.com/issue/PY-75568/Large-stri…

2025最新智能优化算法:改进型雪雁算法(Improved Snow Geese Algorithm, ISGA)求解23个经典函数测试集,MATLAB

一、改进型雪雁算法 雪雁算法&#xff08;Snow Geese Algorithm&#xff0c;SGA&#xff09;是2024年提出的一种新型元启发式算法&#xff0c;其灵感来源于雪雁的迁徙行为&#xff0c;特别是它们在迁徙过程中形成的独特“人字形”和“直线”飞行模式。该算法通过模拟雪雁的飞行…

LearnOpenGL——高级OpenGL(下)

教程地址&#xff1a;简介 - LearnOpenGL CN 高级数据 原文链接&#xff1a;高级数据 - LearnOpenGL CN 在OpenGL中&#xff0c;我们长期以来一直依赖缓冲来存储数据。本节将深入探讨一些操作缓冲的高级方法。 OpenGL中的缓冲本质上是一个管理特定内存块的对象&#xff0c;它…

nodejs及搭建

java项目可以运行在tomcat服务器&#xff0c;开始完成前后端完全分离。前端有自己独立的工程。我们需 要把前端独立的工程运行起来。---运行在nodejs服务器下。 1.安装nodejs 检验是否安装过 node --version 2.安装npm java项目需要依赖jar&#xff0c;安装maven。 前端项目…

Jenkins插件管理切换国内源地址

安装Jenkins 插件时&#xff0c;由于访问不了国外的插件地址&#xff0c;会导致基本插件都安装失败。 不用着急&#xff0c;等全部安装失败后&#xff0c;进入系统&#xff0c;修改插件源地址&#xff0c;重启后在安装所需插件。 替换国内插件更新地址 选择&#xff1a;系统…

关于uniApp的面试题及其答案解析

我的血液里流淌着战意&#xff01;力量与智慧指引着我&#xff01; 文章目录 1. 什么是uniApp&#xff1f;2. uniApp与原生小程序开发有什么区别&#xff1f;3. 如何使用uniApp实现条件编译&#xff1f;4. uniApp支持哪些平台&#xff0c;各有什么特点&#xff1f;5. 在uniApp中…

2025年2月9日(数据分析_2)

散点图 from matplotlib import pyplot as plt from matplotlib import font_manager # 字体相关# 字体 font_path = r"C:\Windows\Fonts\msyh.ttc" my_font = font_manager.FontProperties(fname=font_path)x = list(range(31)) x2 = list(range(31, 62)) a3 = [11…

11.编写前端内容|vscode链接Linux|html|css|js(C++)

vscode链接服务器 安装VScode插件 Chinese (Simplified) (简体中⽂) Language Pack for Visual Studio CodeOpen in BrowserRemote SSH 在命令行输入 remote-ssh接着输入 打开配置文件&#xff0c;已经配置好主机 点击远程资源管理器可以找到 右键链接 输入密码 …

【插件】前端生成word 文件

文章目录 1、背景2、方式一&#xff1a;html-docx-js2.1 具体代码2.2 前端生成word文件的样式2.3 总结 3、方式二&#xff1a;pizzip docxtemplater3.1 具体代码3.2 前端生成word文件的样式3.3 总结 4、参考链接 1、背景 在实际开发中&#xff0c;业务需要&#xff0c;需要把数…

大道至简 少字全意 易经的方式看 缓存 mybatis缓存 rendis缓存场景 案例

目录 介绍 mybatis缓存 一级缓存 1.是什么 2.特点 3.场景 mybatis 二级缓存 1.是什么 2.特点 3.配置步骤 注意 一级缓存问题 二级缓存问题 扩展 1.MyBatis集成 Redis 2.直接使用Redis redis 缓存 一、String 字符串 二、Llst 列表 三、Hash 哈希 四、Set…

RocketMQ消息是如何储存的?

前言 之前有写过关于kafka的存储结构的文章。RocketMQ大部分是借鉴了Kafka的设计原理&#xff0c;但是副本集群机制和存储结构有些差异。看完本篇文章可以看看这篇。消息中间件之kafka RocketMQ 的消息存储机制是其高吞吐、高可用和高可靠性的关键。以下将介绍 RocketMQ 消息存…

10分钟上手DeepSeek开发:SpringBoot + Vue2快速构建AI对话系统

作者&#xff1a;后端小肥肠 目录 1. 前言 为什么选择DeepSeek&#xff1f; 本文技术栈 2. 环境准备 2.1. 后端项目初始化 2.2. 前端项目初始化 3. 后端服务开发 3.1. 配置文件 3.2. 核心服务实现 4. 前端服务开发 4.1. 聊天组件ChatWindow.vue开发 5. 效果展示及源…

Coze扣子怎么使用更强大doubao1.5模型

最近&#xff0c;豆包刚刚发布了最新的doubao1.5系列模型&#xff0c;并且加量不加价。 在性能极大进步的情况下&#xff0c;价格还与之前一致。真是业界良心了。 在同样的价格下&#xff0c;肯定要使用性能更强大的模型嘛 于是我准备把所有的智能体和工作流切换到doubao1.5…

UEditorPlus v4.3.0 已知问题修复,表格自适应,全屏编辑优化

UEditor 是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于MIT开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;更…

【核心算法篇十四】《深度解密DeepSeek量子机器学习:VQE算法加速的黑科技与工程实践》

在经典计算机逼近物理极限的今天,量子计算正以指数级加速潜力颠覆传统计算范式。想象一下,一个需要超级计算机运算千年的化学分子模拟问题,用量子计算机可能只需几分钟——这就是DeepSeek团队在VQE(Variational Quantum Eigensolver)算法加速实践中创造的奇迹。根据,VQE作…

Hackthebox- Season7- Titanic 简记 [Easy]

简记 ip重定向到 http://titanic.htb,先添加hosts 收集子域名 wfuzz -c -u http://titanic.htb/ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -H Host:FUZZ.titanic.htb --hl 9 ******************************************************** * Wfu…

【C语言】C语言 哈夫曼编码传输(源码+数据文件)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 C语言 哈夫曼编码传输&#xff08;源码数据文件&am…

撕碎QT面具(6):调节窗口大小后,控件被挤得重叠的解决方法

问题&#xff1a;控件重叠 分析原因&#xff1a;因为设置了最小大小&#xff0c;所以界面中的大小不会随窗口的变化而自动变化。 处理方案&#xff1a;修改mimumSize的宽度与高度为0&#xff0c;并设置sizePolicy为Expanding&#xff0c;让其自动伸缩。 结果展示&#xff08;自…

Leetcode - 周赛436

目录 一、3446. 按对角线进行矩阵排序二、3447. 将元素分配给有约束条件的组三、3448. 统计可以被最后一个数位整除的子字符串数目四、3449. 最大化游戏分数的最小值 一、3446. 按对角线进行矩阵排序 题目链接 本题可以暴力枚举&#xff0c;在确定了每一个对角线的第一个元素…

玩转SpringCloud Stream

背景及痛点 现如今消息中间件(MQ)在互联网项目中被广泛的应用&#xff0c;特别是大数据行业应用的特别的多&#xff0c;现在市面上也流行这多个消息中间件框架&#xff0c;比如ActiveMQ、RabbitMQ、RocketMQ、Kafka等&#xff0c;这些消息中间件各有各的优劣&#xff0c;但是想…