博主是在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 目录下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基础通用模块undefinedruoyi-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 TIME_THREADLOCAL = new NamedThreadLocal("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 项目。
关键词:
-
当前聚焦:项目讲解之火爆全网的开源后台管理系统RuoYi
博主是在2018年中就接触了RuoYi项目这个项目,对于当时国内的开源后台管理系统来说,RuoYi算是一个完成度较高,易读易懂、界面简洁美观的前后
-
应用数据可跨系统迁移?细数“互传联盟”成功之路
随着手机行业的快速发展,当今各家手机品牌可谓是“乱花渐欲迷人眼”。在任君挑选的市场竞争下,不少消费者纷纷有了换机的欲望与
-
俄总统特别助理将于9日与伊朗最高国家安全委员会秘书举行会谈 简讯
当地时间7日晚,俄罗斯总统普京特别助理伊戈尔·列维京抵达伊朗首都德黑兰。他将于当地时间9日与伊朗最高国家安全委员会秘书阿
-
战神4斧头技能推荐 战神4斧头技能推荐
在战神4的游戏过程中,奎爷能通过学习技能来增加战斗招式。然后游戏中的技能数量较多,很多玩家不了解哪些技能好用。所以今天小编就给大家准备
-
北京证券交易所:已初步形成全链条服务专精特新企业市场体系_全球快讯
北京证券交易所:已初步形成全链条服务专精特新企业市场体系
-
天天新消息丨和生活爱辽宁app下载安装安卓(和生活爱辽宁app老版本下载)
和生活爱辽宁对的积分怎么查看订单1 在手机上找到并打开“中国移动”应用,如果未安装可到AppStore搜索下载安装。2 在中国移动界面,选择右下
-
倍轻松:对2023年全年经营情况抱有积极预期
倍轻松近期接受投资者调研时称,展望2023年,公司同样对全年经营情况抱有积极的预期,在此情况下,公司将积极地在渠道、产品
-
焦点快播:权益基金走马灯换股效果迥异 踩准节奏成黑马 踩错节奏引质疑
【权益基金走马灯换股效果迥异踩准节奏成黑马踩错节奏引质疑】近期公募基金2022年年报披露完毕,在全盘曝光隐形重仓股同时,基金的换手率也连
-
valorant瓦罗兰特下载完打不开/进不去/启动失败/无法启动解决 快播
瓦罗兰特开启预约之后,很多玩家都表示非常期待。有部分玩家担心游戏时会遇到valorant瓦罗兰特下载完打不开 进不去 游戏启动失败 无法启动的情
-
焦点访谈丨直播带岗“职”等你来
直播带货,您一定知道,那您听说过直播带岗吗?最近,直播带岗这种新的数字化招聘方式蓬勃兴起,迅速成为一个重要的招聘渠道。从蓝领群体到高
-
焦点热门:透视医药集采成效:累计降低药耗费用超4000亿元
App4月8日消息,第八批国家组织药品集采日前在海南开标。从2019年“4+7”集采试点扩围开始,截至目前,国家已经开展8批333种药品、3批4类高值
-
安旭生物(688075)4月7日主力资金净买入1066.69万元
截至2023年4月7日收盘,安旭生物(688075)报收于82 24元,上涨4 33%,换手率4 49%,成交量1 01万手,成交额8199 66万元。
-
世界微动态丨excel自动减去出库_excel自动减库存
1、=SUMPRODUCT((MOD(COLUMN(D1:K1),2)=0)*(D1:K1))-SUMPRODUCT((
-
ati radeon hd 5450现在还能用吗_ati radeon hd 5450
1、老一代显卡适用类型台式机核心代号CedarPro制造工艺40nm核心频率650MHz显存类型支持DDR2
-
陈韪简介_陈韪
1、【典故】汉朝末年(东汉),北海地方出了一个很博学的人,名叫孔融,宇文举,是孔子的二十世孙。2、他从小就很聪明,尤
-
全球热门:派出所门口意外落水,民警心肺复苏紧急救援
“救我女儿的民警不肯告诉我他叫什么,他瘦瘦高高的,我要当面感谢他。”
-
大观云南 | 文化云南之精巧的编制工艺|今日看点
编者按:彩云之南,这里有丰富的自然资源,这里有绚丽的民族文化;这里山清水秀,这里美食如云;这里多姿多彩,这里蔚然大观。文旅头条新闻网
-
讯息:第一批上海市级乡村旅游重点村,松江、奉贤、浦东这些地方上榜!
上海乡村是超大城市的稀缺资源,是城市核心功能的重要承载地,是提升城市能级和核心竞争力的战略空间。为助力全面推进乡村振兴战略,深入实施
-
招商蛇口完成发行10亿短期融资券 利率2.2%
债券简称23招商蛇口SCP004,发行金额为10亿元,息期利率为2 2%,发行期限为90天。
-
铜仁石阡:制清明美食 品春的味道|焦点热议
铜仁石阡:制清明美食品春的味道