????开源风云系列
本篇文字量巨大,甚至在发表编辑之时造成编辑器卡顿,哈哈,最近在忙人生的另一项规划,文章更新就逐渐缓慢了,希望我们都逐渐走向自己的道路呀!
- ????本系列将从开源名将若依出发,探究优质开源项目脚手架汲取编程之道。
- ????从不分离版本开写到前后端分离版,再到微服务版本,乃至其中好玩的一系列增强Plus操作。
-
????希望你具备如下技术栈:
- ????Spring
- ????SpringMVC
- ????Mybatis/Mybatis-plus
- ????Thymeleaf
- ????SpringBoot
- ????Shiro
- ????SpringSecurity
- ????SpringCloud
- ????云服务器相关知识
- 本篇是微服务版第一篇
-
文章同时同步到我的个人站点????欢迎来访!:
- ????国内:https://www.linxiaoqin.netlify.app
- ????国际:https://www.linxiaoqin.vercel.app
目录
- ????开源风云系列
- 1、RuoYi-Clouid
- 1.1、导入数据库
- 1.2、Docker中运行Nacos
- 1.3、运行网关Gateway模块
- 1.3.1、修改ruoyi-gateway-dev.yml
- 1.3.2、启动RuoYiGatewayApplication.java
- 1.3.3、启动时控制台细节
- 1.4、运行认证Auth模块
- 1.5、运行系统System模块
- 1.6、运行前端
- 1.7、前后端目录结构
- 1.7.1、后端结构
- 1.7.2、前端结构
- 1.7.3、核心技术
- 2、服务网关
- 2.1、微服务架构图
- 2.2、路由分发具体策略
- 2.3、过滤器工厂
- 2.3.1、全局过滤器
- 2.4、断言工厂
- 3、业务逻辑
- 3.1、被定位至登录
- 3.2、记住密码逻辑
- 3.3、dev-api
- 3.4、验证码
- 3.5、登录
- 3.5.1、登录前端
- 3.5.2、表单校验
- 3.5.3、登录后端
- 1、验证码过滤器
- 2、登录逻辑
- 3、生成token
- 4、JWT存储信息
- 3.5.4、登录前端
- 3.5.5、获取用户信息前端
- 3.5.6、获取用户信息后端
- 3.5.7、获取路由信息后端
- 3.5.8、获取路由信息前端
- 3.5.9、获取用户信息前端补充
- 3.6、权限
- 3.6.1、前端权限
- 3.6.2、后端权限
- 3.6.3、权限总结
1、RuoYi-Clouid
我这里将部分服务部署在云上服务器
1.1、导入数据库
- 下载源码,解压,将
ruoyi-ui
放到webstrom中 - 将其他目录加载进 IDEA 中,等待IDEA加载依赖
- 在宝塔创建数据库
kuangstudy_cloud
,访问权限选择所有人。再创建数据库kuangstudy_config
-
使用Navicat连接数据库
kuangstudy_cloud
,导入数据脚本ry_2024xxxx.sql
(必须),quartz.sql
(可选) -
使用Navicat连接数据库
kuangstudy_config
,导入数据脚本ry_config_2024xxxx.sql
(必须)
[!WARNING]
注意: 在执行
ry_config_2024xxxx.sql
时候,需要提前进入 sql ,将ry-config
替换为kuangstudy-config
如果你数据库起名为
ry-config
,则不需要执行这一步。
1.2、Docker中运行Nacos
我们要首先安装Docker,Docker的安装可以使用命令也可以使用宝塔一键安装,我这边使用宝塔进行安装。
[!NOTE]
这里我贴上我自己的Docker笔记,里面有相关的安装命令,非常详细。
- Docker镜像命令与容器命令及数据卷(一)
- Docker网桥、DockerFile自定义镜像、DockerCompose工具(二)
- 在宝塔后台安装Docker,点击Docker - 立即安装 - 这里我选择阿里云镜像安装
- 安装完成后设置加速URL,我选择的是阿里云镜像加速站,然后重启Docker
或者也可以参考教程贴设置自己的容器加速:如何在宝塔面板更换Docker加速站
只是我这边发现设置了不回显,执行命令
cat /etc/docker/daemon.json
也无此文件,说明宝塔面板的加速URL的设置没生效,所以我是直接更换了镜像加速
安装成功后,在服务器上执行docker -v
即可看到安装的版本
- 宝塔面板的应用商店只有个别的镜像,我没搜到nacos镜像,所以还是得命令执行拉取nacos镜像
docker pull nacos/nacos-server
- 运行nacos容器
docker run -d \
--name nacos \
-e PREFER_HOST_MODE=hostname \
-e MODE=standalone \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=49.232.28.14 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_USER=kuang_config \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e MYSQL_SERVICE_DB_NAME=kuangstudy_config \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
--network=host \
nacos/nacos-server
docker run
命令用来在Docker中启动一个Nacos服务器容器。让我们逐个解析参数和它们的作用:
-d
:以守护进程(daemon)模式运行容器,这意味着容器将在后台运行。--name nacos
:为容器命名,这里命名为nacos
。-e
:设置环境变量。以下是一些具体的环境变量及其作用:
PREFER_HOST_MODE=hostname
:指示Nacos优先使用主机名而不是IP地址进行网络通信。MODE=standalone
:指定Nacos运行模式为独立模式,即单机模式。SPRING_DATASOURCE_PLATFORM=mysql
:告诉Nacos数据源平台是MySQL。MYSQL_SERVICE_HOST=49.232.28.14
:MySQL服务的主机地址。MYSQL_SERVICE_PORT=3306
:MySQL服务的端口。MYSQL_SERVICE_USER=kuang_config
:用于连接MySQL数据库的用户名。MYSQL_SERVICE_PASSWORD=123456
:连接MySQL数据库的密码。MYSQL_SERVICE_DB_NAME=kuangstudy_config
:要使用的MySQL数据库名称。JVM_XMS=256m
:设置JVM初始堆内存大小为256MB。JVM_XMX=256m
:设置JVM最大堆内存大小为256MB。--network=host
:使用宿主机的网络模式,这将使容器共享宿主机的网络栈,因此容器将直接使用宿主机的网络接口。nacos/nacos-server
:指定要运行的Docker镜像,这里是Nacos服务器的官方镜像。此外,使用
--network=host
可能会带来安全风险,因为它允许容器直接访问宿主机的网络,这可能会暴露宿主机上的其他服务。在生产环境中,通常建议使用更安全的网络模式,如桥接网络或用户定义的网络。
在宝塔面板可以点击容器,看到我们的nacos容器正在运行。
- 访问:
http://服务器ip:8848/nacos
,默认账号密码都是nacos
[!NOTE]
注意:记得宝塔面板和云服务器开启8848防火墙端口呦!官方文档说开8848和9848就可以满足大多数场景下的网络配置需求。登录成功后就可以看到如下页面,而表格中的数据就是我们导入的 config 配置。
[官方文档]nacos默认需要放开哪几个端口号
1.3、运行网关Gateway模块
- RuoYiGatewayApplication (网关模块 必须)
- RuoYiAuthApplication (认证模块 必须)
- RuoYiSystemApplication (系统模块 必须)
- RuoYiMonitorApplication (监控中心 可选)
- RuoYiGenApplication (代码生成 可选)
- RuoYiJobApplication (定时任务 可选)
- RuoYFileApplication (文件服务 可选)
在真正部署起来后,前端所有的API请求都会通过Nginx,Nginx会将请求转发到网关模块,也就是 8080 端口,之后由后端的网关模块再去进行一个转发。
-
修改
ruoyi-gateway
模块下的bootstrap.yml
只需要更改三个地方的ip,服务注册地址、配置中心地址、nacos配置持久化,控制台地址ip不需要改动
# Tomcat
server:
port: 8080
# Spring
spring:
application:
# 应用名称:向注册中心注册的时候用的名称
name: ruoyi-gateway
profiles:
# 环境配置 指定了当前环境配置为 dev(开发环境)
active: dev
cloud:
nacos:
# discovery 配置用于服务发现,指定了 Nacos 服务器地址
discovery:
# 服务注册地址
server-addr: 49.232.28.14:8848
# config 配置用于从 Nacos 获取配置信息,同样指定了 Nacos 地址,并且说明了配置文件的格式为 .yml
config:
# 配置中心地址
server-addr: 49.232.28.14:8848
# 配置文件格式
file-extension: yml
# 共享配置:定义了要从 Nacos 加载的共享配置文件,使用了 ${} 占位符来动态引用环境变量,即在开发环境下加载名为 application-dev.yml 的配置文件。
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 用于流量控制、熔断降级和系统保护的应用组件sentinel
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 指定 Sentinel 控制台地址
dashboard: 127.0.0.1:8718
# nacos配置持久化
datasource:
# ds1 是一个指向 Nacos 的数据源,用于存储和读取 Sentinel 的规则配置
ds1:
nacos:
server-addr: 49.232.28.14:8848
# dataId 和 groupId 分别表示规则在 Nacos 中的标识和分组
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
# data-type 和 rule-type 指定了规则类型为 JSON 格式和网关流量控制规则
data-type: json
rule-type: gw-flow
共享配置就是不止网关模块,其他模块也在用的配置文件,我们称为共享配置。一般情况下这个共享配置就是
application-dev.yml
我们点击详情,可以进去查看
spring:
# 排除Druid 数据源,因为若依自己重写了多数据源
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
# 指定了 Spring MVC 使用 Ant 风格的路径匹配器(AntPathMatcher)作为请求映射策略
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# feign 配置:
feign:
# 启用 Sentinel 与 Feign 的集成,Sentinel 是一个开源的系统保护框架,可以用于流量控制、熔断降级等场景
sentinel:
enabled: true
# 使用 OkHttp 作为 Feign 的 HTTP 客户端,而不是 Apache HttpClient
okhttp:
enabled: true
httpclient:
enabled: false
# 设置 Feign 客户端的连接超时时间为 10 秒,读取超时时间也为 10 秒
client:
config:
default:
connectTimeout: 10000
readTimeout: 10000
# 启用了 Feign 请求和响应的压缩,请求压缩最小大小为 8KB。这有助于减少网络传输的数据量,提高传输效率
compression:
request:
enabled: true
min-request-size: 8192
response:
enabled: true
# 暴露监控端点
# Actuator 提供了一系列的监控和管理端点,如健康检查、度量指标、审计事件等。将 include 设置为 '*' 意味着所有端点都可以通过 Web 访问,这对于开发和测试非常有用,但在生产环境中可能需要更严格的访问控制。
management:
endpoints:
web:
exposure:
include: '*'
1.3.1、修改ruoyi-gateway-dev.yml
- 修改
ruoyi-gateway-dev.yml
,修改 redis 配置
spring:
redis:
# 主机地址
host: 49.232.28.14
# 端口
port: 6379
# 密码
password: xxxx
database: 10
# 配置了 Spring Cloud Gateway 的服务发现定位器,使其能够从注册中心Nacos发现并路由到服务实例
cloud:
gateway:
discovery:
locator:
# 服务 ID 将被转换为小写
lowerCaseServiceId: true
# 启用这个特性
enabled: true
# 认证中心:每个 - 开头的条目定义了一个路由规则,包括路由id、目标uri、路由条件、路由过滤器
routes:
# ruoyi-auth路由将所有以 /auth/ 开始的请求代理到名为 ruoyi-auth 的服务,并且应用了三个过滤器:缓存请求、验证码验证和前缀剥离
- id: ruoyi-auth
uri: lb://ruoyi-auth
predicates:
- Path=/auth/**
filters:
# 验证码处理
- CacheRequestFilter
- ValidateCodeFilter
- StripPrefix=1
# 代码生成
- id: ruoyi-gen
uri: lb://ruoyi-gen
predicates:
- Path=/code/**
filters:
- StripPrefix=1
# 定时任务
- id: ruoyi-job
uri: lb://ruoyi-job
predicates:
- Path=/schedule/**
filters:
- StripPrefix=1
# 系统模块
- id: ruoyi-system
uri: lb://ruoyi-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
# 文件服务
- id: ruoyi-file
uri: lb://ruoyi-file
predicates:
- Path=/file/**
filters:
- StripPrefix=1
# 安全配置
security:
# 验证码开启
captcha:
enabled: true
type: math
# 防止XSS攻击
xss:
enabled: true
# 排除 url
excludeUrls:
- /system/notice
# 不校验白名单:不需要身份验证的 URL 白名单
ignore:
whites:
- /auth/logout
- /auth/login
- /auth/register
- /*/v2/api-docs
- /csrf
1.3.2、启动RuoYiGatewayApplication.java
启动RuoYiGatewayApplication.java
的 main 方法即可。在Nacos中的服务列表可以看到服务,则说明启动成功
1.3.3、启动时控制台细节
启动时,我们可以从打印控制台看到如下信息:
21:12:49.954 [main] INFO c.a.c.n.r.NacosContextRefresher - [registerNacosListener,129] - [Nacos Config] Listening config: dataId=ruoyi-gateway, group=DEFAULT_GROUP
21:12:49.955 [main] INFO c.a.c.n.r.NacosContextRefresher - [registerNacosListener,129] - [Nacos Config] Listening config: dataId=ruoyi-gateway.yml, group=DEFAULT_GROUP
21:12:49.955 [main] INFO c.a.c.n.r.NacosContextRefresher - [registerNacosListener,129] - [Nacos Config] Listening config: dataId=ruoyi-gateway-dev.yml, group=DEFAULT_GROUP
(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙
.-------. ____ __
| _ _ \ \ \ / /
| ( ' ) | \ _. / '
|(_ o _) / _( )_ .'
| (_,_).' __ ___(_ o _)'
| |\ \ | || |(_,_)'
| | \ `' /| `-' /
| | \ / \ /
''-' `'-' `-..-'
配置中心的数据实时发布,微服务模块可以收到配置中心的数据,那么网关模块可以收到哪些配置信息呢?仔细看如下打印,有三个配置文件可以收到:
Listening config: dataId=ruoyi-gateway, group=DEFAULT_GROUP
Listening config: dataId=ruoyi-gateway.yml, group=DEFAULT_GROUP
Listening config: dataId=ruoyi-gateway-dev.yml, group=DEFAULT_GROUP
说明网关模块在获取dataID为ruoyi-gateway
,group为DEFAULT_GROUP
的配置信息,可以理解为横纵坐标,通过横纵坐标,可以找到网关模块可以获取到如下配置信息:
在这里可以发现,若依很细节,其实如果我们不写后缀 .yml,其实网关模块也是可以收到的哈哈哈
1.4、运行认证Auth模块
- 修改修改
ruoyi-auth
模块下的bootstrap.yml
- 修改nacos的
ruoyi-auth-dev.yml
spring:
redis:
host: 49.232.28.14
port: 6379
password: xxxx
database: 10
- 启动
RuoYiAuthApplication.java
的 main 方法即可。在Nacos中的服务列表可以看到服务,则说明启动成功
同理,通过控制台可以看到认证模块监听的配置文件如下
1.5、运行系统System模块
- 修改
ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml
- 修改
ruoyi-system-dev.yml
- 修改 redis 的host、账号密码、包括 database
- 修改主库数据源的链接、账号密码
# spring配置
spring:
redis:
host: 49.232.28.14
port: 6379
password: First123.
database: 10
datasource:
# druid 服务监控的账号和密码,也就是druid自己的控制台
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: 123456
# 动态数据源
dynamic:
druid:
# 初始创建的连接数
initial-size: 5
# 最小空闲连接数
min-idle: 5
# 最大活动连接数
maxActive: 20
# 获取连接的最大等待时间,单位毫秒
maxWait: 60000
# 建立连接的超时时间,单位毫秒
connectTimeout: 30000
# 读取数据的超时时间,单位毫秒
socketTimeout: 60000
# 连接空闲检查的时间间隔,单位毫秒
timeBetweenEvictionRunsMillis: 60000
# 连接空闲多久后可被驱逐,单位毫秒
minEvictableIdleTimeMillis: 300000
# 用于验证连接有效性的SQL语句
validationQuery: SELECT 1 FROM DUAL
# 当连接空闲时进行验证
testWhileIdle: true
# 当从连接池获取连接时进行验证
testOnBorrow: false
# 当连接返回连接池时进行验证
testOnReturn: false
# 是否缓存PreparedStatement
poolPreparedStatements: true
# 每个连接缓存的PreparedStatement数量
maxPoolPreparedStatementPerConnectionSize: 20
# Druid提供的过滤器,例如统计和日志记录
filters: stat,slf4j
# Druid的连接属性,包括合并SQL和慢SQL的阈值
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
datasource:
# 主库数据源
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://49.232.28.14:3306/kuangstudy_cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: kuangstudy_cloud
password: 123456
# 从库数据源
# slave:
# username:
# password:
# url:
# driver-class-name:
# mybatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.ruoyi.system
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath:mapper/**/*.xml
# swagger配置
swagger:
title: 系统模块接口文档
license: Powered By ruoyi
licenseUrl: https://ruoyi.vip
解释之前为什么要排除Druid,是因为我们自己写了动态数据源 dynamic,然后用了Druid,又分为主从库
- 运行
RuoYiSystemApplication.java
的main方法
同理,通过控制台可以看到系统模块监听的配置文件如下
1.6、运行前端
这样必须运行的模块都运行完成了,其他模块暂时可以不用管,我们接下来运行前端
- 拉取依赖
npm i
# 或者(推荐)
pnpm i
- 在 package.json 中运行 dev
大功告成!我们这个时候可以不登陆,直接去看redis中的数据!
这个就跟前后端分离版本串起来了!满满的熟悉感吧哈哈哈!之后就可以奔放玩啦!
1.7、前后端目录结构
1.7.1、后端结构
微服务版本若依没有用Spring Security 框架,而是自己写了一套安全框架。
1.7.2、前端结构
1.7.3、核心技术
[!NOTE]
- 前端技术栈 ES6、vue、vuex、vue-router、vue-cli、axios、element-ui
- 后端技术栈 Spring Boot、Spring Cloud & Alibaba、Nacos、Sentinel
2、服务网关
2.1、微服务架构图
????????????浏览器发生API的调用,调用的时候可以使用Nginx进行负载均衡,进入网关gateway集群,例如如下配置:网关根据我们的url路径,判断进入哪个微服务,比如:访问的路径是/auth/**
打头的,那么网关就将请求负载均衡送入lb://ruoyi-auth
微服务,lb就是负载均衡,并且对请求进行过滤和处理,需要注意的是StripPrefix=1
,会把请求的/auth
前缀去掉,那么请求的就会是/**
后面的url了。
spring:
cloud:
routes:
# 认证中心
- id: ruoyi-auth
uri: lb://ruoyi-auth
predicates:
- Path=/auth/**
filters:
# 验证码处理
- CacheRequestFilter
- ValidateCodeFilter
- StripPrefix=1
像上面配置的 filters 过滤器有三个,分别是验证码、校验码、前缀去除过滤器。其中前缀去除StripPrefix过滤器是SpringCloud自带的,SpringCloud自带的过滤器有很多,进入查看
- 并且这种配置在一个路由下的 filters 是局部过滤器,只对这个路由下的请求生效
2.2、路由分发具体策略
spring:
redis:
host: 49.232.28.14
port: 6379
password: xxx
database: 10
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 认证中心
- id: ruoyi-auth
uri: lb://ruoyi-auth
predicates:
- Path=/auth/**
filters:
# 验证码处理
- CacheRequestFilter
- ValidateCodeFilter
- StripPrefix=1
# 代码生成
- id: ruoyi-gen
uri: lb://ruoyi-gen
predicates:
- Path=/code/**
filters:
- StripPrefix=1
# 定时任务
- id: ruoyi-job
uri: lb://ruoyi-job
predicates:
- Path=/schedule/**
filters:
- StripPrefix=1
# 系统模块
- id: ruoyi-system
uri: lb://ruoyi-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
# 文件服务
- id: ruoyi-file
uri: lb://ruoyi-file
predicates:
- Path=/file/**
filters:
- StripPrefix=1
# 安全配置
security:
# 验证码
captcha:
enabled: true
type: math
# 防止XSS攻击
xss:
enabled: true
excludeUrls:
- /system/notice
# 不校验白名单
ignore:
whites:
- /auth/logout
- /auth/login
- /auth/register
- /*/v2/api-docs
- /csrf
Spring Cloud Gateway配置
-
routes
:定义 Spring Cloud Gateway的路由规则 -
id: ruoyi-auth
: 路由规则的ID,用于标识该路由规则 -
uri: lb://ruoyi-auth
:路由的目标地址,使用负载均衡的方式访问ruoyi-auth
服务- lb : load balance 负载均衡
-
predicates
: 定义路由规则的匹配条件-
- Path=/auth/**
:请求路径匹配规则,表示所有以/auth/
开头的请求
-
-
filters
:定义过滤器,对请求进行过滤和处理-
- CacheRequestFilter
:缓存请求的过滤器 -
- ValidateCodeFilter
: 验证码验证过滤器 -
- StringPrefix=1
:移除请求路径中的/auth
前缀
-
2.3、过滤器工厂
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。
在过滤器这里可参考:SpringCloud过滤器工厂
2.3.1、全局过滤器
2.4、断言工厂
- 这里我之前的笔记也有记录:SpringCloud断言工厂
3、业务逻辑
3.1、被定位至登录
当我们请求localhost:80
也就是相当于请求path为空,会被重定向到 index 首页,但是实际上是进入的登录login页面,为什么会这样呢?
- 实际上是前端的前置路由会去判断此次请求是否携带了 token,如果没带且不在白名单内,则会重定向至登录页面
3.2、记住密码逻辑
记住密码若依是什么逻辑呢?在login.vue
里面可以看到,进入页面会执行getCookie
方法,也就是假如点击了记住密码,那么首先会从Cookie里面去找username和password。
而且我们的账号密码默认填充的,也是在da