项目讲解之火爆全网的开源后台管理系统RuoYi

简介: 项目讲解之火爆全网的开源后台管理系统RuoYi

image.png

博主是在2018年中就接触了 RuoYi 项目 这个项目,对于当时国内的开源后台管理系统来说,RuoYi 算是一个完成度较高,易读易懂、界面简洁美观的前后端不分离项目。

对于当时刚入行还在写 jsp 模板的博主来说,RuoYi 项目在后台基础功能、模块划分、易用性和页面美观度上,对比同期用 Java 开源的前后端不分离后台项目整体上是高了一个等级的。并且项目 commit 频繁,代码质量不断提高、bug不断修复,使得这个项目在今天来说任然是具有学习价值的。

本文博主尽量用一个理性视角带领大家由浅入深看 RuoYi 项目v4.7.6版本的优秀设计。

一、快速了解

RuoYi 项目是一个基于 SpringBoot + Mybatis + Shiro 开发的轻量级 Java 快速开发框架,它包含基础的后台管理功能以及权限控制。项目作者对于 RuoYi 项目的定调是这样的:

RuoYi是一款基于SpringBoot+Bootstrap的极速后台开发框架。

RuoYi 是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Apache Shiro、MyBatis、Thymeleaf、Bootstrap)。内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、通知公告等。在线定时任务配置;支持集群,支持多数据源,支持分布式事务。

二、多模块设计

如果想快速了解一个项目的设计理念那直接下载这个项目,查看项目结构即可略知一二。这里参考官网给出的项目结构:

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

由上可知,RuoYi 前后端不分离项目按照模块划分成了七个模块

  • ruoyi-common 包含了整个项目基础的注解、枚举、异常、帮助类的定义以及在 core 包中定义的基础用户、角色、菜单、字典类的 entity 对象以及其他 ajax 响应结果、分页参数、文本处理等一众基础类

image.png

ruoyi-framework 是整个项目的核心模块,因为这里面有整个项目的核心配置代码,全部在 config 目录下

image.png

  • 其中 ShiroConfig 是最核心的配置,整合了 shiro 框架,给项目提供了权限管理功能
  • ruoyi-generator 主要用作代码生成,目包含一个对外提供服务模块所需的 contrller、domain、mapper、service、util、config 等包。如果添加 Spring Boot 启动类就可以直接作为独立项目启动。作为 ruoyi-admin 模块的插件存在,通过增添 pom 依赖来控制插件是否开启

image.png

  • ruoyi-quartz 主要用作定时任务,集成了分布式定时任务调度框架 quartz ,目录与ruoyi-generator类似,也是作为 ruoyi-admin 模块的插件存在,通过增添 pom 依赖来控制插件是否开启
  • ruoyi-system 包含后台系统中非核心用户、角色、菜单、字典类实体对象之外的 mapper、service 层功能代码

image.png

ruoyi-admin 用作后台web服务,包含后台系统的 controlelr 层代码以及配置文件。也是整个 RuoYi 项目后台的启动入口

image.png

  • ruoyi-xxxxxx 作为由开发人员引入的其他模块,一般是新业务模块代码

最后再列出项目 ruoyi-admin 的模块依赖图,简单讲解下各个模块间的依赖关系

image.png

  • ruoyi-common 基础通用模块
  • ruoyi-system依赖ruoyi-common模块
  • ruoyi-framework依赖ruoyi-system模块
  • ruoyi-generator依赖ruoyi-common模块
  • ruoyi-quartz依赖ruoyi-common模块
  • ruoyi-admin依赖ruoyi-frameworkruoyi-generatorruoyi-quartz

看完了 RuoYi 的项目结构与模块依赖关系,大家可以看看自己日常开发业务后台的项目结构。或多或少,大家都可能遇到过那种一把梭所以代码都全部放在同一个 Maven 模块的项目。对比 RuoYi 的项目结构,相信大家都会觉得多模块设计是比单模块更优的设计。

拆分出ruoyi-common模块后,其他插件模块可以只引用ruoyi-common的通用代码就能完成插件功能开发。拆分出ruoyi-framework模块后,项目中的核心配置代码全部放在ruoyi-framework中与ruoyi-admin分离,防止对ruoyi-admin的修改影响到项目核心配置。博主认为合理的模块拆分可以减少模块间的耦合与改动模块所带来的影响范围。

通过多模块设计将项目划分成 common -> system -> framework -> admin 由低到高的核心模块以及插件形式的 common -> ruoyi-generator|ruoyi-quartz 模块。模块之间尽量松耦合,方便模块升级、增减模块。

三、优雅的操作日志记录

在 RuoYi 项目中通过 com.ruoyi.framework.aspectj.LogAspect 日志切面,以自定义日志注解作为切点来记录日志信息,这样可以避免在接口中进行重复的操作日志记录代码编写,以及日志记录发生异常也不影响接口返回。

自定义日志注解如下:

/**  
* 自定义操作日志记录注解  
*  
* @author ruoyi  
*/  
@Target({ ElementType.PARAMETER, ElementType.METHOD })  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface Log {  
    /**  
    * 模块  
    */  
    public String title() default "";  
    /**  
    * 功能  
    */  
    public BusinessType businessType() default BusinessType.OTHER;  
    /**  
    * 操作人类别  
    */  
    public OperatorType operatorType() default OperatorType.MANAGE;  
    /**  
    * 是否保存请求的参数  
    */  
    public boolean isSaveRequestData() default true;  
    /**  
    * 是否保存响应的参数  
    */  
    public boolean isSaveResponseData() default true;  
    /**  
    * 排除指定的请求参数  
    */  
    public String[] excludeParamNames() default {};  
}

可以看到 LogAspect 注解类中定义了模块名称、业务操作类型(新增、修改、删除、导出等业务操作)、操作人类别(其他、后台、手机等)、是否保存请求的参数、是否保存响应的参数、排除指定的请求参数等六个属性。我们在使用自定义注解时,通常只用根据接口作用指定模块名称和业务操作类型就可以,日志注解使用如下:

@Log(title = "参数管理", businessType = BusinessType.INSERT)  
@PostMapping("/add")  
@ResponseBody  
public AjaxResult addSave(@Validated SysConfig config) {...}

自定义日志注解切面代码如下:

/**  
* 操作日志记录处理  
*  
* @author ruoyi  
*/  
@Aspect  
@Component  
public class LogAspect {  
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);  
    /** 排除敏感属性字段 */  
    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword" ... };  
    /** 计算操作消耗时间 */  
    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");  
    /**  
    * 处理请求前执行  
    */  
    @Before(value = "@annotation(controllerLog)")  
    public void boBefore(JoinPoint joinPoint, Log controllerLog) {  
    TIME_THREADLOCAL.set(System.currentTimeMillis());  
    }  
    /**  
    * 处理完请求后执行  
    *  
    * @param joinPoint 切点  
    */  
    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")  
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {  
    handleLog(joinPoint, controllerLog, null, jsonResult);  
    }  
    /**  
    * 拦截异常操作  
    *  
    * @param joinPoint 切点  
    * @param e 异常  
    */  
    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")  
    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {  
    handleLog(joinPoint, controllerLog, e, null);  
    }  
    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, 
        final Exception e, Object jsonResult)  
        ...
    } 
}

通过 aop 切面对使用了日志注解的方法进行三个方面的切入:

  • @Before(value = "@annotation(controllerLog)") 处理请求前执行记录日志记录开始时间
  • @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") 处理完请求后执行记录日志结束时间,填充操作日志最后异步插入
  • @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") 以及处理完请求发生异常后执行记录日志结束时间,填充操作日志、异常原因最后异步插入日志

在使用了日志切面后,操作日志记录的逻辑与后台各功能接口的业务逻辑相分离,减少了日志记录代码的的重复编写,后期修改日志记录逻辑只用修改切面代码,提高了操作日志记录的可维护性,也避免了日志记录发生异常时影响业务接口,使用线程池插入日志记录还可以缩短接口响应时长。可以看到通过切面完成日志记录有这么多好处。

其实 RuoYi 中不仅仅只有日志记录使用了切面处理,像是日常开发中数据过滤权限、多数据源切换等也都使用了切面处理。使用切面可以让我们集中处理单一逻辑、方便增添关注点、减少重复代码、对控制层零侵入性以及提高可维护性

四、总结

本文目前从模块设计、操作日志记录等两个方面对 RuoYi 项目进行了讲解。如果大家也使用过 RuoYi 项目,欢迎大家讨论发言给出想法,最后希望本文对大家日常项目开发有所帮助,喜欢的朋友们可以点赞加关注😘。

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
目录
相关文章
|
Android开发 Kotlin JavaScript
Compose 为什么可以跨平台?
Compose 为什么可以跨平台?
880 0
Compose 为什么可以跨平台?
|
存储 JSON 数据格式
UCB Data100:数据科学的原理和技巧:第一章到第五章
UCB Data100:数据科学的原理和技巧:第一章到第五章
532 0
UCB Data100:数据科学的原理和技巧:第一章到第五章
|
Cloud Native 持续交付 测试技术
ALPD——驱动业务创新的精益产品开发
ALPD——驱动业务创新的精益产品开发
7200 0
ALPD——驱动业务创新的精益产品开发
|
4月前
|
SQL Java 关系型数据库
Spring事务传播机制:7种姿势教你玩转"事务接力赛"
事务传播机制是Spring框架中用于管理事务行为的重要概念,它决定了在方法调用时事务如何传递与执行。通过7种传播行为,开发者可以灵活控制事务边界,适应不同业务场景。例如:REQUIRED默认加入或新建事务,REQUIRES_NEW独立开启新事务,NESTED支持嵌套回滚等。合理使用传播机制不仅能保障数据一致性,还能提升系统性能与健壮性。掌握这“七种人格”,才能在复杂业务中游刃有余。
|
编解码 人工智能 运维
南加大提出全新通用时间序列基础模型TimeDiT!基于扩散模型创新物理约束机制
 【10月更文挑战第10天】南加大提出TimeDiT模型,创新融合扩散模型与Transformer架构,针对真实世界时间序列数据的复杂性,如多分辨率、缺失值等问题,提供高效解决方案。该模型通过新颖的掩码机制和无微调编辑策略,实现多任务处理及物理知识集成,显著提升预测和异常检测的准确性和鲁棒性。
462 3
|
10月前
|
NoSQL Java 数据库连接
微服务——MongoDB实战演练——技术选型
本节主要介绍技术选型中的两个重要工具:**mongodb-driver** 和 **SpringDataMongoDB**。其中,mongodb-driver 是 MongoDB 官方提供的 Java 驱动包,用于连接和操作 MongoDB 数据库,功能类似 JDBC 驱动。通过官方示例可快速上手。而 SpringDataMongoDB 是 Spring 生态的一员,封装了 mongodb-driver,提供了更简洁的 API,方便开发者在 Spring 环境中操作 MongoDB。两者各有优势,可根据实际需求选择合适的技术方案。
186 2
|
数据安全/隐私保护 数据格式
数据安全必备:三种实用的数据脱敏技术
在数字化时代,数据安全和隐私保护成为了企业和个人关注的焦点。数据脱敏作为一种有效的数据保护手段,能够降低数据泄露的风险,保护用户隐私。本文将介绍三种常见的数据脱敏方案,帮助您在实际工作中选择合适的脱敏技术。
1850 2
阿里云域名注册流程(图文教程很详细)
阿里云域名注册流程,包括阿里云账号注册、阿里云账号实名认证,域名信息模板实名认证、域名名称及后缀选择、域名优惠口令、域名代金券使用详细教程。
5049 0
阿里云域名注册流程(图文教程很详细)
|
SQL JSON Java
json传参到java接口部分参数接收不到
json传参到java接口部分参数接收不到
709 0
json传参到java接口部分参数接收不到
|
自然语言处理 JavaScript 数据可视化
5个值得推荐的Vue后台管理框架
几个优秀好看的 Vue 后台管理框架,每个框架都有自己的特点和优势,开发者可以根据项目需求选择适合的框架。
942 0