目录

概述

前端代码

后端代码


概述

前端代码

前端代码位于@/views/tool/index.vue(Vue3版本在@/views/tool/gen/index.vue)

可以看到,点击生成按钮后会触发点击事件,并通过点击事件调用handleGenTable方法。

我们再定位到该方法,了解一下它的具体内容:

代码分析

参数 row:对象类型,代表一行数据,包含了 tableNamegenType 等属性。

tbNames 是表名,优先使用 row.tableName,如果为空,则取 tableNames.value

关于row.tableName和tableNames.value的选取

首先,我们要知道,若依框架前端提供了两种按钮来完成生成代码的功能:

第一种按钮在表格之外,无法获取表格中的行数据的具体内容的,也就是说,如果点击第一种按钮,handleGenTable(row)中的row,并没有记录选中行的相关数据,所以row.tableName会为空,那怎么解决呢?源代码是这样写的:

const tbNames = row.tableName || tableNames.value;

它的意思是,优先使用row.tableName,如果row.tableName为空,那就用tableNames.value。

如果两个都为空(前端没有选中任何行),前端就会给出提示,并退出该方法,正如源代码所写:

if (tbNames == "") {
    proxy.$modal.msgError("请选择要生成的数据");
    return;
  }

tableNames.value通过选中多选框来获取值(后面我详细讲解)。

而点击第二种按钮时,因为该按钮是在表的内部,所以可以得到当前行的数据,row.tableName的值就是当前行的表名称

在我们用多选框选中时,会调用下面的方法:

参数selection是一个数组,用于存放已选中的行的对象,比如我选中了两个行:

那么selection就像下面这样:

将它展开:

可以看到,每个元素里都有对应行的相关数据,其中就包括表名。

handleSelectionChange(selection)就会将select中的数据进行过滤,并赋值给index.vue中声明的变量:

如果在前端生成配置中选中了自定义路径:

那么生成方法中的row.genType会被赋值为1,然后就可以执行下面的代码:

调用异步函数 genCode 生成代码,成功后显示成功提示,并展示生成路径。

否则,row.genType的值为0,可以执行下面的代码:

通过 proxy.$download.zip 下载生成的代码压缩包。

下载路径是:/tool/gen/batchGenCode?tables= + 表名,文件名固定为 ruoyi.zip

proxy.$download.zip中的download是一个抽取好的文件:

这里用的是download中的zip方法

zip方法的具体内容:

这段代码的功能是实现文件下载(一个 ZIP 文件),同时提供了加载提示和错误处理。以下是对代码的逐步分析:

1. 函数定义和URL处理

zip(url, name) {
    var url = baseURL + url
  • 函数 zip(url, name) 接收两个参数:
    • url: 相对路径或具体资源路径。
    • name: 下载文件保存的名称。
  • url 被拼接成完整的路径 baseURL + url,其中 baseURL 应该是一个全局变量,存储了基础 API 地址。

2. 加载提示

downloadLoadingInstance = ElLoading.service({ 
    text: "正在下载数据,请稍候", 
    background: "rgba(0, 0, 0, 0.7)" 
})
  • 使用 ElLoading.service(可能是 Element-UI 的加载组件)显示一个带有文本提示和半透明背景的加载框,告知用户正在下载数据。

3. 发起文件下载请求

axios({
    method: 'get',
    url: url,
    responseType: 'blob',
    headers: { 'Authorization': 'Bearer ' + getToken() }
})
  • 请求方式: GET
  • 请求地址: url(拼接后的完整路径)。
  • 响应类型: blob,表明希望接收到二进制流数据(通常用于下载文件)。
  • 请求头: 包含 Authorization,其中 Bearer 后面的 getToken() 返回一个认证令牌,应该是用户登录后的凭证。

4. 处理响应数据

.then((res) => {
    const isBlob = blobValidate(res.data);
    if (isBlob) {
        const blob = new Blob([res.data], { type: 'application/zip' });
        this.saveAs(blob, name);
    } else {
        this.printErrMsg(res.data);
    }
    downloadLoadingInstance.close();
})
  • blobValidate 验证响应数据:
    • 验证 res.data 是否有效的二进制文件(Blob)。
    • blobValidate 是用户自定义的一个校验方法。
  • 有效数据处理:
    • 如果校验通过,将数据转换为一个 Blob 对象,并指定 MIME 类型为 application/zip(表示 ZIP 文件)。
    • 调用 this.saveAs(blob, name) 保存文件:
      • saveAs 是一个方法(可能是自定义方法或来自 FileSaver.js),负责触发浏览器的下载。
  • 无效数据处理:
    • 调用 this.printErrMsg(res.data) 输出错误信息。
  • 关闭加载提示框:
    • 无论是否成功处理响应,最后都会关闭加载框。

5. 处理错误情况

.catch((r) => {
    console.error(r);
    ElMessage.error('下载文件出现错误,请联系管理员!');
    downloadLoadingInstance.close();
})
  • 捕获异常:
    • 如果请求失败(例如网络错误或服务器异常),会捕获到异常。
  • 错误提示:
    • 使用 ElMessage.error(可能是 Element-UI 的消息组件)显示错误提示。
  • 关闭加载提示框:
    • 无论是否成功,都会关闭加载框以结束用户的等待状态。

后端代码

该方法是一个 HTTP GET 接口,用户通过请求访问该方法来生成代码文件。

String[] tableNames = Convert.toStrArray(tables);

参数 tables 是前端传入的表名列表,通常以逗号分隔的字符串。

使用 Convert.toStrArray(tables) 将其转换为字符串数组 tableNames

byte[] data = genTableService.downloadCode(tableNames);

调用 genTableService.downloadCode 方法生成代码文件,返回打包后的字节数据 data

genCode(response, data);

调用 genCode 方法,将生成的代码文件字节流写入到 HttpServletResponse 中,供用户下载。


该方法将生成的代码文件作为 ZIP 文件,通过 HTTP 响应返回给前端。

我们再来看看byte[] data = genTableService.downloadCode(tableNames);中downloadCode方法的具体内容:

这段代码实现了将一组表的代码生成结果打包为一个 ZIP 文件并返回为字节数组。以下是逐步的分析:

创建输出流

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  • 创建一个字节数组输出流,用于将生成的 ZIP 内容存储在内存中。
  • ByteArrayOutputStream 是 Java 提供的内存缓冲流,支持动态扩展。
ZipOutputStream zip = new ZipOutputStream(outputStream);

基于 outputStream 创建一个 ZipOutputStream,用于将多个文件打包成 ZIP 格式。

遍历表名并生成代码

for (String tableName : tableNames)
{
    generatorCode(tableName, zip);
}
  • 遍历表名数组:对传入的每个表名调用 generatorCode 方法,将其生成的代码内容写入到 zip 流中。
  • 方法调用generatorCode(tableName, zip)
    • 假设这是一个外部方法,用于根据表名生成对应代码文件,并写入到 zip
    • zip 是一个 ZipOutputStream,此方法应该负责为每个表生成一个 ZIP 条目(文件),并将内容写入。

关闭流

IOUtils.closeQuietly(zip);
  • 使用 Apache Commons IO 的 IOUtils.closeQuietly 工具方法,安全地关闭流。
  • 即使关闭时出现异常,closeQuietly 也会捕获并忽略它,防止影响程序运行。

返回字节数组

return outputStream.toByteArray();

调用 ByteArrayOutputStreamtoByteArray 方法,将内存中写入的 ZIP 数据转为字节数组并返回。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐