若依框架-代码生成器-源码-生成代码
前端代码位于@/views/tool/index.vue(Vue3版本在@/views/tool/gen/index.vue)可以看到,点击生成按钮后会触发点击事件,并通过点击事件调用handleGenTable方法。代码分析参数row:对象类型,代表一行数据,包含了tableNamegenType等属性。tbNames是表名,优先使用,如果为空,则取。
目录
概述
前端代码
前端代码位于@/views/tool/index.vue(Vue3版本在@/views/tool/gen/index.vue)
可以看到,点击生成按钮后会触发点击事件,并通过点击事件调用handleGenTable方法。
我们再定位到该方法,了解一下它的具体内容:
代码分析
参数 row
:对象类型,代表一行数据,包含了 tableName
、genType
等属性。
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();
调用 ByteArrayOutputStream
的 toByteArray
方法,将内存中写入的 ZIP 数据转为字节数组并返回。
更多推荐
所有评论(0)