有了这个开源工具后,我五点就下班了
Posted IT学习日记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有了这个开源工具后,我五点就下班了相关的知识,希望对你有一定的参考价值。
文章目录
前言
一个优秀的开发者,一定是会利用各种工具来提升自己的开发效率。 前段时间,博主在Gitee/Github开源了一个提升开发效率的工具,工具内集成了各种常用工具如csv、excel、ftp、文件系统等等,只需要简单调用API,就可以得到想要的结果,可以极大帮助开发者提升效率,下面来一起看看这款工具如何使用吧。
工具介绍
报表的导出、导入功能、文件上传、下载等在平常业务中是最常见不过的功能了,许多小伙伴在开发的时候才会去网上找之前别人编写过的案例参考,但是许多博客记载的都是时间比较长远或者不完整的代码,这导致在引入的时候还要处理引入的许多未知问题。
现在博主开源的“轮子之王”包含了这些常见的功能,源码全开发,每种功能都有相应的例子说明,项目会持续更新迭代,有问题还可以及时给项目提issue,相信比大多数网上的博客代码可靠性更高。
项目地址如下:
Github:https://github.com/it-learning-diary/it-wheels-king
Gitee:https://gitee.com/it-learning-diary/it-wheels-king
项目结构如下:
一、excel工具
该工具实现采用的是开源的easyexcel框架。easyexcel是阿里的开发人员对poi框架进行了优化,解决了poi在大数据量时可能出现OOM异常,并且兼容xls和xlsx两种文件类型的一个开源框架。
excel工具集成功能如下:
- excel的导入(可以自定义转换后的excel数据处理的业务逻辑,支持抛出异常、事务回滚、记录解析时的异常数据)
- 导出(支持固定表头,兼容多sheet页和动态表头,兼容多sheet页)功能。
excel工具的特点如下:
使用过easyexcel框架的一些读者知道,每个导入功能都要写一个对应的Listener进行数据转换,在很多时间其实转换的逻辑都是类似的,不同的只不过是转换后数据处理的业务逻辑不一样。
本开源项目的excel工具则利用Java中的泛型和Java8中的Consumer接口将相同的部分(转换逻辑)抽取出来,不同的部分则单独传入(数据处理的业务逻辑),这样就避免了每个导入都需要创建一个相类似的Listerner,减少了类的创建和提高了开发效率。
部分源码如下:
/**
* 通用导入excel文件方法
*
* @param fileStream 导入的文件流
* @param rowDto 接收excel每行数据的实体
* @param rowAction 将接收到的实体进行自定义的业务处理逻辑方法
* @param <T> 实体类型
*/
public static <T> void importFile(InputStream fileStream, T rowDto, ThrowingConsumer<List<T>> rowAction)
// 获取excel通用监听器
ExcelImportCommonListener<T> commonListener = new ExcelImportCommonListener<>(rowAction);
// 读取excel文件并导入
EasyExcel.read(fileStream, rowDto.getClass(), commonListener).sheet().doRead();
/**
* excel文件导出(可以包含多个sheet页),固定表头(通过实体指定属性的方式)
* @param response
* @param fileName 导出文件名
* @param head 导出表头(多个sheet页就是多个集合元素)
* @param exportData 需要导出数据
* @param sheetNames sheet页的名称,为空则默认以:sheet + 数字规则命名
*/
public static <T> void exportFile(String fileName, List<T> head, List<List<T>> exportData, List<String> sheetNames, HttpServletResponse response)
if (Objects.isNull(response) || StrUtil.isBlank(fileName) || CollUtil.isEmpty(head))
log.info("ExcelExportUtil exportFile required param can't be empty");
return;
ExcelWriter writer = null;
try
response.setContentType(ExportConstant.EXCEL_CONTENT_TYPE);
response.setCharacterEncoding(ExportConstant.UTF_8);
response.setHeader(ExportConstant.CONTENT_DISPOSITION, ExportConstant.ATTACHMENT_FILENAME + fileName + ExportConstant.XLSX_SUFFIX);
// 设置导出的表格样式
HorizontalCellStyleStrategy horizontalCellStyleStrategy = getExportDefaultStyle();
writer = EasyExcel.write(response.getOutputStream()).registerWriteHandler(horizontalCellStyleStrategy).build();
for (int itemIndex = 0; itemIndex < exportData.size(); itemIndex++)
// 表头数据
Object headData = head.get(itemIndex);
// sheet页的数据
List<T> list = exportData.get(itemIndex);
WriteSheet sheet = EasyExcel.writerSheet(itemIndex, CollUtil.isEmpty(sheetNames) ? ExportConstant.SHEET_NAME + itemIndex + 1 : sheetNames.get(itemIndex)).head(headData.getClass()).build();
writer.write(list, sheet);
catch (Exception e)
log.error("ExcelExportUtil exportFile in error:", e);
finally
if (null != writer)
writer.finish();
使用案例如下(在工具中每个项目都有具体的案例,不懂的还可以留言跟博主沟通):
/**
* 导入用户数据案例
*
* @param file
*/
@Transactional(rollbackFor = Exception.class)
public void uploadUserListDemoWithExcel(MultipartFile file, String username) throws Exception
// 此处先校验导入的文件类型是否为excel
String type = FileTypeUtil.getType(file.getInputStream());
if (StrUtil.isBlank(type) || type.contains(ImportConstant.XLS_TYPE) || type.contains(ImportConstant.XLSX_TYPE))
// 返回校验失败信息
return;
User user = new User();
user.setId(100);
user.setName("外层");
user.setPassword("外层");
userService.save(user);
// 调用统一导入方法
ExcelImportUtil.importFile(file.getInputStream(), new UserDto(), UserServiceImpl::saveUserList);
/**
* 导出案例
*
* @param response
*/
public void exportUserListDemoWithExcel(HttpServletResponse response)
// 表头(使用excel中的注解定义,如果表头不固定,请使用ExcelExportUtil.exportWithDynamicData进行导出)
List<UserExportVo> head = Stream.of(new UserExportVo()).collect(Collectors.toList());
// 数据(使用两层list为了兼容多个sheet页,如果是不同的sheet页则放在不同的List集合中)
List<List<UserExportVo>> exportDataList = new ArrayList<>();
List<UserExportVo> exportItem = new ArrayList<>();
// 查询数据
List<User> dbData = userService.list();
// 将数据转换成导出需要的实际数据格式,此处只是演示
for (User user : dbData)
UserExportVo vo = new UserExportVo();
BeanUtil.copyProperties(user, vo);
exportItem.add(vo);
exportDataList.add(exportItem);
// sheet页名称-自定义,如果没有则传空
List<String> sheetNameList = Stream.of("sheet1").collect(Collectors.toList());
ExcelExportUtil.exportFile("user", head, exportDataList, sheetNameList, response);
二、csv工具
Csv即逗号分隔值,也可以称为字符分隔符,与excel等文件相比,excel文件中会包含许多格式信息,占用的空间会更大,所以Csv在很多大数据场景导出、导入场景是非常常见的。该工具实现采用的是开源的univocity-parsers框架实现。
之前有一篇专门讲解轮子之王项目为何使用univocity-parsers框架集成csv的详细过程,有兴趣的读者可以点击链接查看:集成csv工具的前因后果
部分源码如下:
/**
* 使用实体bean接收csv数据文件并进行数据落盘
*
* @param inputStream
* @param errorList
* @param rowDtoClass
* @param rowAction
* @param <T>
*/
public static <T> void importCsvWithBean(InputStream inputStream, List<String> errorList, Class rowDtoClass, ThrowingConsumer<List<T>> rowAction)
// 定义bean解析者:用于将csv中数据绑定到实体属性中,然后存储带list集合上
BeanListProcessor<T> rowProcessor = new BeanListProcessor<>(rowDtoClass);
CsvParserSettings setting = getDefaultSetting(errorList);
setting.setProcessor(rowProcessor);
// 创建csv文件解析
CsvParser csvParser = new CsvParser(setting);
csvParser.parse(inputStream);
// 获取数据映射后的集合
List<T> dataList = rowProcessor.getBeans();
// 校验必填字段
for (T row : dataList)
// 校验导入字段
ImportValid.validRequireField(row, errorList);
// 执行数据持久化
persistentBeanDataToDb(dataList, rowAction);
/**
* 导出csv文件(表头和行都以实体的方式)
*
* @param response
* @param head
* @param rowDataList
*/
public static <T> void exportCsvWithBean(HttpServletResponse response, String fileName, T head, List<T> rowDataList)
CsvWriter writer = null;
try
// 设置响应头格式
response.setContentType(ExportConstant.EXCEL_CONTENT_TYPE);
response.setCharacterEncoding(ExportConstant.UTF_8);
response.setHeader(ExportConstant.CONTENT_DISPOSITION, ExportConstant.ATTACHMENT_FILENAME + fileName + ExportConstant.CSV_SUFFIX);
// 设置导出格式
CsvWriterSettings setting = getDefaultWriteSetting();
// 创见bean处理器,用于处理写入数据
BeanWriterProcessor<?> beanWriter = new BeanWriterProcessor<>(head.getClass());
setting.setRowWriterProcessor(beanWriter);
// 导出数据
writer = new CsvWriter(response.getOutputStream(), setting);
writer.processRecords(rowDataList);
writer.flush();
catch (Exception e)
log.error("CsvExportUtil exportCsvWithBean in error:", e);
finally
if (Objects.nonNull(writer))
writer.close();
使用案例如下:
/**
* 导出案例
*
* @param response
*/
public void exportUserListWithCsv(HttpServletResponse response)
List<UserExportCsvVo> exportItem = new ArrayList<>();
// 查询数据
List<User> dbData = userService.list();
// 使用字符串数组方式作为表头导出csv数据
List<Object> head = Stream.of("id", "name", "password").collect(Collectors.toList());
List<List<Object>> dataList = new ArrayList<>();
for (User user : dbData)
List<Object> row = new ArrayList<>();
row.add(user.getId());
row.add(user.getName());
row.add(user.getPassword());
dataList.add(row);
CsvExportUtil.exportCsvWithString(response, "demo", head, dataList);
/**
* 导入用户数据案例(csv模式)
*
* @param file
*/
@Transactional(rollbackFor = Exception.class)
public void uploadUserListWithCsv(MultipartFile file) throws Exception
// 此处先校验导入的文件类型是否为csv
String type = FileTypeUtil.getType(file.getInputStream());
if (StrUtil.isBlank(type) || type.contains(ImportConstant.CSV_TYPE))
// 返回校验失败信息
return;
User user = new User();
user.setId(100);
user.setName("外层");
user.setPassword("外层");
userService.save(user);
List<String> errorLogList = new ArrayList<>();
// 调用统一导入方法
// 方式一:使用csv数据映射到dto实体的方式进行数据导入
//CsvImportUtil.importCsvWithBean(file.getInputStream(), errorLogList, UserCsvDto.class, UserServiceImpl::saveUserListWithCsv);
// 方式二、使用csv数据映射到字符串数组的方式进行数据导入
CsvImportUtil.importCsvWithString(file.getInputStream(), errorLogList, UserCsvDto.class, UserServiceImpl::saveUserListWithCsvStringArrDemo);
// 如果存在解析异常,输出解析异常并进行事务回滚
if (CollUtil.isNotEmpty(errorLogList))
throw new RuntimeException(StrUtil.toString(errorLogList));
三、ftp工具
Ftp文件上传下载相比excel、csv等出现的场景较少,但是,如果你参与的项目是政府或者涉及到第三方旧系统对接的时候,很多时候就需要使用到它。因为很多旧系统或者政府项目使用的技术比较旧或者有制度限制,一般都是以文件的形式与你进行交互,此时ftp工具就很有效了。
Ftp工具使用的commons-net开源框架进行实现,具体的集成流程之前单独使用一篇文章进行了非常详细的介绍,有需要的读者可以点击后面链接查看:手把手教你搭建ftp服务器,并用程序完成ftp上传下载功能
部分源码如下:
/**
* 上传
*
* @return
*/
public boolean upload(FtpUploadParam param)
boolean flag = false;
FTPClient ftpClient = new FTPClient();
//1 测试连接
if (connect(ftpClient, param.getHostname(), param.getPort(), param.getUsername(), param.getPassword()))
try
//2 检查工作目录是否存在,不存在则创建
if (!ftpClient.changeWorkingDirectory(param.getWorkingPath()))
ftpClient.makeDirectory(param.getWorkingPath());
// 将文件编码成Ftp服务器支持的编码类型(FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码。)
String fileName = new String(param.getSaveName().getBytes(ftpClientCharset), ftpServerCharset);
// 3 上传文件
if (ftpClient.storeFile(fileName, param.getInputStream()))
flag = true;
else
log.warn("FtpUtils uploadFile unsuccessfully!!");
catch (IOException e)
log.error("FtpUtils upload in error:", e);
finally
disconnect(ftpClient);
return flag;
/**
* @description: 下载ftp文件
* @param:
* @param: param
* @param: downloadFileName
* @return:
* @date: 2022/7/14 10:56
*/
public boolean download(FtpDownloadParam param, String downloadFileName)
FTPClient ftpClient = 有了这个开源工具后,明天争取5点钟下班了
为啥我的电脑 每天下午四点-五点都要自动重启.而且是无限重启.关机一个小时以上再开机就好了.