【开源风云】从若依系列脚手架汲取编程之道(一)

📕开源风云系列

  • 🍊本系列将从开源名将若依出发,探究优质开源项目脚手架汲取编程之道。
  • 🍉从不分离版本开写到前后端分离版,再到微服务版本,乃至其中好玩的一系列增强Plus操作
  • 🍈希望你具备如下技术栈
    • 🍎Spring
    • 🍍SpringMVC
    • 🍐Mybatis/Mybatis-plus
    • 🍅Thymeleaf
    • 🥝SpringBoot
    • 🍓Shiro
    • 🍏SpringSecurity
    • 🍌SpringCloud
    • 🍒云服务器相关知识
  • 本篇是不分离版第一篇

后期会考虑将项目和安全方面的文章迁移至vuepress,找一个好看的主题,视觉效果++!

1、拉取代码

  1. 进入若依官网:RuoYi
  1. 进入Gitee,点击Forked ,就会Forked一份代码到自己的仓库
  1. 在自己仓库找到RuoYi仓库,然后复制其 URL
  1. 打开IDEA,点击 从VCS获取 ,粘贴上方复制的URL,然后点击克隆
  1. OK,现在我们就把RuoYi的代码拉到自己本地啦!

2、创建数据库

  1. 打开Navicat ,新建数据库kuangstudy_ruoyi_fast,字符集为utf8mb4,排序规则为 utf8mb4_general_ci
  1. 右键运行SQL文件 ,导入刚才拉取代码sql里面的quartz.sqlry_20240112.sql
  1. 打开ruoyi-admin/src/main/resources/application-druid.yml,修改主库数据源
  1. 运行ruoyi-admin/src/main/java/com/ruoyi/web/RuoYiApplication.java
  1. 打开浏览器,输入http://localhost:80 ,输入默认账户密码:admin/admin123

3、项目结构

text 复制代码
com.ruoyi     
├── common            // 工具类
│       └── annotation                    // 自定义注解
│       └── config                        // 全局配置
│       └── constant                      // 通用常量
│       └── core                          // 核心控制
│       └── enums                         // 通用枚举
│       └── exception                     // 通用异常
│       └── json                          // JSON数据处理
│       └── utils                         // 通用类处理
│       └── xss                           // XSS过滤处理
├── framework         // 框架核心
│       └── aspectj                       // 注解实现
│       └── config                        // 系统配置
│       └── datasource                    // 数据权限
│       └── interceptor                   // 拦截器
│       └── manager                       // 异步处理
│       └── shiro                         // 权限控制
│       └── web                           // 前端控制
├── ruoyi-generator   // 代码生成(不用可移除)
├── ruoyi-quartz      // 定时任务(不用可移除)
├── ruoyi-system      // 系统代码
├── ruoyi-admin       // 后台服务
├── ruoyi-xxxxxx      // 其他模块

4、配置介绍

4.1、服务器配置

4.1.1、如何修改服务器端口

  • ruoyi-admin/src/main/java/application.yml下查看服务端配置
yaml 复制代码
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为80
  port: 80
  servlet:
    # 应用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # 连接数满后的排队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100

假如将服务器的HTTP端口改为8090,应用的访问路径改为/admin,则访问浏览器就从localhost:80 变成 localhost:8090/admin

4.1.2、如何配置tomcat访问日志

  1. 修改application.yml中的server开发环境配置
yaml 复制代码
tomcat:
    # 存放Tomcat的日志目录
    basedir: D:\Code\IDEA\KuangStudy_RuoYi_Fast\logs\tomcat
    accesslog:
      # 开启日志记录
      enabled: true
      # 访问日志存放目录
      directory: logs
  1. 重启应用登录

  2. 进入E:\Code\IDEA\KuangStudy_RuoYi_Fast\logs\tomcat 则可查看到日志

若需要再额外配置日志,请百度:SpringBoot配置tomcat访问日志

4.2、多环境配置

在我们的日常开发中,生产环境的配置测试环境的配置 以及开发环境的配置基本上都是不相同的,每次到部署环境的时候,就需要手动的切换配置文件,如果在切换的过程中一不小心的话就会出错,所以在开发中,一般会搞个配置文件检查的功能,来避免出错,而Spring Boot则充分考虑了这种情况,为开发人员提供了天然的多环境配置支持。

  1. 配置文件的名字可以是application-{profile}.yml
  2. 在配置文件中指定:spring.profiles.active={profile}

我们可以创建三个配置文件,分别为:

  • application-test.yml : 测试环境

  • application-dev.yml : 开发环境

  • application-prod.yml : 生产环境

application-test.yml 内容如下,测试端口为81:

yaml 复制代码
# 开发环境配置
server:
    # 服务器的HTTP端口,测试环境为81
    port: 81
    servlet:
        # 应用的访问路径
        context-path: /
    tomcat:
        # tomcat的URI编码
        uri-encoding: UTF-8
        # 连接数满后的排队数,默认为100
        accept-count: 1000
        threads:
            # tomcat最大线程数,默认为200
            max: 800
            # Tomcat启动初始化的线程数,默认值10
            min-spare: 100

# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://localhost:3306/kuangstudy_ruoyi_fast?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: 123456
            # 从库数据源
            slave:
                # 从数据源开关/默认关闭
                enabled: false
                url: 
                username: 
                password: 
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置连接超时时间
            connectTimeout: 30000
            # 配置网络超时时间
            socketTimeout: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter: 
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username: ruoyi
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true
  • application-dev.yml 开发环境同上,只是端口为80
  • application-prod.yml 生产环境同上,只是端口为82

之后在 application.ymlspring.profile.active指定环境即可:

yaml 复制代码
# Spring配置
spring:
  profiles:
  	# active: test
  	# active: dev
  	# active: prod
    active: druid

4.2.1、文档块简洁配置

除了上述配置方法外,我们还可以使用文档块配置,更简洁:

  1. application.yml添加
yaml 复制代码
---
spring:
 profiles: dev

# 开发环境配置
server:
    # 服务器的HTTP端口,测试环境为81
    port: 81
    servlet:
        # 应用的访问路径
        context-path: /
    tomcat:
        # tomcat的URI编码
        uri-encoding: UTF-8
        # 连接数满后的排队数,默认为100
        accept-count: 1000
        threads:
            # tomcat最大线程数,默认为200
            max: 800
            # Tomcat启动初始化的线程数,默认值10
            min-spare: 100
            
            
---
spring:
 profiles: test
 
# 测试环境配置
server:
    # 服务器的HTTP端口,测试环境为81
    port: 81
    servlet:
        # 应用的访问路径
        context-path: /
    tomcat:
        # tomcat的URI编码
        uri-encoding: UTF-8
        # 连接数满后的排队数,默认为100
        accept-count: 1000
        threads:
            # tomcat最大线程数,默认为200
            max: 800
            # Tomcat启动初始化的线程数,默认值10
            min-spare: 100


---
spring:
 profiles: prod
 
# 生产环境配置
server:
    # 服务器的HTTP端口,生产环境为82
    port: 82
    servlet:
        # 应用的访问路径
        context-path: /
    tomcat:
        # tomcat的URI编码
        uri-encoding: UTF-8
        # 连接数满后的排队数,默认为100
        accept-count: 1000
        threads:
            # tomcat最大线程数,默认为200
            max: 800
            # Tomcat启动初始化的线程数,默认值10
            min-spare: 100

4.2.2、jar包指定环境

如果我们将项目打成 jar 包,如何指定环境运行呢?

bash 复制代码
# 以开发环境运行
java -jar RuoYi.jar --spring.profiles.active=dev
# 以测试环境运行
java -jar RuoYi.jar --spring.profiles.active=test
# 以生产环境运行
java -jar RuoYi.jar --spring.profiles.active=prod

4.3、读取application.yml

ruoyi-admin/src/main/resources/application.yml里面有项目相关配置,我们来看在代码层面是怎么获取的

yaml 复制代码
# 项目相关配置
ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 4.7.8
  # 版权年份
  copyrightYear: 2023
  # 实例演示开关
  demoEnabled: true
  # 上传的文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: false

# Shiro
shiro:
  user:
    # 登录地址
    loginUrl: /login
    # 权限认证失败地址
    unauthorizedUrl: /unauth
    # 首页地址
    indexUrl: /index
    # 验证码开关
    captchaEnabled: true
    # 验证码类型 math 数字计算 char 字符验证
    captchaType: math
  cookie:
    # 设置Cookie的域名 默认空,即当前访问的域名
    domain:
    # 设置cookie的有效访问路径
    path: /
    # 设置HttpOnly属性
    httpOnly: true
    # 设置Cookie的过期时间,天为单位
    maxAge: 30
    # 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效)
    cipherKey:
  session:
    # Session超时时间,-1代表永不过期(默认30分钟)
    expireTime: 30
    # 同步session到数据库的周期(默认1分钟)
    dbSyncPeriod: 1
    # 相隔多久检查一次session的有效性,默认就是10分钟
    validationInterval: 10
    # 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
    maxSession: -1
    # 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
    kickoutAfter: false
  rememberMe:
    # 是否开启记住我
    enabled: true

ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java类是全局配置类,类上面有两个注解:

  • @Component : 把这个类交给Spring处理
  • @ConfigurationProperties(prefix = "ruoyi") : 把配置文件application.yml 里面的值映射到类里面,指定前缀是 ruoyi

所以要在其他类中读取到这些信息,可以使用如下第一种方式

  1. 导入RuoYiConfig 类,使用 RuoYiConfig.xxx 来访问
  2. 在Spring中注入使用
java 复制代码
@AutoWired
private RuoYiConfig ruoYiConfig;

// xxx
// 调用方法
ruoYiConfig.getName();

也可以使用第二种方式 :例如application.yml里面的shiro配置

yaml 复制代码
# Shiro
shiro:
  user:
    # 登录地址
    loginUrl: /login
    # 权限认证失败地址
    unauthorizedUrl: /unauth
    # 首页地址
    indexUrl: /index
    # 验证码开关
    captchaEnabled: true
    # 验证码类型 math 数字计算 char 字符验证
    captchaType: math
  cookie:
    # 设置Cookie的域名 默认空,即当前访问的域名
    domain:
    # 设置cookie的有效访问路径
    path: /
    # 设置HttpOnly属性
    httpOnly: true
    # 设置Cookie的过期时间,天为单位
    maxAge: 30
    # 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效)
    cipherKey:
  session:
    # Session超时时间,-1代表永不过期(默认30分钟)
    expireTime: 30
    # 同步session到数据库的周期(默认1分钟)
    dbSyncPeriod: 1
    # 相隔多久检查一次session的有效性,默认就是10分钟
    validationInterval: 10
    # 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
    maxSession: -1
    # 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
    kickoutAfter: false
  rememberMe:
    # 是否开启记住我
    enabled: true

src/main/java/com/ruoyi/framework/config/ShiroConfig.java类中使用@Value注解来注入值

复习:

  • 当类中使用了@Value@Bean注解,需要加@Configuration注解。
  • @Configuration 用于标识一个类作为应用程序上下文的配置类

4.4、自定义资源映射

src/main/java/com/ruoyi/framework/config/ResourcesConfig.java 是静态资源映射的路径:

  • 默认的/是转发跳转到首页
  • 对于上传的文件其实是上传到本地的D:/ruoyi/uploadPath路径下

怎么验证呢,我们登录若依,并修改自己的头像,修改好的头像会上传到本机D:/ruoyi/uploadPath目录下。

5、Shiro相关

5.1、登录的实现

  1. src/main/resources/templates/login.html是我们的登录的 html,在 src/main/resources/static/ruoyi/login.js 是我们登录的 js,这里看一下登录表单的验证

表单验证方法为function validateRule() 方法,若未填写账户密码会提示文字 message。

  1. 当表单验证成功后会进入 $.validator.setDefaults() 方法,会调用 login()方法进行登录
  1. 我们看一下后端的登录接口,在src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

里面的 Post 方法登录:

  1. 我们自定义的Realm是在src/main/java/com/ruoyi/framework/shiro/realm/UserRealm.java中,调用了我们自己的 loginService.login() 方法
  1. src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java 登录逻辑里面做了用户名和密码的校验

5.2、验证码实现

  1. src/main/java/com/ruoyi/framework/config/CaptchaConfig.java 里面可以设置验证码的设置
  1. application.yml里面有验证码的开关和验证码的类型

5.3、记住我实现

  1. login.html里面有 input 标签,对应 login.js 里面会传递一个 rememberMe布尔值
  1. SysLoginController.java里面会接收前端传递的布尔值,进而在ShiroConfig里面进行放置到Cookie中,最终通过securityManager()方法将这些信息注入到安全管理器里面。
  • 如图,在yml中配置cookie的属性
  • rememberMeManager注入到安全管理器securityManager
  • 最重要的是ShiroConfig的Shiro过滤器配置,这里表示对于user,kickout,onlineSession,syncOnlineSession这些路径点击记住我之后就可以被访问。

5.4、权限控制实现

  1. 角色管理可以控制对应角色的菜单权限

在前端代码层面是使用shiro:hasPermission="xxx:xxx:xxx" 来控制按钮的权限,当然我们也可以加shiro:hasRole="admin" 这样的话这个按钮就只能由权限字符为 admin 的用户操作了。

当然关于角色权限字符串 可以在sys_role表中查看:

对于权限标识可以在sys_menu中查看:

  1. 在后端也有相应的权限控制@RequiresPermissions("xxx.xxx.xxx")

[!note]

为什么前后端都要设置权限呢?

  • 前端权限是为了展示出操作按钮,恶意用户总有可能尝试绕过前端直接对后端接口发起请求。 因此,后端必须对每一个请求进行权限检查,确保只有拥有足够权限的用户才能执行相关操作

5.5、退出

Shiro自身带有退出的过滤器,所以若依是重写了过滤器的方法。

同时在ShiroConfig里面指明请求/logout路径的过滤器为logout,过滤器logout指向的就是若依自己写logoutFilter,在这个退出过滤器里面重写了方法。

相关推荐
_oP_i4 小时前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
星就前端叭9 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
Faith_xzc13 小时前
【Apache Doris】周FAQ集锦:第 26 期
大数据·数据仓库·开源·doris
vvw&17 小时前
如何在 Ubuntu 22.04 上安装 Ansible 教程
linux·运维·服务器·ubuntu·开源·ansible·devops
vvw&19 小时前
如何在 Ubuntu 22.04 上安装 Graylog 开源日志管理平台
linux·运维·服务器·ubuntu·开源·github·graylog
HelloGitHub20 小时前
跟着 8.6k Star 的开源数据库,搞 RAG!
开源·github
GitCode官方20 小时前
GitCode 光引计划投稿 | GoIoT:开源分布式物联网开发平台
分布式·开源·gitcode
m0_7482567821 小时前
WebGIS实战开源项目:智慧机场三维可视化(学习笔记)
笔记·学习·开源
猫头虎21 小时前
新纪天工 开物焕彩:重大科技成就发布会参会感
人工智能·开源·aigc·开放原子·开源软件·gpu算力·agi
血色橄榄枝1 天前
进阶岛-L2G5000
人工智能·开源