
[Java]RouYi从入门到开发
若依(RouYi)是一款基于JavaEE技术的企业级快速开发平台, 让开发者用少量代码,快速搭建和开发各种管理系统开发版本RuoYi-Vueruoyi-vue版本,采用了前后端分离的单体架构设计官网。
背景介绍
若依(RouYi)是一款基于JavaEE技术的企业级快速开发平台, 让开发者用少量代码,快速搭建和开发各种管理系统
开发版本
RuoYi-Vue
ruoyi-vue版本,采用了前后端分离的单体架构设计
软件环境:jdk, mysql, redis, maven, node
技术选型:springboot, springsecurity, mybatis, jwt, vue3, element-plus
代码下载:RuoYi-Vue: 🎉 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本
扩展地址:RuoYi-Vue3: 🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
其他低代码
若依搭建
搭建后端项目
1.通过idea下载代码
代码下载完成后, idea会自动加载`Maven`依赖包,初次加载会比较慢
说明: 模块文件加粗, 证明包加载完毕
说明: 如果包下载失败, 可以先清理, 在重新下载
2.导入SQL与配置
- 创建数据库`create database ry-vue;`
- 执行sql脚本文件
- 在`ruoyi-admin`模块下,修改数据库连接,编辑`application-druid.yml`配置
- 如果Redis有密码, 修改application.yml配置
3.启动Redis
- 启动Redis: redis-server.exe redis.windows.conf
4.启动项目
- 启动项目: 运行`com.ruoyi.RuoYiApplication.java`
搭建前端项目
1.下载项目
2.安装依赖
3.运行项目
入门案例
1.分析原型
- 查看原型确定需求
- 分析需要的接口, 这里需要5个接口: 条件查询接口,添加接口, 编辑接口, 删除接口,详情接口(回显)
2.建表
- 根据原型, 确定表结构
- 建表: 执行资料中的 [课程管理] SQL文件
- 检查表结构
3.配置代码生成信息
4.下载代码并导入到项目
功能详解
权限控制
1.介绍
若依内置了强大的权限控制系统, 为企业级项目提供了通用的解决方案
RBAC(基于角色的访问控制)是一种广泛使用的访问控制模型, 通过角色来分配和管理用户的菜单权限
2.表关系说明
- 通过三种主表, 加两张中间表就可以实现RBAC
- 若依为了实现更精细的权限控制, 所以提供了更多的数据表, 以实现不同角色查看相同页面, 但是数据不同的精细控制
3.实际操作
创建菜单
创建角色,并分配权限
创建用户,并关键角色
登录验证
数据字典
1.介绍
若依内置的数据字典, 用于维护系统中常见的静态数据, 如性别, 状态....
优势: 提高数据库存储效率, 提高程序灵活性
2.表关系说明
3.实际操作
目标: 把课程管理的学科字段改为数据字典维护
其他功能
1.参数配置
对系统中的参数进行动态维护, 实现在不更改代码的情况下, 控制系统中的功能
控制登录验证码
- 修改后, 无需改动代码, 立刻生效
控制注册页面
- 更改后, 需要在前端登录页, 显示注册按钮
2.通知公告
促进组织内部信息的传递
- 若依的通知功能是一个半成品, 因为通知这个业务, 每个公司需要的形式都不一样, 所以需要自己二次开发
- 常见的通知形式有消息弹窗, 邮箱通知等
3.日志管理
轻松追踪用户行为和系统运行的状况
操作日志
登录日志
- 日志随着时间的积累, 数据会越来越多, 如果需要, 可以考虑通过定时任务, 定期导出日志, 然后清理数据
系统监控
若依提供了强大的监控工具, 帮助开发和运维快速了解系统的性能状态
- 数据监控是druid提供的功能, 所以需要二次登录, 才可以使用
定时任务
若依为定时任务功能提供了友好方便的web界面, 实现动态管理任务
1.创建任务类
- 添加完成后要重启服务
2.添加任务规则
- 执行策略: 如果系统宕机, 定时任务会累积, 服务恢复后, 这些任务如何处理
- 是否并发: 多个定时任务, 允许并发性能更好, 禁止并发可以保证任务的执行顺序不变
3.启动任务
表单构建
表单构建工具, 只需要开发者通过图形界面和拖拽等操作, 就可以快速构建复杂的表单
1.制作表单并导出
- 默认会提供提交和重置按钮
2.复制到前端工程
3.创建动态菜单
代码生成
代码生成器:根据数据库表结构自动生成前后端的CRUD代码, 提供三种生成模板
- 单表:入门案例中使用的就是单表模式
- 树表:是一种展示层级数据的表格,能展开折叠, 清晰的呈现父子关系,便于管理
- 主子表:一对多的表关系,后面再讲
系统接口
Swagger, 能够自动生成API的同步在线文档,并提供Web界面进行接口调用和测试
接口文档
准备工作
接口接口
项目结构
后端部分
1.后台服务
2.通用工具
3.框架核心
3.系统模块
4.模块依赖关系
前端部分
表结构
整个ruoyi系统共有32张表. 我们需要熟悉的是下面的19张表
源码阅读
前端代码分析
全局处理code
工具方法
import useDictStore from '@/store/modules/dict'
import { getDicts } from '@/api/system/dict/data'
/**
* 获取字典数据
*/
export function useDict(...args) {
const res = ref({});
return (() => {
args.forEach((dictType, index) => {
res.value[dictType] = [];
const dicts = useDictStore().getDict(dictType);
if (dicts) {
// 仓库中有数据,直接使用
res.value[dictType] = dicts;
} else {
// 仓库中没有数据,请求数据
getDicts(dictType).then(resp => {
res.value[dictType] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass }))
useDictStore().setDict(dictType, res.value[dictType]);
})
}
})
return toRefs(res.value);
})()
}
页面文件
<template>
<el-table>
<el-table-column label="课程学科" align="center" prop="subject">
<template #default="scope">
<!-- 使用字典组件 -->
<dict-tag :options="coures_subject" :value="scope.row.subject"/>
</template>
</el-table-column>
</el-table>
</template>
<script setup name="Course">
// 拿到字典数据
const { proxy } = getCurrentInstance();
const { coures_subject } = proxy.useDict('coures_subject');
</script>
字典组件
<template>
<div>
<template v-for="(item, index) in options">
<!-- 匹配成功 -->
<template v-if="values.includes(item.value)">
<!-- 使用span展示 -->
<span
v-if="(item.elTagType == 'default' || item.elTagType == '') && (item.elTagClass == '' || item.elTagClass == null)"
:key="item.value"
:index="index"
:class="item.elTagClass"
>{{ item.label + " " }}</span>
<!-- 使用el-tag展示 -->
<el-tag
v-else
:disable-transitions="true"
:key="item.value + ''"
:index="index"
:type="item.elTagType === 'primary' ? '' : item.elTagType"
:class="item.elTagClass"
>{{ item.label + " " }}</el-tag>
</template>
</template>
<!-- 匹配失败 -->
<template v-if="unmatch && showValue">
{{ unmatchArray | handleArray }}
</template>
</div>
</template>
<script setup>
// 记录未匹配的项
const unmatchArray = ref([]);
const props = defineProps({
// 数据
options: {
type: Array,
default: null,
},
// 当前的值
value: [Number, String, Array],
// 当未找到匹配的数据时,显示value
showValue: {
type: Boolean,
default: true,
},
// 分隔符
separator: {
type: String,
default: ",",
}
});
/**
* 作用: 基于props.value计算出一个数组
* 如果props.value是数组,则直接返回其映射(每个项转换为字符串);
* 如果是字符串,则使用props.separator作为分隔符将其分割成数组;
*/
const values = computed(() => {
// 非空拦截
if (props.value === null || typeof props.value === 'undefined' || props.value === '') return [];
// 数组或字符串
return Array.isArray(props.value) ? props.value.map(item => '' + item) : String(props.value).split(props.separator);
});
/**
* 作用: 用于判断并收集未匹配的项。
* 遍历values中的每个项,检查是否在props.options中有对应的数据
* 如果没有找到匹配项,则将其添加到unmatchArray中,并设置标志变量unmatch为true。
*/
const unmatch = computed(() => {
unmatchArray.value = [];
// 没有value不显示
if (props.value === null || typeof props.value === 'undefined' || props.value === '' || props.options.length === 0) return false
// 传入值为数组
let unmatch = false // 添加一个标志来判断是否有未匹配项
values.value.forEach(item => {
if (!props.options.some(v => v.value === item)) {
unmatchArray.value.push(item)
unmatch = true // 如果有未匹配项,将标志设置为true
}
})
return unmatch // 返回标志的值
});
/**
* 生成字符串
*/
function handleArray(array) {
// 非空拦截
if (array.length === 0) return "";
// 拼接未匹配的数据
return array.reduce((pre, cur) => {
return pre + " " + cur;
});
}
</script>
<style scoped>
.el-tag + .el-tag {
margin-left: 10px;
}
</style>
后端代码分析
1.BaseController介绍
BaseController: web层通用数据处理, 供controller使用
2.注解介绍
记录用户的操作日志: @Log(title = "课程管理", businessType = BusinessType.UPDATE)
权限控制的注解: @PreAuthorize("@ss.hasPermi('course:course:edit')")
它在方法运行前先验证权限, 权限够放行, 不够就拦截
3.分页查询接口介绍
4.非分页查询接口介绍
5.BaseEntity
所有实体类都继承BaseEntity实体基类
前后端交互流程
1.接口文档: 前后端基于接口文档实现数据交互
2.前端请求流程
3,后端响应数据
二次开发
新建业务模块
1.改名
若依框架修改器是一个可以一键修改RouYi包名和项目名的工具
地址: https://gitee.com/lpf_project/RouYi-MT/releases
1.压缩工程
2.运行修改器
3.配置参数
4.开始执行
5.打开新工程
6.修改启动类文件
2.新建sky-merchant子模块
3.父工程版本锁定
4.sky-admin添加依赖
5.验证一下, 运行项目
菜品管理
利用若依代码生成器(主子表模版), 生成菜品管理的前后端代码
1.准备SQL并导入数据库
2.配置代码生产信息
准备工作
配置菜品管理表
配置菜品口味表
- 其他两项不做调整
3.下载代码并导入到项目
- 如果导入后端文件保存, 可以手动导入依赖包 ctrl + enter
列表调整
1.安装ai助手
- 建议: 先解释代码, 再生成代码
2.页面改造
3.修复图片回显
原因:
- 本地图片需要拼接地址前缀, 完成图片预览
- 对于阿里云oss图片来说, 会重复拼接
- 多添加一个过滤条件就OK了
口味改造
改造效果
代码展示
<template>
....
<el-table-column label="口味名称" prop="name" width="150">
<template #default="scope">
<el-select v-model="scope.row.name" placeholder="请选择口味名称" @change="changeFlavorName(scope.row)">
<el-option
v-for="dishFlavor in dishFlavorListSelect"
:label="dishFlavor.name"
:value="dishFlavor.name"
:key="dishFlavor.name"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="口味列表" prop="value" width="350">
<template #default="scope">
<el-select v-model="scope.row.value" placeholder="请输入口味列表" multiple
@focus="focusFlavorValue(scope.row)" style="width: 90%;">
<el-option
v-for="value in checkValueList"
:label="value"
:value="value"
:key="value"
/>
</el-select>
</template>
</el-table-column>
...
</template>
<script setup name="Dish">
/** 修改按钮操作 */
function handleUpdate(row) {
...
// 将口味列表的value字符串转数组
if(dishFlavorList.value) {
dishFlavorList.value.forEach(item => {
item.value = JSON.parse(item.value)
});
}
}
/** 提交按钮 */
function submitForm() {
...
// 将口味列表的value数据转字符串
if(form.value.dishFlavorList) {
form.value.dishFlavorList.forEach(item => {
item.value = JSON.stringify(item.value)
});
}
}
// -------------------------------------------------------
// 定义口味名称和口味列表静态数据
const dishFlavorListSelect = ref([
{name: '辣度',value: ["不辣","微辣","中辣","特辣"]},
{name: '忌口',value: ["不要葱","不要蒜","不要香菜","不要辣"]},
{name: '甜味',value: ["无糖","少糖","半糖","多糖"]},
]);
// 储存当前选中口味列表的数组
const checkValueList = ref([]);
// 口味名称改变时更新口味列表
function changeFlavorName(row) {
// 清空当前行
row.value = []
// 根据选择的nane查找数据的value
checkValueList.value = dishFlavorListSelect.value.find(item => item.name == row.name).value;
}
// 口味列表获取焦点时更新选中的口味
function focusFlavorValue(row) {
// 根据选择的nane查找数据的value
checkValueList.value = dishFlavorListSelect.value.find(item => item.name == row.name).value;
}
</script>
页面调整
- 浏览器标签页icon, 标题修改
- 系统页面中的logo, 标题修改
- 去除源码和文档链接
- 修改主题和自定义图标
- 登录阿里图标库, 搜索需要的图标
- 点击下载
- 调整颜色和尺寸, 点击SVG下载
- 嵌入到前端工程, 刷新页面, 重新选择
- 登录页的标题和背景图修改
更多推荐
所有评论(0)