若依Vue(若依前后端分离版)--01

2023-10-31

(该文章整理于网络,仅用于学习记录,如有侵权,请联系删除)

介绍

RuoYi-Vue 是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring Security、MyBatis、Jwt、Vue),内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、代码生成等。在线定时任务配置;支持集群,支持多数据源,支持分布式事务。比较好用。

 快速了解  

   可参考官网。

环境部署

部署Java:多模块springboot ,通过宝塔创建springboot项目,再通过nginx反向代理即可。

部署Vue :打包部署。

war部署方式
ruoyi/pom.xml中的packaging修改为war,放入tomcat服务器webapps

SpringBoot去除内嵌Tomcat(PS:此步骤不重要,因为不排除也能在容器中部署war

项目介绍

1. 注解:需要通过反射来进行解析,参考excle注解。如果没解析器就没有任何意义。

 

 2. ruoyi配置,通过该类读取yml配置文件:(

@Component
@ConfigurationProperties(prefix = "ruoyi")

3. constant常量

4. core: 基本的control 封装公共。

5.公共的实体:如loginbody.

6.封装的page.

7. redis操作的方法。

bbbub{},“aaa”====》

debug讲解

登陆讲解:

获取验证码,获取配置默认的验证码类型。

验证码存放到redis ,并且返回一个uuuid到前台用于验证(有时效),如果要使用,可以临时去取。

登陆逻辑梳理:

  public void validateCaptcha(String username, String code, String uuid)
    {
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        String captcha = redisCache.getCacheObject(verifyKey);
        redisCache.deleteObject(verifyKey);
        if (captcha == null)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
            throw new CaptchaExpireException();
        }
        if (!code.equalsIgnoreCase(captcha))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
    }

登陆debug:

注意是封装的第三方组件。

模拟登陆若依

      通过API POST 或者 IDEA 的HTTP客户端发起请求,获取图片后 ,解析到答案。

     或者直接根据UUID去redis查询到结果:

  1. 获取验证码,得到UUID

  2. 向后端发送login请求,带上username,password,uuid,code(验证码)

  3. 登录成功 获取TOKEN token解密后,并缓存到redis.

     4. 发起其他请求,需要带上token进行认证。(两种均可)

后台手册

复习反射注解

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。

Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。

内置的注解

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

作用在代码的注解是

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。

  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

作用在其他注解的注解(或者说 元注解)是:

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

  • @Documented - 标记这些注解是否包含在用户文档中。

  • @Target - 标记这个注解应该是哪种 Java 成员。

  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

从 Java 7 开始,额外添加了 3 个注解:

  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。

  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。


    获取并设置字段


获取注解,比如或用户名称上的注解信息:(注意soutv的使用)

通过反射获取构造函数并实例化,获取成员方法并调用:如下:

 

 

导入导出

  • 导入

  • 导出

分页

  • 前端实现

    // 一般在查询参数中定义分页变量
    queryParams: {
      pageNum: 1,
      pageSize: 10
    },
    ​
    // 页面添加分页组件,传入分页变量
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
    ​
    // 调用后台方法,传入参数 获取结果
    listUser(this.queryParams).then(response => {
        this.userList = response.rows;
        this.total = response.total;
      }
    );
  • 后端实现

    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(User user)
    {
        startPage();  // 此方法配合前端完成自动分页
        List<User> list = userService.selectUserList(user);
        return getDataTable(list);
    }

上传下载

  • 上传

    drop table if exists sys_file_info;
    create table sys_file_info (
      file_id           int(11)          not null auto_increment       comment '文件id',
      file_name         varchar(50)      default ''                    comment '文件名称',
      file_path         varchar(255)     default ''                    comment '文件路径',
      primary key (file_id)
    ) engine=innodb auto_increment=1 default charset=utf8 comment = '文件信息表';
    <el-upload
      ref="upload"
      :limit="1"
      accept=".jpg, .png"
      :action="upload.url"
      :headers="upload.headers"
      :file-list="upload.fileList"
      :on-progress="handleFileUploadProgress"
      :on-success="handleFileSuccess"
      :auto-upload="false">
      <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" :loading="upload.isUploading" @click="submitUpload">上传到服务器</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
    import { getToken } from "@/utils/auth";
    // 上传参数
    upload: {
      // 是否禁用上传
      isUploading: false,
      // 设置上传的请求头部
      headers: { Authorization: "Bearer " + getToken() },
      // 上传的地址
      url: process.env.VUE_APP_BASE_API + "/common/upload",
      // 上传的文件列表
      fileList: []
    },
    handleAdd() {
      ...
      this.upload.fileList = [];
    }
    ​
    handleUpdate(row) {
      ...
      this.upload.fileList = [{ name: this.form.fileName, url: this.form.filePath }];
    }
    // 文件提交处理
    submitUpload() {
      this.$refs.upload.submit();
    },
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true;
    },
    // 文件上传成功处理
    handleFileSuccess(response, file, fileList) {
      this.upload.isUploading = false;
      this.form.filePath = response.url;
      this.msgSuccess(response.msg);
    }
  • 下载

    <template>
      <div class="app-container">
        <el-row :gutter="20">
          <el-col xl="24" md="24" lg="24" sm="24">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-edit"
              @click="handleDownload"
            >下载
            </el-button>
    ​
    ​
          </el-col>
    ​
        </el-row>
    ​
      </div>
    </template>
    ​
    <script>
    export default {
      name: "index",
      methods: {
        // 文件下载处理
        handleDownload() {
    ​
          var name = "/profile/upload/2021/01/18/4d6b8f1f-5b10-4e76-b5b4-675bd90856b6.jpg";
          var url = "http://localhost:8080/profile/upload/2021/01/18/4d6b8f1f-5b10-4e76-b5b4-675bd90856b6.jpg";
    ​
    ​
          var suffix = url.substring(url.lastIndexOf("."), url.length);
          const a = document.createElement('a')
          a.setAttribute('download', name + suffix)
          a.setAttribute('target', '_blank')
          a.setAttribute('href', url)
          a.click()
        }
    ​
      }
    }
    </script>
    ​
    <style scoped>
    ​
    </style>

权限控制

  • 授之以渔。

  • 菜单-角色-用户-权限:

    ​
    1、xxx:xxx:list意思是能不能进入这个菜单进行对表增删改查,如果没有这个权限,前端不能进入菜单。
    2、xxx:xxx:add,remove,edit,query,意思是对前端的增删改查实现,往往会在前端的组件多加一个指令v-hasPermi(若依封装),如果没有这个权限,则组件将不会显示。
    ​
    3、后端执行某个controller若需要某个权限才能执行,则需要加上注解@PreAuthorize("@ss.hasPermi('system:user:list')")
    这个注解是若依+SpringSecurity框架共同实现的,它会先去执行方法ss.hasPermi('system:user:list')来判断是否能去执行相关的controller。
    4、在登录的时候,每次点击全局页面刷新的时候,都会执行getInfo方法去获取权限,这个权限会被vuex进行管理,从而方便在每一个界面判断是否展示某个组件/按钮。
    ​
  • 数据权限 ---留到后面再讲

    • 所谓数据权限,就是某个用户能查询哪些数据,来看一下若依给我们的解释:

      在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。 例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。

事务管理

同SpringBoot,主要注解:@Transactional

异常处理

全局异常处理。通过一个全局异常处理类来进行处理GlobalExceptionHandler,这里面有两个重要的注解叫:@RestControllerAdvice,@ExceptionHandler(BaseException.class),用AOP的方法去增强方法,若发生异常将由ExceptionHandler注解的方法去处理这个异常,一般都是给前端返回一个错误的信息。这里BaseException.class就是指定某个异常,当这个异常发生,就会执行相关方法,例如:

/**
 * 基础异常
 */
@ExceptionHandler(BaseException.class)
public AjaxResult baseException(BaseException e)
{
    return AjaxResult.error(e.getMessage());
}

这个方法就会去处理发生了BaseException的控制器。

系统日志

  • 登录日志(需要线程池知识)

    • 登录日志带大家debug,在com/ruoyi/framework/web/service/SysLoginService.java这个类中的login方法中能找到相关的日志打印信息,例如:

                  AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
      ​
  • 控制器操作日志

    • AOP切面实现逻辑-debug。

    • 案例-自定义自己的操作日志。

数据权限

在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。 例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。

针对角色设置的-去角色管理进行设置每一个角色的数据权限。

这个数据权限是AOP来实现的,主要注解是@Before(前置切入),通过对维护的param属性对应的HashMap中dataScope健存入一段SQL,这段SQL最终将加在查询语句的后边,mybatis中引用:${param.dataScope}。如何拼装的SQL在切面类(DataScopeAspect)中debug可以看到。

多数据源

前置知识 -> 如何实现多数据源?,实现多数据源的ThreadLocal类作用是什么呢?

主要通过继承AbstractRoutingDataSource类来实现。

ThreadLocal是存储线程独立局部变量用的,多个线程之间互不干扰。

前端手册

组件文档

项目扩展

视频教程

更新日志

其它

公共基础:

获取当前用户逻辑

  • 前端获取方法:var userName = this.$store.state.user.name; 那么 什么时候这里面有值的呢?

  • 后端获取方法

    • 方法一:工具类获取
      String userName = SecurityUtils.getUsername();
    • @Autowired
      private TokenService tokenService;
          
      LoginUser loginUser = tokenService.getLoginUser();
      // 获取当前的用户名称
      String userName = loginUser.getUsername();

前端获取路由逻辑

Excel导入逻辑 * 讲过

Excel导出逻辑 不讲

登录逻辑 * 讲过

鉴权(权限)逻辑 -- 讲了

sys_config表是个什么玩意?

对应前端参数设置的值。

redis存的一些值是什么玩意?怎么项目一启动就有值的?

值来自sys-config表

作业:

Excel导入,顺带导入角色,在模板中给用户以提示。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

若依Vue(若依前后端分离版)--01 的相关文章

随机推荐

  • 卸载cpu版本的torch并离线安装对应的gpu版本

    每次从github上安装项目对应的库 利用requirements txt安装很容易出现版本不对应的情况 尤其是将torch的gpu版本安装成cpu 这里记录一些查看版本的指令和离线安装的方法 就不用每次百度啦 注 其他库的离线安装也可以用
  • stm32不使用外部晶振管脚怎么处理_stm32的外部晶振不起振以及更改外部晶振值的问题...

    今天有人问我关于外部晶振不起振以及如歌更改32的外部晶振 在此我做一个简单的记录 以stm32f1系列为例 其余类似 1 晶振不起振 此次遇到的问题倒不是出在电路上 实际上还是软件上的问题 画的新板子 换了一块贴片的晶振 与原来的直插式有点
  • Linux (二): 文件系统介绍、文件处理与权限操作

    目录 四 文件系统 分区与文件系统 组成 文件读取 磁盘碎片 block inode 目录 日志 挂载 目录配置 五 文件 文件属性 文件与目录的基本操作 1 ls 2 cd 3 mkdir 4 rmdir 5 touch 6 cp 7 r
  • Flink 1.17教程:输出算子之输出到Kafka

    输出到Kafka 1 添加Kafka 连接器依赖 由于我们已经测试过从Kafka数据源读取数据 连接器相关依赖已经引入 这里就不重复介绍了 2 启动Kafka集群 3 编写输出到Kafka的示例代码 输出无key的record public
  • word2vec和常见CNN+RNN网格结构组成的文本分类模型

    作者为了应付毕业 所以在补充深度学习相关知识 这是我尝试把word2vec和深度学习相互结合的一次记录 数据集来源 数据集预处理 生成word2vec模型 搭建网络并且训练 数据集来源 本文的数据集源自kaggle比赛中的NLP入门比赛 灾
  • S3C2416 SD卡启动和NAND启动的配置

    S3C2416的启动方式分为IROM NAND ONENAND ROM三种模式 有的datasheet上只有IROM ONENAND ROM两种模式 如下图所示 图1 图2 图2应该是早期三星的2416手册 图1为之后再次更新的 所以这里以
  • R语言实验课(生信)(附代码)

    实验五 题目1 解决方法 a lt read table E R Rcode temp txt 读取txt文件 找到下载路径 b lt list c lt list d lt list e lt list h lt matrix 0 5 1
  • 云风的新书电子版出来的真快

    云风大侠新书出来没几天 电子版就出来了 电骡上好像很早就有下载的了 不过我认为电子版不会影响销售的 只会聚集更多的人气 我这里也有个链接 ftp pub pub ftp PicDisk net pub Scan 游戏之旅 我的编程感悟 pd
  • 关于2022年9月以太坊合并你需要知道的10件事

    关于2022年9月以太坊合并你需要知道的10件事 1 什么是合并 合并是以太坊区块链将共识机制从工作量证明 pow 转为权益证明 pos 的事件 是以太坊主网与信标链 beacon chain 合并的简称 2 为什么 合并 这么值得关注 在
  • MicroBlaze系列教程(5):AXI_UART16550的使用

    文章目录 toc AXI UART16550简介 MicroBlaze硬件配置 常用函数 使用示例 参考资料 工程下载 本文是Xilinx MicroBlaze系列教程的第5篇文章 AXI UART16550简介 axi uart16550
  • MockMvc

    MockMvc classes SpringbootApplication class 指定入口启动类 webEnvironment SpringBootTest webEnvironment RANDOM PORT采用随机端口启动 不会产
  • MMU的作用及工作过程

    以下内容摘自 步步惊芯 软核处理器内部设计分析 一书的第10章 MMU剖析 MMU的作用及工作过程 MMU Memory Management Unit 是内存管理单元的简称 读者朋友在学习嵌入式的时候应该听说过 CLinux 这是适合没有
  • Android自动化测试框架

    1 Monkeyrunner 优点 操作最为简单 可以录制测试脚本 可视化操作 缺点 主要生成坐标的自动化操作 移植性不强 功能最为局限 2 Rubotium 主要针对某一个APK进行自动化测试 APK可以有源码 也可以没有源码 功能强大
  • ug装配绕轴旋转_UG绘制一个灯泡,这个白炽灯大家都熟悉吧

    灯泡三维建模你会吗 今天来学习一下吧 白炽灯是一种热辐射光源 能量的转换效率很低 只有2 4 的电能转换为眼睛能够感受到的光 虽然现在是普遍选用日光灯 但在10多年前 白炽灯还是使用最广泛的 今天就来用UG画个白炽灯怀念下吧 这个灯泡看看起
  • 计算机网络基础--互联网组成

    目录 互联网的边缘部分 通信方式 C S方式 通信方式 P2P方式 互联网的核心部分 电路交换 分组交换 报文交换 三种交换比较 互联网这个词想必对于大家来说已经不陌生了 那么你能说出互联网是由什么组成的吗 既然要步入互联网行业 那就应该知
  • 基于flowplayer的视频缩略图的视频预览

    大家在平时观看视频的视频网站中 比如优酷 爱奇艺 腾讯视频等 鼠标移动至播放条区域的时候 大家可以看到会弹出小的视频预览图片 这样子就可以给用户很好体验 至少可以知道前后播放的内容 最近公司业务需要 就不得不研究了 本文将从三个方面进行总结
  • 【OpenCV实战】这是我看过最详细的计算机视觉小项目,基于OpenCV进行长时间曝光,学到了~(赶紧收藏)

    前言 在本文中 我们将学习长时间曝光摄影技术 以及如何使用Python和OpenCV 开源计算机视 觉库 对其进行仿真 作者 程序员梨子 文章源码免费获取 为了感谢每一个关注我的小可爱 每篇文章的项目源码都是无偿分享滴 点下面找我获取完整资
  • matlab @函数_用MATLAB绘制正弦函数的图形

    用MATLAB正确地绘制正弦函数的图形 从中你会发现许多技术细节问题 一些抽象的理论问题 你可以在实践中得以启发 close all clear n 64 x 0 2 pi n 2 pi x x 1 n y sin x figure ste
  • Fastjson1.2.24-RCE 漏洞复现(CVE-2017-18349)

    0x01 漏洞简介 fastjson是阿里巴巴的开源JSON解析库 它可以解析JSON格式的字符串 支持将Java Bean序列化为JSON字符串 也可以从JSON字符串反序列化到JavaBean 即fastjson的主要功能就是将Java
  • 若依Vue(若依前后端分离版)--01

    该文章整理于网络 仅用于学习记录 如有侵权 请联系删除 介绍 RuoYi Vue 是一个 Java EE 企业级快速开发平台 基于经典技术组合 Spring Boot Spring Security MyBatis Jwt Vue 内置模块