百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

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

toyiye 2024-06-23 18:51 12 浏览 0 评论

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

?

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

?

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

  • RuoYi 仓库地址:https://gitee.com/y_project/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 响应结果、分页参数、文本处理等一众基础类
  • 「ruoyi-framework」 是整个项目的核心模块,因为这里面有整个项目的核心配置代码,全部在 config 目录下 其中 ShiroConfig 是最核心的配置,整合了 shiro 框架,给项目提供了权限管理功能
  • 「ruoyi-generator」 主要用作代码生成,目包含一个对外提供服务模块所需的 contrller、domain、mapper、service、util、config 等包。如果添加 Spring Boot 启动类就可以直接作为独立项目启动。作为 ruoyi-admin 模块的插件存在,通过增添 pom 依赖来控制插件是否开启
  • 「ruoyi-quartz」 主要用作定时任务,集成了分布式定时任务调度框架 quartz ,目录与「ruoyi-generator」类似,也是作为 ruoyi-admin 模块的插件存在,通过增添 pom 依赖来控制插件是否开启
  • 「ruoyi-system」 包含后台系统中非核心用户、角色、菜单、字典类实体对象之外的 mapper、service 层功能代码
  • 「ruoyi-admin」 用作后台web服务,包含后台系统的 controlelr 层代码以及配置文件。也是整个 RuoYi 项目后台的启动入口
  • 「ruoyi-xxxxxx」 作为由开发人员引入的其他模块,一般是新业务模块代码


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

  • 「ruoyi-common」 基础通用模块
  • 「ruoyi-system」依赖「ruoyi-common」模块
  • 「ruoyi-framework」依赖「ruoyi-system」模块
  • 「ruoyi-generator」依赖「ruoyi-common」模块
  • 「ruoyi-quartz」依赖「ruoyi-common」模块
  • 「ruoyi-admin」依赖「ruoyi-framework」「ruoyi-generator」「ruoyi-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 项目,欢迎大家讨论发言给出想法,最后希望本文对大家日常项目开发有所帮助,喜欢的朋友们可以点赞加关注。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码