前言:vscode中vue代码没有高亮显示,可以下载vetur插件解决,ctrl+点击无法跳转函数定义问题,可以下载vue-helper插件解决;idea中ctrl+点击函数即可跳转函数定义。
一、登录
1.生成验证码
基本思路:
后端生成一个表达式,1+1=?@2,
将1+1=?转换成流,生成图片,传给前端,
答案2存入redis
vue获取图片的请求:http://localhost:81/dev-api/captchaImage
请求的是后端还是前端?链接端口号是81,前端的端口号,因此请求的是前端;
反向代理,url请求前端,进行代理,映射到后端,解决跨域问题。
前后端端口号不一样,所以前后端交互存在跨域问题,前端通过反向代理方式解决跨域问题。
url端口号还是前端端口号,所以不存在跨域问题,利用代理映射到后端端口号,巧妙解决跨域,看起来是在请求前端,但实际上是在请求后端。
/dev-api 替换成' ' 再映射到 http://localhost:8080
最终请求为 http://localhost:8080/captchaImage
前端发起请求===>后端查询数据库sys_config表,查看是否开启了验证码,若是没有开启直接跳过生成验证码图片这一步===>生成uuid以及redis的key值===>验证码类型为math,则生成表达式,将式子转换成图片===>将答案存入redis数据库===>将图片和uuid返回给前端===>前端将图片显示在页面上,并将uuid存入表单。
2.登录的具体流程
后端:
- 校验验证码
- 校验用户名和密码
- 生成token
使用异步任务管理器,结合线程池,实现了异步的操作日志记录,和业务逻辑实现异步解耦合。
3. getInfo
获取当前用户的角色和权限信息,存储到VueX中;
写在ruoyi-ui目录中的permission.js文件中的router.beforeEach方法中,和login请求绑定在一起,发送login请求时,也会发送getinfo请求;另外,前端页面进行跳转时也会进到router.beforeEach这个方法中,发送getinfo请求。
4. getRouters
根据当前用户的权限获取动态路由
二、用户管理
流程:加载vue页面===>请求后台数据
1. getlist
(1)startPage()
pagehelper中的reasonable对参数进行逻辑处理,保证参数的正确性
(2)userService.selectUserList(user);
注解@DataScope(deptAlias = "d", userAlias = "u")
给表设置别名,表sys_dept的别名为d, 表sys_user的别名为u
2.deptTree
①查出所有的部门数据
②组装成树状结构
buildDeptTreeSelect:将10条记录组装成一个树状图
三、添加数据
reset()重置表单
getUser获取角色和部门信息
后端 user 业务逻辑
四、修改数据
这里的getUser方法除了要获取所有岗位和角色信息之外,还要获取当前用户已经拥有的岗位和角色。
先删除再新增
结合上两张图片中的代码,总结数据库操作:
1.修改user
2.重新维护user_post和user_role
五、异步任务管理器
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
通过异步任务管理器记录登录日志
1.AsyncManager.me()获取一个AsyncManager对象
2.执行execute方法,执行任务,传入的是一个Task对象,实现了runnable接口,表示它是一个任务,由线程Thread去执行。
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);
}
};
}
封装了登录用户的信息,执行添加操作,这里不会执行,而是将任务交给线程对象来执行。
异步任务管理器,内部定义了一个线程池,然后根据业务创建添加日志的任务,交给线程池来处理,这样做到日志和业务的抽象,解耦合,日志全部统一处理。
六、代码自动生成
根据自己创建的数据表,可以自动生成增删改查的所有前后端代码。
1.创建数据表
use ry_vue;
create table test_user(
id int primary key auto_increment,
name varchar(11),
password varchar(11)
);
2.系统工具===>代码生成
3.导入后,点击编辑
前端类型后来改成vue2版本了,vue3时前端test页面不显示,猜测是框架不匹配
4.点击生成代码
5.解压
main(java后端代码)
vue(Vue前端代码)
sql(菜单sql语句)
6.导入代码,重启项目
进入main目录下,复制java和resource目录,粘贴到ruoyi-vue项目的ruoyi-admin目录下的main目录中;
前端同样粘贴完成。
重启项目:前端执行npm run dev;后端重新构建后,运行RuoYiApplication.java