若依源码分析

一.登录

1.1 生成验证码

基本思路

在这里插入图片描述

  • 后端生成一个表达式,7+4=?@11

  • 7+4=?转成图片,传到前端进行展示

  • 将结果11存入redis

    在这里插入图片描述

  • 前端代码实现:

    在这里插入图片描述

    请求后端地址:http://localhost/dev-api/captchaImage,通过反向代理解决前后端跨域问题,将请求路径变为:http://localhost:8080/captchaImage

    在这里插入图片描述

  • 后端代码实现:

    /*** 生成验证码*/
    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException
    {AjaxResult ajax = AjaxResult.success();boolean captchaEnabled = configService.selectCaptchaEnabled();ajax.put("captchaEnabled", captchaEnabled);if (!captchaEnabled){return ajax;}// 保存验证码信息String uuid = IdUtils.simpleUUID();String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;String capStr = null, code = null;BufferedImage image = null;// 生成验证码String captchaType = RuoYiConfig.getCaptchaType();if ("math".equals(captchaType)){String capText = captchaProducerMath.createText();capStr = capText.substring(0, capText.lastIndexOf("@"));code = capText.substring(capText.lastIndexOf("@") + 1);image = captchaProducerMath.createImage(capStr);}else if ("char".equals(captchaType)){capStr = code = captchaProducer.createText();image = captchaProducer.createImage(capStr);}redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);// 转换流信息写出FastByteArrayOutputStream os = new FastByteArrayOutputStream();try{ImageIO.write(image, "jpg", os);}catch (IOException e){return AjaxResult.error(e.getMessage());}ajax.put("uuid", uuid);ajax.put("img", Base64.encode(os.toByteArray()));return ajax;
    }
    

1.2 登录

  • 后端

    • 1.校验验证码
    • 2.校验用户名和密码
    • 3.生成ToKen
    /*** 登录方法* * @param loginBody 登录信息* @return 结果*/
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {AjaxResult ajax = AjaxResult.success();// 生成令牌String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),loginBody.getUuid());ajax.put(Constants.TOKEN, token);return ajax;
    }
    

    使用异步任务管理器,结合线程池,实现了异步的操作日志记录,和业务逻辑实现异步解耦合.

1.3 获取用户信息

/*** 获取用户信息* * @return 用户信息*/
@GetMapping("getInfo")
public AjaxResult getInfo()
{SysUser user = SecurityUtils.getLoginUser().getUser();// 角色集合Set<String> roles = permissionService.getRolePermission(user); // 超级管理员// 权限集合Set<String> permissions = permissionService.getMenuPermission(user); // *:*:*AjaxResult ajax = AjaxResult.success();ajax.put("user", user);ajax.put("roles", roles);ajax.put("permissions", permissions);return ajax;
}

获取当前用户的角色和权限信息,存储到Vuex中

1.4 获取路由信息

根据当前用户的权限信息获取动态路由,最终完成动态菜单的展示

/*** 获取路由信息* * @return 路由信息*/
@GetMapping("getRouters")
public AjaxResult getRouters()
{Long userId = SecurityUtils.getUserId();List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);return AjaxResult.success(menuService.buildMenus(menus));
}

二.首页加载

在这里插入图片描述

在这里插入图片描述

当用户登录成功以后我们可以根据路由看出,默认跳转到路由/viees/index.vue页面

三.用户管理

3.1 查询

流程:加载vue页面 -> 请求后台数据

在这里插入图片描述

  • 获取用户信息后端

    /*** 获取用户列表*/
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user)
    {startPage(); // 做分页List<SysUser> list = userService.selectUserList(user); // 查询数据return getDataTable(list); // 返回结果
    }
    
  • 获取树状图后端

    /*** 获取部门树列表*/
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept)
    {return success(deptService.selectDeptTreeList(dept));
    }
    

3.2 添加用户

  • 前端
/** 新增按钮操作 */
handleAdd() {this.reset();// 清空表单getUser().then(response => {this.postOptions = response.posts;// 岗位this.roleOptions = response.roles;// 角色this.open = true;this.title = "添加用户";this.form.password = this.initPassword;});
},/** 提交按钮 */submitForm: function() {this.$refs["form"].validate(valid => {if (valid) {if (this.form.userId != undefined) {updateUser(this.form).then(response => {this.$modal.msgSuccess("修改成功");this.open = false;this.getList();});} else {addUser(this.form).then(response => {this.$modal.msgSuccess("新增成功");this.open = false;this.getList();});}}});},
  • 后端
/*** 根据用户编号获取详细信息*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{userService.checkUserDataScope(userId);AjaxResult ajax = AjaxResult.success();List<SysRole> roles = roleService.selectRoleAll();ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));ajax.put("posts", postService.selectPostAll());if (StringUtils.isNotNull(userId)){SysUser sysUser = userService.selectUserById(userId);ajax.put(AjaxResult.DATA_TAG, sysUser);ajax.put("postIds", postService.selectPostListByUserId(userId));ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));}return ajax;
}/*** 新增用户*/
@PreAuthorize("@ss.hasPermi('system:user:add')")
@Log(title = "用户管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysUser user)
{if (!userService.checkUserNameUnique(user)){return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");}else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)){return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");}else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)){return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");}user.setCreateBy(getUsername());user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));return toAjax(userService.insertUser(user));
}

修改和删除查看源码步骤相同,这里省略

四.异步任务管理器

这里选取一段代码作示例:com.ruoyi.framework.web.service.SysLoginService

AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));

通过异步任务管理器记录登录日志

  • AsyncManager.me():获取一个AsyncManager对象
  • 执行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(){@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);}};
}

封装了登录用户的信息,执行添加操作,这里不会执行,而是将任务交给线程对象来执行

异步任务管理器,内部定义了一个线程池,然后根据业务创建添加日志的任务,交给线程池来处理,这样做到日志和业务的抽象,解耦合,日志全部统一处理.

五.代码自动生成

5.1 创建数据表

use ry_vue;
create table test_user
(id       int primary key auto_increment,name     varchar(11),password varchar(11)
);

5.2 系统工具–>代码生成

在这里插入图片描述

5.2.1 导入数据表

在这里插入图片描述

5.2.2 编辑数据表

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.2.3 点击生成代码

在这里插入图片描述

5.2.4 解压压缩包

在这里插入图片描述

5.2.5 导入代码,重启项目
  • 后端

在这里插入图片描述

  • 前端

在这里插入图片描述

  • 数据库

2364434953)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/223721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ESXI 6.7升级update3

一、适用场景 1、企业已有专业服务器&#xff0c;通过虚拟化环境搭建了vm server&#xff1b; 2、备份整个vm server时&#xff0c;需要使用ovftool工具完成&#xff0c;直接导出ovf模板时报错&#xff1b; 3、升级EXSI6.7的build 8169922版本为update 3版本后&#xff0c;已保…

The method show() from the type Window is deprecated

java.awt.Window.show() java.awt.Component.setVisible(true); Window.show() java.awt.JFrame java.awt.Frame java.awt.Windows java.awt.Component.setVisible(true);

论文查重过多怎么降重 神码ai

大家好&#xff0c;今天来聊聊论文查重过多怎么降重&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 论文查重过多怎么降重 当论文查重率过高时&#xff0c;需要进行降重处…

LeetCode力扣每日一题(Java)66、加一

每日一题在昨天断开了一天&#xff0c;是因为作者沉迷吉他&#xff0c;无法自拔……竟然把每日一题给忘了&#xff0c;所以今天&#xff0c;发两篇每日一题&#xff0c;把昨天的给补上 一、题目 二、解题思路 1、我的思路 其实乍一看这道题还是比较简单的&#xff0c;就是让…

商业智能BI和数据可视化的区别

现在市场上有非常多的商业智能BI产品&#xff0c;几乎都在着重宣传其数据可视化功能的强大&#xff0c;给人造成一种商业智能BI就是数据可视化的印象。事实上商业智能BI并不等于数据可视化。要探究商业智能BI和数据可视化的区别&#xff0c;我们先要分别弄清楚这两个概念。 1、…

gitlab下载,离线安装

目录 1.下载 2.安装 3.配置 4.启动 5.登录 参考&#xff1a; 1.下载 根据服务器操作系统版本&#xff0c;下载对应的RPM包。 gitlab官网&#xff1a; The DevSecOps Platform | GitLab rpm包官网下载地址: gitlab/gitlab-ce - Results in gitlab/gitlab-ce 国内镜像地…

智能优化算法应用:基于狮群算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于狮群算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于狮群算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.狮群算法4.实验参数设定5.算法结果6.参考文献7.MA…

常见的Linux基本指令

目录 什么是Linux&#xff1f; Xshell如何远程控制云服务器 Xshell远程连接云服务器 Linux基本指令 用户管理指令 pwd指令 touch指令 mkdir指令 ls指令 cd指令 rm指令 man命令 cp指令 mv指令 cat指令 head指令 ​编辑 tail指令 ​编辑echo指令 find命令 gr…

记一次挖矿病毒的溯源

ps&#xff1a;因为项目保密的原因部分的截图是自己在本地的环境复现。 1. 起因 客户打电话过来说&#xff0c;公司web服务异常卡顿。起初以为是web服务缓存过多导致&#xff0c;重启几次无果后觉得可能是受到了攻击。起初以为是ddos攻击&#xff0c;然后去查看web服务器管理…

Python调用API的实用技巧

导语&#xff1a;在当今的软件开发世界中&#xff0c;API&#xff08;应用程序接口&#xff09;已成为数据传输和功能调用的重要桥梁。Python作为一种功能强大的编程语言&#xff0c;提供了多种调用API的方法。本文将分享一些实用的Python调用API技巧&#xff0c;帮助你更好地利…

最大子数组和java实现【动态规划基础练习】

12.15 最大子数组和 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4]…

深入了解空号检测API:提升通信效率的关键

引言 随着通信技术的不断发展&#xff0c;人们对于通信效率的要求也越来越高。在通信过程中&#xff0c;空号检测是一个非常重要的环节&#xff0c;它可以帮助我们避免无效的通信&#xff0c;提高通信效率。而空号检测API则是实现空号检测功能的重要工具。 空号检测API 空号…

git的分支的使用,创建分支,合并分支,删除分支,合并冲突,分支管理策略,bug分支,强制删除分支

GIT | 分支 文章目录 GIT | 分支创建分支合并分支删除分支合并冲突分支管理策略bug分支强制删除分支 创建分支 查看当前本地仓库中有哪些分支 git branchHEAD所指向的分支就是当前正在工作的分支 cat .git/HEAD创建一个分支 git branch dev创建好了&#xff0c;但是目前还是…

数字人克隆系统源码无限克隆数字人!

随着人工智能技术的不断发展&#xff0c;数字人的应用越来越广泛。数字人可以用于虚拟演员、虚拟客服、虚拟主持人等领域&#xff0c;为企业和个人带来更多的商业价值和娱乐体验。然而&#xff0c;数字人的制作过程需要大量的人力和时间&#xff0c;成本较高&#xff0c;限制了…

记一次clickhouse启动报错

clickhouse一次排错 clickhouse启动报错 报错&#xff1a; Application: Code: 210. DB::Exception: Listen [::]:8123 failed: Poco::Exception. Code: 1000, e.code() 0, DNS error: EAI: Address family for hostname not supported (version 23.3.1.2823 (official bui…

破局:国内市场确实存在“消费升级”和“消费降级”,3.0全新新零售商业模式

国内市场确实存在“消费升级”和“消费降级”两个趋势&#xff0c;这是由于不同消费者群体的需求和购买力存在差异。消费升级主要发生在高端市场&#xff0c;消费者愿意为高品质、高价值、高价格的商品和服务付出更多。而消费降级则主要发生在中低端市场&#xff0c;消费者更加…

vue2项目vue-qrcode-reader 扫一扫二维码插件

vue2项目 vue-qrcode-reader 扫一扫二维码插件 问题所在解决办法成功展示 问题所在 今天在引导师弟做扫二维码功能&#xff0c;发现通过npm install --save vue-qrcode-reade安装死活就是报错TypeError: Object...) is not a function 解决办法 百度了很多大牛的博客&#…

Leetcode—2415.反转二叉树的奇数层【中等】

2023每日刷题&#xff08;六十&#xff09; Leetcode—2415.反转二叉树的奇数层 BFS的C实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(n…

【docker 】Dockerfile指令学习

学习文档地址 上篇文章&#xff1a;【docker 】基于Dockerfile创建镜像 Dockerfile指令文档地址 .dockerignore 文件 Dockerfile指令 常见的指令 Dockerfile 指令说明FROM指定基础镜像&#xff0c;用于后续的指令构建。MAINTAINER指定Dockerfile的作者/维护者。&#xff…

RK3568平台(网络篇) 有线网络基本概念及测试手法

一.什么是交换机&#xff1f; 交换机是一种用于电(光)信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路。最常见的交换机是以太网交换机。交换机工作于OSI参考模型的第二层&#xff0c;即数据链路层。交换机拥有一条高带宽的背部总线和内部交换…