哪里有永久免费建站,最新域名查询,10元建站,东城区网站建设哈喽~大家好#xff0c;这篇来看看若依前后端分离版#xff0c;快速上手#xff08;肝了挺久的#xff09;。 #x1f947;个人主页#xff1a;个人主页 #x1f948; 系列专栏#xff1a;【Springboot和Vue全栈开发】… 哈喽~大家好这篇来看看若依前后端分离版快速上手肝了挺久的。 个人主页个人主页 系列专栏【Springboot和Vue全栈开发】 与这篇相关的文章 JAVA进程和线程JAVA进程和线程-CSDN博客HttpClient 入门使用示例HttpClient 入门使用示例-CSDN博客Spring Task 快速入门Spring Task 快速入门-CSDN博客 目录
一、前言
1、什么是若依
二、验证码
1、验证码前端实现
2、验证码后端实现
3、反向代理
三、登录后端实现
四、获取用户角色和权限
1、getInfo前端实现
2、getInfo后端实现
五、获取动态菜单路由
1、前端实现
2、后端实现
六、首页数据加载
七、用户数据分页
八、部门树状图
九、添加用户数据
1、回显数据
2、新增操作
十、修改用户信息
十一、删除用户
十二、异步任务管理器
十三、代码自动生成器 一、前言
1、什么是若依 若依框架RuoYi是一套基于Java开发的快速开发框架它提供了许多常用的功能模块和工具包括用户管理、部门管理、角色管理、菜单管理、字典管理、系统监控、定时任务等。若依框架采用了MVCModel-View-Controller的架构模式使用了Spring Boot、MyBatis等流行的开源框架可以帮助开发者快速搭建企业级的后台管理系统。若依框架还提供了许多可视化的操作界面使得开发者可以方便地进行系统配置和管理。 二、验证码
1、验证码前端实现
在运行成功之后前端会自动进入到后台管理系统界面然后发送一个验证码的一个请求“captchaImage”打开前端代码login.vue里面的created方法。 之后执行getCodeImg生成一张图片显示在网页上。
验证码的验证规则是怎样的呢 在后端会直接生成一个表达式例如112那么就会将这个格式转换为 11?2 11? 转成图片传到前端进行展示而将2 存入 Reids里面我们看看后端代码。 2、验证码后端实现
在CaptchaController控制器类中的getCode方法大哥断点这里就显示的将112的格式转为11?2。 然后将key就是verifyKey与value是code还有设置验证码有效期分钟、存储到redis里面前端验证验证码就直接从redis里面进行验证。 3、反向代理
前端代码是80端口后台代码是8080端口但是我们F12打开控制台来查看为什么localhost没有带端口号呢为什么又多了一个dev-api的路径呢 在前端的vue.config.js文件当中这里的作用是反向代理路径重写。 proxy: { // 反向代理8080 - 80// detail: https://cli.vuejs.org/config/#devserver-proxy[process.env.VUE_APP_BASE_API]: {target: http://localhost:8080,changeOrigin: true,pathRewrite: { // 路径重写[^ process.env.VUE_APP_BASE_API]: // 替换为空然后再映射}}},
其中里面有一块是VUE_APP_BASE_API这个开发环境在其后面添加路径为 /dev-api 。 三、登录后端实现 找到login方法首先它会进行验证码校验对当期的用户名进行验证首先先判断验证码是否为空然后转载redis里面拿出键值进行用户输入的验证码与redis取出来的进行对比输入错误抛出异常然后发出一个异步请求来记录登录信息记录打印信息到日志、获取客户端操作系统、获取客户端浏览器、对象然后将数据插入进去。 然后登录前置校验检验用户名或密码为空、密码如果不在指定范围内、IP黑名单校验。
登录操作查询出来用户存在账号与密码都正确然后插入当前用户的操作、记录登录信息、生成token返回给前端。 四、获取用户角色和权限
在输入完正确的用户名、密码、验证码我们可以看到一个名为getInfo的请求。
1、getInfo前端实现 这其实是个全局获取当用户登录之后会立即发送作用是获取当前用户的角色和权限信息并且存储到 Vuex 中这个在permission.js 文件当中。 扩vue中 router.beforeEach() 的作用——router.beforeEach 是全局钩子函数它是在路由跳转之前所调用的函数在实际开发中页面进度条的加载、设置页面标题、判断用户是否已经登录过了等等都可以在该函数中执行。
点击GetInfo进去看看GetInfo是一个方法其作用是获取用户信息。 货到最上面getInfo是来自/api/login文件下的进去看看这里就是发起请求的路径了方式为get。 2、getInfo后端实现
进入到控制层getInfo方法。 getRolePermission查询当前用户的角色信息是管理员add(admin)不是的话去数据库里面查找用户。 getMenuPermission查询用户的权限信息。 如果是管理员就是 *:*:* 获取全部的权限菜单目录按钮,不是的话去数据库里面查找权限。
然后将获取到的user、roles、permissions封装到AjaxResult里面返回给前端。
前端如何解析后端返回的数据呢 在之前的GetInfo方法里面的commit将值存储到vuex里面将信息解析出来渲染到页面上面。 五、获取动态菜单路由
我们看到左边的菜单栏是动态生成的不是直接写死在页面上面不同的用户有不同的权限就有不同的菜单这个是如何实现的呢 1、前端实现
控制台有一个getRouters请求很明显这个就是实现动态菜单的请求了而且这个貌似与上面的getInfo一样是全局路由
打开permission.js文件很明显GenerateRoutes这个就是我们要找的进去看看同样的生成路由从后端获取信息解析。 但是getRouters是在/api/menu目录下的去看看一个发起请求的路径。 2、后端实现
这里猜一下菜单实现的方法是什么——递归我们找的getRouters来看看。 selectMenuTreeAll查找管理员的权限对应的菜单数据。 selectMenuTreeByUserId查找不是管理员的权限对应的菜单数据。 一直追踪selectMenuTreeAll 一直到mapper文件找到sql直接cv到navicat 运行看看啥效果。 其中sys_menu 这张表有menu_id与parent_id这两个就是分辨哪个是哪个的子菜单parent_id为0的就是父菜单最最顶上面的。
将查出来的值menus与00的值就是parentId先查找父菜单传到getChildPerms方法里面。
迭代list里面的值的getParentId如果等于parentId值那就是父菜单。 然后开始递归方法为recursionFn思路一样如果list里面的值的getParentId如果等于parentId值那就是找到了对应的父菜单这样一级一级的组成一个类似链表的一个结构最后返回给控制层一个ListSysMenu类型的数据封装成AjaxResult返回给前端。
前端将AjaxResult一个一个组装成路由字符串转换为组件对象。 六、首页数据加载
登录完成之后会直接进入到首页这个是怎么实现的呢 在handleLogin方法里面当用户登录成功之后直接重定向到“/”。 这个路径对应到哪呢 其实是router里面的index.js文件。 点击进去看看
navbar/ 导航栏
app-main/首页 找到Sidebar文件的index.js里面可以看到有一个v-for这个就是之前的动态菜单后端传来的数据通过循环一个一个渲染到页面上面的。 七、用户数据分页
进入到页面之后我们点击用户管理其中会发送一个list请求加上分页信息pageNum1pageSize10这个是如何实现的呢 找到对应的index文件。 数据在页面加载的时候就出来了这肯定一初始化有关created()方法。 this.getList()获取用户管理数据。 this.getDeptTree()获取旁边的部门信息。 listUser向后端发起请求后端接收。 找到list。 startPage设置请求分页数据。 selectUserList查找用户信息。 getDataTable响应请求分页数据 利用分页插件PageHelper将响应请求分页数据返回给前端。
其中 1、startPage() PageHelper 中的 reasonable 对参数进行逻辑处理保 证参数的正确性 pageNum 0/-1pageNum 1 2、userService.selectUserList(user); 注解 DataScope(deptAlias d, userAlias u) 给表设置别名的sys_dept dsys_user u 八、部门树状图
在前面写到当页面初始化的时候会直接加载三个方法其中getDeptTree就是查出所有的部门数据。 进入user.js里面路径是/system/user/deptTree直接到后端查找。 进入控制层进入到selectDeptTreeList里面看看。 其中selectDeptList方法是查询部门管理数据buildDeptTreeSelect是构建前端所需要下拉树结构将selectDeptList查询出来的结果depts传给buildDeptTreeSelect。 其中buildDeptTree是构建前端所需要树结构里面看到了老面孔——recursionFn逻辑与前面一样如果父节点等于子节点那么子节点就是父节点的子菜单。 recursionFn递归列表。 然后将结果返回给前端前端再解析出来。
九、添加用户数据
1、回显数据
在user/index.vue里面找到新增按钮的方法其中里面有一个名为reset他的作用是在打开的新增表单重置。 然后里面getUser方法点进去很熟悉前面讲过的只是后面加了个参数userId路径为/system/user/userId传给后端。 后端控制层找到方法GetMapping接受无路径与有路径为userId checkUserDataScope校验用户是否有数据权限。 selectRoleAll查询所有角色。 selectPostAll查询所有岗位。 将这些数据回显到页面上去也就是现在我们能看到的归属部门、岗位、角色所选的下拉列表。
然后再根据用户ID查询用户selectUserById然后将数据封装返回给前端。
2、新增操作
将基本信息填写完成之后点击确定按钮数据提交给后端。 通过点击事件找到方法 新增与修改请求路径如下。 控制层先做判断登录账号已存在、手机号码已存在、邮箱账号已存在然后设置登录用户名、对密码进行加密密码默认的是123456。 然后直接向DBsys_user表插入数据。 然后新增用户岗位关联insertUserPost、新增用户与角色管理insertUserRole 其实就是对三张表进行新增操作sys_user、sys_user_post、sys_user_role。 十、修改用户信息
找到修改按钮然后找到对应的点击事件方法——updateUser同样的数据回显查询用户详细数据然后数据回显在页面上这里就不做过多的描述了。 点击确定触发updateUser携带数据到后端路径为/system/user。 点击updateUser进入到业务层发现这个不是和新增操作一样吗对修改的逻辑就是先删除后进行新增操作。 十一、删除用户
找到删除的点击事件——handleDelete路径为/system/user/userId发送给后端后端接收请求。 首先先判断是否为当前正在操作的用户也就是本人本人操作肯定是不能删除的了。 如果没有问题执行业务层然后校验用户是否允许操作checkUserAllowed 结果是 不允许操作超级管理员用户、校验用户是否有数据权限checkUserDataScope 结果是 没有权限访问用户数据、然后删除用户与角色关联deleteUserRole、删除用户与岗位关联deleteUserPost、批量删除用户信息deleteUserByIds。
注意这里的批量删除用户信息不是真的删除而是一个逻辑删除也就是修改他的状态del_flag为2。 十二、异步任务管理器
打开后端找到login的控制层点击login进入到业务层在业务层中有一行这样的代码。 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message(user.password.not.match))); 一看就很高级那么他有什么作用呢 给出结论通过异步任务管理器记录登录日志。 首先AsyncManager进去看看里面有啥一个异步任务管理器。找到me()是个静态方法return 了一个me看看上面 懒汉式单例模式分配异步任务。 那么就是AsyncManager.me() 获取一个 AsycnManager 对象。
然后执行 execute 方法执行任务传入的是一个 Task 对象就是AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message(user.password.not.match)这么大长一段并设置操作延迟10毫秒。 TimerTask实现了TimerTask接口由线程 Thread 去执行。 那么recordLogininfor的作用是记录登录信息将代码cv出来。 /*** 记录登录信息* * 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(){Overridepublic 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);}};}
其实这串代码就是封装了当前登录用户的信息获取客户端操作系统、获取客户端浏览器等然后封装对象。插入数据insertLogininfor。
但是这里不会执行而是将任务交给线程对象来执行这里只是个任务而已。
找到execute方法点击进去然后点击executorexecutor是一个成员变量异步操作任务调度线程池将我们上面封装的对象交给线程池来执行。 敲两下shift键将scheduledExecutorService cv到搜索框中找到scheduledExecutorService的bean。 也就是说AsyncManager 的executor其实就是scheduledExecutorService返回的对象那么ScheduledThreadPoolExecutor就是在创建线程池大小为50corePoolSize。 那么逻辑就是异步任务管理器内部定义了一个线程池然后根据业务创建添加日志的任务交给线程池来处理这样做到日志和业务的抽象解耦合日志全部统一处理。 举个例子用户登录操作将登录的信息存储日志同步的话用户登录请求完成之后等待日志插入请求完成然后再执行用户登录后操作异步的话将插入日志分离了出来这样的话不管是啥操作都可以通过异步任务管理器创建一个任务交给线程池直接去执行就不用我们去管了线程池分配了他线程他就会执行大大提高了效率。 十三、代码自动生成器
首先先创建数据表
create table test_user(
id int primary key auto_increment,
name varchar(11),
password varchar(11)
);
建完之后打开若依运行的web在系统工具里面的代码生成点击导入按钮。 然后编辑基本信息带*号的一定要填。 然后点击生成代码。 将下载好的压缩包解压出来mainJava 后端代码vueVue 前端代码SQL菜单 SQL导入代码重启项目。
注如果后端抛出 404 异常rebuild project重新启动。 效果展示 不积跬步无以至千里趁年轻使劲拼给未来的自己一个交代向着明天更好的自己前进吧 文章转载自: http://www.morning.weiwt.com.gov.cn.weiwt.com http://www.morning.jpfpc.cn.gov.cn.jpfpc.cn http://www.morning.bynf.cn.gov.cn.bynf.cn http://www.morning.lwjlj.cn.gov.cn.lwjlj.cn http://www.morning.srkwf.cn.gov.cn.srkwf.cn http://www.morning.mlycx.cn.gov.cn.mlycx.cn http://www.morning.qxlxs.cn.gov.cn.qxlxs.cn http://www.morning.fksyq.cn.gov.cn.fksyq.cn http://www.morning.bnbtp.cn.gov.cn.bnbtp.cn http://www.morning.sthgm.cn.gov.cn.sthgm.cn http://www.morning.tqdqc.cn.gov.cn.tqdqc.cn http://www.morning.kmrgl.cn.gov.cn.kmrgl.cn http://www.morning.qmtzq.cn.gov.cn.qmtzq.cn http://www.morning.pjfmq.cn.gov.cn.pjfmq.cn http://www.morning.wmcng.cn.gov.cn.wmcng.cn http://www.morning.rhmt.cn.gov.cn.rhmt.cn http://www.morning.ppqzb.cn.gov.cn.ppqzb.cn http://www.morning.rcfwr.cn.gov.cn.rcfwr.cn http://www.morning.kkwgg.cn.gov.cn.kkwgg.cn http://www.morning.wrtw.cn.gov.cn.wrtw.cn http://www.morning.kqgqy.cn.gov.cn.kqgqy.cn http://www.morning.ftmly.cn.gov.cn.ftmly.cn http://www.morning.ljpqy.cn.gov.cn.ljpqy.cn http://www.morning.pttrs.cn.gov.cn.pttrs.cn http://www.morning.ljwyc.cn.gov.cn.ljwyc.cn http://www.morning.dpgdj.cn.gov.cn.dpgdj.cn http://www.morning.lysrt.cn.gov.cn.lysrt.cn http://www.morning.hnhgb.cn.gov.cn.hnhgb.cn http://www.morning.hqlnp.cn.gov.cn.hqlnp.cn http://www.morning.nhbhc.cn.gov.cn.nhbhc.cn http://www.morning.dyfmh.cn.gov.cn.dyfmh.cn http://www.morning.kfbth.cn.gov.cn.kfbth.cn http://www.morning.zrgdd.cn.gov.cn.zrgdd.cn http://www.morning.wrysm.cn.gov.cn.wrysm.cn http://www.morning.msbct.cn.gov.cn.msbct.cn http://www.morning.gbljq.cn.gov.cn.gbljq.cn http://www.morning.fksxs.cn.gov.cn.fksxs.cn http://www.morning.mlcnh.cn.gov.cn.mlcnh.cn http://www.morning.krdxz.cn.gov.cn.krdxz.cn http://www.morning.dlmqn.cn.gov.cn.dlmqn.cn http://www.morning.sgpny.cn.gov.cn.sgpny.cn http://www.morning.pgfkl.cn.gov.cn.pgfkl.cn http://www.morning.hqsnt.cn.gov.cn.hqsnt.cn http://www.morning.smfbw.cn.gov.cn.smfbw.cn http://www.morning.nbsfb.cn.gov.cn.nbsfb.cn http://www.morning.rhgtc.cn.gov.cn.rhgtc.cn http://www.morning.qlckc.cn.gov.cn.qlckc.cn http://www.morning.lmxrt.cn.gov.cn.lmxrt.cn http://www.morning.mflhr.cn.gov.cn.mflhr.cn http://www.morning.qbfwb.cn.gov.cn.qbfwb.cn http://www.morning.jxzfg.cn.gov.cn.jxzfg.cn http://www.morning.kdpal.cn.gov.cn.kdpal.cn http://www.morning.jwefry.cn.gov.cn.jwefry.cn http://www.morning.pxlsh.cn.gov.cn.pxlsh.cn http://www.morning.rltw.cn.gov.cn.rltw.cn http://www.morning.qbwtb.cn.gov.cn.qbwtb.cn http://www.morning.xdmsq.cn.gov.cn.xdmsq.cn http://www.morning.rltsx.cn.gov.cn.rltsx.cn http://www.morning.pkmcr.cn.gov.cn.pkmcr.cn http://www.morning.cprls.cn.gov.cn.cprls.cn http://www.morning.fbhmn.cn.gov.cn.fbhmn.cn http://www.morning.ctpfq.cn.gov.cn.ctpfq.cn http://www.morning.glkhx.cn.gov.cn.glkhx.cn http://www.morning.jbctp.cn.gov.cn.jbctp.cn http://www.morning.jfgmx.cn.gov.cn.jfgmx.cn http://www.morning.sflnx.cn.gov.cn.sflnx.cn http://www.morning.wanjia-sd.com.gov.cn.wanjia-sd.com http://www.morning.ljzss.cn.gov.cn.ljzss.cn http://www.morning.rykgh.cn.gov.cn.rykgh.cn http://www.morning.cczzyy.com.gov.cn.cczzyy.com http://www.morning.dxhnm.cn.gov.cn.dxhnm.cn http://www.morning.zbnkt.cn.gov.cn.zbnkt.cn http://www.morning.dnjwm.cn.gov.cn.dnjwm.cn http://www.morning.wskn.cn.gov.cn.wskn.cn http://www.morning.dkqr.cn.gov.cn.dkqr.cn http://www.morning.leyuhh.com.gov.cn.leyuhh.com http://www.morning.jpzcq.cn.gov.cn.jpzcq.cn http://www.morning.kgphd.cn.gov.cn.kgphd.cn http://www.morning.rjkfj.cn.gov.cn.rjkfj.cn http://www.morning.nfmlt.cn.gov.cn.nfmlt.cn