若依学习笔记
# 若依(前后端分离版)
# 如何快速上手开源项目?
先看前端,再看后端
打开浏览器,检查网络,粘贴请求的路径
看前端代码
到后端代码 按 全局文件搜索:crtl + shift + f 该路径,快速找到对应代码
# 文件结构
# 后端结构
com.ruoyi
├── common // 工具类
│ └── annotation // 自定义注解
│ └── config // 全局配置
│ └── constant // 通用常量
│ └── core // 核心控制
│ └── enums // 通用枚举
│ └── exception // 通用异常
│ └── filter // 过滤器处理
│ └── utils // 通用类处理
├── framework // 框架核心
│ └── aspectj // 注解实现
│ └── config // 系统配置
│ └── datasource // 数据权限
│ └── interceptor // 拦截器
│ └── manager // 异步处理
│ └── security // 权限控制
│ └── web // 前端控制
├── ruoyi-generator // 代码生成(可移除)
├── ruoyi-quartz // 定时任务(可移除)
├── ruoyi-system // 系统代码
├── ruoyi-admin // 后台服务
├── ruoyi-xxxxxx // 其他模块
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 前端结构
├── build // 构建相关
├── bin // 执行脚本
├── public // 公共文件
│ ├── favicon.ico // favicon图标
│ └── index.html // html模板
│ └── robots.txt // 反爬虫
├── src // 源代码
│ ├── api // 所有请求
│ ├── assets // 主题 字体等静态资源
│ ├── components // 全局公用组件
│ ├── directive // 全局指令
│ ├── layout // 布局
│ ├── plugins // 通用方法
│ ├── router // 路由
│ ├── store // 全局 store管理
│ ├── utils // 全局公用方法
│ ├── views // view
│ ├── App.vue // 入口页面
│ ├── main.js // 入口 加载组件 初始化等
│ ├── permission.js // 权限管理
│ └── settings.js // 系统配置
├── .editorconfig // 编码格式
├── .env.development // 开发环境配置
├── .env.production // 生产环境配置
├── .env.staging // 测试环境配置
├── .eslintignore // 忽略语法检查
├── .eslintrc.js // eslint 配置项
├── .gitignore // git 忽略项
├── babel.config.js // babel.config.js
├── package.json // package.json
└── vue.config.js // vue.config.js
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 1.1 什么是若依?
开源项目,学习开源项目的目标:
1、用,减少自己的工作量
2、学习优秀开源项目底层的编程思想,设计思路,提高自己的编程能力
官方文档:[介绍 | RuoYi (opens new window)](http://doc.ruoyi.vip/ruoyi-vue/)
更系统的学习,建议看官方文档
基础:Spring Boot + Vue
环境要求:
1、JDK 1.8+
2、MySQL
3、Redis
4、Maven
5、Vue
# 1.2 使用若依
使用开源项目的步骤:
1、下载并运行
2、看懂业务流程
3、进行二次开发
去官网下载源代码
配置数据库 MySQL、Reids
本地执行 SQL 脚本
在工程中配置数据库 -- application-druid.yml 文件中修改
Redis 配置
启动前端:
1、安装依赖 npm install
2、启动 npm run dev
# 1.3 登录
# 1.3.1 生成验证码
基本思路
后端生成一个表达式,1+1=2
1+1=?@2
1+1=? 转成图片,传到前端进行展示
2 (答案)存入 Reids
前端
http://localhost/dev-api/captchaImage (opens new window) (opens new window)前端
页面信息都在 views 文件夹里面
Vue 获取图片,前端还是后端? -- 后端
反向代理,url 请求前端,进行代理,映射到后端,解决跨越问题
/dev-api 替换成'' 再映射到
http://localhost:8080
2
3
http://localhost:8080/captchaImage
后端
到后端代码 按 全局文件搜索:crtl + shift + f
该路径,快速找到对应代码
# 1.3.2 登录的具体流程
后端:
1、校验验证码
2、校验用户名和密码
3、生成 Token
使用异步任务管理器,结合线程池,实现了异步的操作
日志记录,和业务逻辑实现异步解耦合。
# 1.3.3 getInfo
获取当前用户的角色和权限信息,存储到 Vuex 中
*
是通配符,模块:菜单:功能
// spring security 里面的东西
// 代表所有权限
*:*:*
2
3
后端相应代码
# 1.3.4 getRouters
根据当前用户的权限获取动态路由,不同权限的用户,展现的菜单不一样
parent_id 为 0 的是最高级菜单,其他为子菜单
先查询出的是父节点菜单,子菜单包含在 children 里。
# 1.4 用户管理
流程:加载 Vue 页面 -》请求后台数据
1、getList -- 加载用户管理列表
1.1、startPage() -- 分页
PageHelper 中的 reasonable 对参数进行逻辑处理,保证参数的正确性,
当 pageNum = 0/-1 时,自动填写 pageNum = 1
1.2、userService.selectUserList(user);
注解 @DataScope(deptAlias = "d", userAlias = "u")
给表设置别名的,sys_dept d,sys_user u
2、treeselect -- 加载左边的树状图列表
(1)查出所有的部门数据
(2)组装成树状结构
buildDeptTreeSelect:将 10 条记录组装成一个树状图
recursionFn(depts, dept);
2.1、先找到顶级节点,找到它的子节点
2.2、遍历顶级节点的子节点,再找到它的子节点
点击树状图中的数据
# 1.5 添加数据
前端 -- 添加的方法
reset 是表单重置
getTreeselect 获取部门树状图
getUser 获取角色和部门信息
后端 -- User 业务
插入用户的方法包含插入三张表,目的是增添关联表的记录
# 1.6 修改数据
这里的 getUser 方法除了要获取所有的岗位和角色信息之外,还要获取当前用户已经拥有的岗位和角色。
数据库:
1、修改 user
2、重新维护 user_post 和 user_role
修改的逻辑是:先删后增
这样子更加安全,不用判断是否存在
# 1.7 删除数据
做判断,不能删除当前用户,并使用注解记录删除操作的日志信息到数据库中
# 1.8 异步任务管理器
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN\_FAIL, MessageUtils.message("user.password.not.match")));
通过异步任务管理器记录登录日志
1、AsyncManager.me() 获取一个 AsycnManager 对象
2、执行 execute 方法,执行任务,传入的是一个 Task 对象(在异步工厂的类里写),实现了 Runnable 接口,是一个任务,由线程 Thread 去执行
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息
* @param args 列表
* @return 任务task
*/
public static TimerTask recordLogininfor(final String username, final String status, final String message,
final Object... args)
{
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
final String ip = IpUtils.getIpAddr();
return new TimerTask()
{
@Override
public void run()
{
String address = AddressUtils.getRealAddressByIP(ip);
StringBuilder s = new StringBuilder();
s.append(LogUtils.getBlock(ip));
s.append(address);
s.append(LogUtils.getBlock(username));
s.append(LogUtils.getBlock(status));
s.append(LogUtils.getBlock(message));
// 打印信息到日志
sys_user_logger.info(s.toString(), args);
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
// 封装对象
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username);
logininfor.setIpaddr(ip);
logininfor.setLoginLocation(address);
logininfor.setBrowser(browser);
logininfor.setOs(os);
logininfor.setMsg(message);
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus(Constants.SUCCESS);
}
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus(Constants.FAIL);
}
// 插入数据
SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
}
};
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
封装了登录用户的信息,执行添加操作,这里不会执行,而是将任务交给线程对象来执行。
异步任务管理器,内部定义了一个线程池,然后根据业
务创建添加日志的任务,交给线程池来处理,这样做到
日志和业务的抽象,解耦合,日志全部统一处理。
使用线程池有什么用?
提高线程利用率
# 1.9 代码自动生成
# 1、创建数据表
use ruoyi_vue;
create table test_user(
id int primary key auto_increment,
name varchar(11),
password varchar(11)
);
2
3
4
5
6
7
# 2、系统工具 -> 代码生成
# 3、编辑
基本信息
字段信息
生成信息
# 4、点击生成代码
# 5、解压
生成代码后下载压缩包,里面有三个文件:
main(Java 后端代码)
vue(Vue 前端代码)
SQL(菜单 SQL)
# 6、导入代码,重启项目
- 如果后端抛出 404 异常,可能是因为代码刚导进项目,还未被扫描到
- rebuild project,重新启动即可