当前位置: 首页 > wzjs >正文

企业网站建设知识应用技能土特产网站建设状况

企业网站建设知识应用技能,土特产网站建设状况,休闲吧网站建设,想做一个自己设计公司的网站怎么做描述 使用Java代码封装的一个Excel批量导入框架,使用EasyExcel完成excel文件方面的交互,重在整合功能,仅需少量代码就可以在自己的项目中快速引入该功能。可以流式分批读取Excel中的数据,避免OOM,使用多线程提高处理速…

描述

使用Java代码封装的一个Excel批量导入框架,使用EasyExcel完成excel文件方面的交互,重在整合功能,仅需少量代码就可以在自己的项目中快速引入该功能。可以流式分批读取Excel中的数据,避免OOM,使用多线程提高处理速度,异步线程处理便于前端查看导入进度与处理结果。

框架代码采取了设计模式中的策略模式,只需要实现其中的策略类(针对自己的业务来处理每行数据),就可以快速使用导入功能,并且给出了前端的配套代码示例(vue)。

demo项目地址:https://github.com/destinyol/excel-multi-import-progress

(demo项目不包括数据库交互部分,所以无法运行,只是演示代码如何使用)

框架项目文件结构:

image-20250209232807807

ps:修改ExcelImportMainTool 中的 BATCH_COUNT 可自定义每次从excel中读取多少行数据,默认1000行

效果展示

测试上传效果

可调参数

ExcelImportMainTool类中有一些可以根据实际情况自行调整的参数

public static final int BATCH_COUNT = 1000; // 批量处理,每批从excel中读取并处理的数据行数,可根据情况自行修改public int BATCH_INSERT_COUNT = 200; // 使用批量插入时的每批次处理数量(传入handleMultiDataAndSave函数的数组大小),可根据情况自行修改,可动态设置public static final boolean PROCESS_SAVE_RESULT_LIST = true; // redis保存进度条时是否保存报错结果数组ExcelResDto,true保存,false不保存

使用方法

1、继承EasyExcelReadDataAbstract抽象类并实现其中EasyExcelReadData接口的方法,该子类是对应EasyExcel导入的实体类,用来存储单行数据,需要实现其中的方法

public interface EasyExcelReadData {/*** 去掉每个字段首尾空格(若不需要则方法体为空即可)*      (处理过程中每行会调用一次)*/public void trimAllFields();/*** 为了排除表格空行(建议实现该方法,空行比较容易出现)*      检查该行中的每个属性是否都为null或空字符串,如果是,则返回true;否则返回false*      (处理过程中每行会调用一次)*/public boolean dataIsAllEmpty();}

例如

@Data
public class CustomerImportDto extends EasyExcelReadDataAbstract {@ExcelProperty(value = "客户名称")private String name;@ExcelProperty(value = "手机号")private String phone;// ***********************// 省略各种字段@Overridepublic boolean dataIsAllEmpty(){return (name == null || name.isEmpty()) &&(phone == null || phone.isEmpty());}@Overridepublic void trimAllFields() {if (name != null) name = name.trim();if (phone != null) phone = phone.trim();}
}

2、实现DataDealHandler接口及对应方法,该实现类是用于自定义的数据处理与保存,便于衔接不同的业务场景

(要用批量插入就实现handleMultiDataAndSave方法,要用逐条插入就实现handleOneDataAndSave

public interface DataDealHandler {/*** 返回模板表头行数(根据对应模板配置实现该方法,例如表头三行:return 3;)* @return*/public Integer getHeadRows();/*** 处理单条数据(比如去重,特殊判断,或者其他自定义业务)*  并自行保存该条数据到数据库* @param importData EasyExcelReadDataAbstract的子类* @return 返回结果内容(显示给前端,表格行号+错误内容)。若返回类为null,则该条数据导入成功,不用显示;若不为null,则将其放入错误结果集中*/@Transactional(rollbackFor = Exception.class)default public ExcelResDto handleOneDataAndSave(EasyExcelReadData importData){throw new RuntimeException("未实现逐条插入数据处理函数handleOneDataAndSave");}/*** 批量处理数据(比如去重,特殊判断,或者其他自定义业务)*  并自行保存数据到数据库,若抛出错误则这一批全部回滚* @param importDataList EasyExcelReadDataAbstract的子类list* @return 返回结果内容数组(显示给前端,表格行号+错误内容)。若数组长度为0,则全部成功;如果长度大于0,则将其放入错误结果集中*/@Transactional(rollbackFor = Exception.class)default public List<ExcelResDto> handleMultiDataAndSave(List<EasyExcelReadData> importDataList){throw new RuntimeException("未实现批量插入数据处理函数handleMultiDataAndSave");}}

3、直接调用

// --------------------------------------导入任务启动的地方---------------------------------
// 构造DataDealHandler的实现类的实例对象
DataDealHandlerImpl handler = new DataDealHandlerImpl(xxxxx,xxxxx自定义构造);
// 启动导入主函数并异步执行,返回redis中保存的该进度的processKey,可以直接返回给前端用于查询进度
// (逐条插入,需实现对应方法)
String processKey = ExcelImportMainTool.buildImport(EasyExcelReadDataAbstract的子类.class, handler, redisTemplate	// 进度保存在redis中,所以需要自行注入redisTemplate
).runAsyncSingle(multipartFile);// (批量插入,需实现对应方法)
String processKey = ExcelImportMainTool.buildImport(EasyExcelReadDataAbstract的子类.class, handler, redisTemplate	// 进度保存在redis中,所以需要自行注入redisTemplate
).setBatchInsertCount(250) // 设置批量插入每批传入`DataDealHandler`中的数据量,不设置则默认200行.runAsyncMulti(multipartFile);
// ---------------------------------------轮询或其他手段,获取任务进度-----------------------
// 获取进度(静态方法,需传入redisTemplate)
ImportProgress progress = ExcelImportMainTool.getProgress(redisTemplate, processKey);

至此整个功能就跑起来了

使用示例

数据实体类实现类

/*** 示例:easyExcel导入的数据实体类*      ( EasyExcelReadDataAbstract的子类 )*/
@Data
public class CustomerImportDto extends EasyExcelReadDataAbstract {@ExcelProperty(value = "销售")private String saleUserName;@ExcelProperty(value = "客户名称")private String name;@ExcelProperty(value = "联系人")private String contacts;@ExcelProperty(value = "联系电话")private String phone;@ExcelProperty(value = "统一社会信用代码")private String sucCode;@ExcelProperty(value = "法人")private String legalPerson;@ExcelProperty(value = "注册资本(单位万元)")private String registerMoney;@ExcelProperty(value = "客户地址")private String address;/*** 检查类中的每个属性是否为null或空字符串,如果是,则返回true;否则返回false* @return*/@Overridepublic boolean dataIsAllEmpty(){return (saleUserName == null || saleUserName.isEmpty()) &&(name == null || name.isEmpty()) &&(contacts == null || contacts.isEmpty()) &&(phone == null || phone.isEmpty()) &&(sucCode == null || sucCode.isEmpty()) &&(legalPerson == null || legalPerson.isEmpty()) &&(registerMoney == null || registerMoney.isEmpty()) &&(address == null || address.isEmpty());}@Overridepublic void trimAllFields() {if (saleUserName != null){saleUserName = saleUserName.replaceAll("\\s+", "");}if (name != null) name = name.trim();if (contacts != null) contacts = contacts.trim();if (phone != null) phone = phone.trim();if (sucCode != null) sucCode = sucCode.trim();if (legalPerson != null) legalPerson = legalPerson.trim();if (registerMoney != null) registerMoney = registerMoney.trim();if (address != null) address = address.trim();}
}

策略类实现类

/*** 示例:客户批量导入handler*      ( DataDealHandler实现类 )*/
public class CustomerImportDataHandler implements DataDealHandler {private UserMapper userMapper;private TdCustomerMapper tdCustomerMapper;public CustomerImportDataHandler(UserMapper userMapper, TdCustomerMapper tdCustomerMapper) {this.userMapper = userMapper;this.tdCustomerMapper = tdCustomerMapper;}@Overridepublic Integer getHeadRows() {return 2;}@Override@Transactional(rollbackFor = Exception.class)public ExcelResDto handleOneDataAndSave(EasyExcelReadData importData) {CustomerImportDto customerImportDto = (CustomerImportDto) importData;ExcelResDto resDto = null;TdUser user = userMapper.queryOneByUserName(customerImportDto.getSaleUserName());if (user == null){resDto = ExcelResDto.build(customerImportDto,"该姓名用户不存在:("+customerImportDto.getSaleUserName()+") ,对应客户名:"+customerImportDto.getName());return resDto;}TdCustomer step = new TdCustomer();step.setName(customerImportDto.getName());step.setContacts(customerImportDto.getContacts());step.setAddress(customerImportDto.getAddress());step.setPhone(customerImportDto.getPhone());step.setCreateBy(user.getUserId());step.setLegalPerson(customerImportDto.getLegalPerson());step.setSucCode(customerImportDto.getSucCode());step.setRegisterMoney(customerImportDto.getRegisterMoney());if (isBlank(step.getName())){resDto = ExcelResDto.build(customerImportDto,"客户名不能为空");return resDto;}TdCustomer customerByName = tdCustomerMapper.getCustomerByName(customerImportDto.getName());if (customerByName != null) {resDto = ExcelResDto.build(customerImportDto,"客户名重复:"+customerImportDto.getName());return resDto;}if (isBlank(step.getContacts())){resDto = ExcelResDto.build(customerImportDto,"客户联系人不能为空,客户名:"+customerImportDto.getName());return resDto;}if (isBlank(step.getPhone())){resDto = ExcelResDto.build(customerImportDto,"客户联系方式不能为空,客户名:"+customerImportDto.getName());return resDto;}boolean save = tdCustomerMapper.insert(step) != 0;if (!save){resDto = ExcelResDto.build(customerImportDto,"客户添加失败,客户名:"+customerImportDto.getName());}return resDto;}@Override@Transactional(rollbackFor = Exception.class)public List<ExcelResDto> handleMultiDataAndSave(List<EasyExcelReadData> importDataList) {// 结果数组List<ExcelResDto> res = new ArrayList<>();List<CustomerImportDto> customerImportDtoList = new ArrayList<>();for (EasyExcelReadData easyExcelReadData : importDataList) {customerImportDtoList.add((CustomerImportDto)easyExcelReadData);}List<TdCustomer> tdCustomerList = new ArrayList<>();for (CustomerImportDto customerImportDto : customerImportDtoList) {TdCustomer step = new TdCustomer();step.setName(customerImportDto.getName());step.setContacts(customerImportDto.getContacts());step.setAddress(customerImportDto.getAddress());step.setPhone(customerImportDto.getPhone());step.setLegalPerson(customerImportDto.getLegalPerson());step.setSucCode(customerImportDto.getSucCode());step.setRegisterMoney(customerImportDto.getRegisterMoney());}//==========================================================// 省略各种业务检查,判断重复之类的//==========================================================Boolean insetCheck = tdCustomerMapper.saveBatch(tdCustomerList);if (!insetCheck){for (CustomerImportDto customerImportDto : customerImportDtoList) {res.add(ExcelResDto.build(customerImportDto,customerImportDto.getName()+"添加失败"));}}return res;}
}

接口示例

	/*** excel 导入客户* @return*/@PostMapping("/importExcel")public Response importExcel(MultipartFile file){Response response = new Response();response.ret(0,"成功了");try {CustomerImportDataHandler handler = new CustomerImportDataHandler(userMapper,tdCustomerMapper);// 逐条插入String processKey = ExcelImportMainTool.buildImport(CustomerImportDto.class, handler, redisTemplate).runAsyncSingle(file);// 批量插入// String processKey = ExcelImportMainTool.buildImport(CustomerImportDto.class, handler, redisTemplate).runAsyncMulti(file);response.setData(processKey);} catch (Exception e) {e.printStackTrace();response.ret(111000,"出错了");}return response;}/*** 获取进度* @return*/@GetMapping("/getProgress")public Response getProgress(String key){Response response = new Response();response.ret(0,"成功了");try {ImportProgress progress = ExcelImportMainTool.getProgress(redisTemplate, key);response.setData(progress);} catch (Exception e) {e.printStackTrace();response.ret(111001,"出错了");}return response;}

文章转载自:

http://vm1BBIfM.crfyr.cn
http://cETZiqnT.crfyr.cn
http://HZsoolSi.crfyr.cn
http://OyVMGPbF.crfyr.cn
http://APL6dWD0.crfyr.cn
http://iBcgaaH1.crfyr.cn
http://t3MrVCR1.crfyr.cn
http://LW6UWVgj.crfyr.cn
http://jjN6Oosg.crfyr.cn
http://YI4y02oX.crfyr.cn
http://zcvGQSSg.crfyr.cn
http://IebiC0Hr.crfyr.cn
http://a6FiAFOG.crfyr.cn
http://EP3jAlv9.crfyr.cn
http://8QUogATC.crfyr.cn
http://Cyhzx2Sz.crfyr.cn
http://6ObBjJOD.crfyr.cn
http://pJX3JmJF.crfyr.cn
http://6jraPXc3.crfyr.cn
http://vkQvaeAU.crfyr.cn
http://t1sTZ3YS.crfyr.cn
http://iaoMHWBc.crfyr.cn
http://NWNr4nm2.crfyr.cn
http://0sgPJDaW.crfyr.cn
http://QhbU9yZ5.crfyr.cn
http://ucCl18mK.crfyr.cn
http://Avpn4R2B.crfyr.cn
http://8gSHcWcS.crfyr.cn
http://dUIganTc.crfyr.cn
http://vIqXRLOo.crfyr.cn
http://www.dtcms.com/wzjs/715484.html

相关文章:

  • 北京pk10网站建设wordpress4.6免费主题
  • 一般网站建设大概需要多少钱建设一个行业性的网站价格
  • 网站主页面设计php简单企业网站源码
  • 90设计手机站上海设计工作室排名
  • 工作室网站开发郑州做网站msgg
  • 苏州网站定制公司店铺营业执照在哪个网站做年审
  • 南昌免费网站建站模板广州市海珠区建设局五位一体网站
  • 网站策划报告书怎么做wordpress编辑器图片
  • 宁乡建设局网站做一个网站能卖多少钱
  • 汝阳县建设局网站织梦5.5模版安装上去为什么打开网站图片不能显示教程
  • 建设网站多钱p2p做网站
  • 手机企业网站源码wordpress 多站点主题
  • 网站建设价格差异好大中铁建设集团董事长
  • 建网站自学.net做网站c#
  • mooc网站开发流程图镇江网站建设制作方案
  • 旅游电子商务网站设计wordpress 添加文章格式
  • 网站建设与维护岗位职责美食网站首页模板
  • 北京网站seo策划网站建设好了怎么发布
  • 网站查询ip地址查询松江集团网站建设
  • 平乡网站建设重庆网站设计排名
  • 南昌那个公司做网站好做微网站用什么框架
  • 购物网站的搜索框用代码怎么做用在线网站做的简历可以吗
  • 做一家视频网站吗个体工商户在线注册
  • 二手商城网站建设论文思勤传媒网站建设公司
  • 建设电子商务网站的花费项目计划书怎么写
  • 建立网站的费用平面设计素材网
  • 哪里做网站最便宜宁波淘宝网站建设
  • 网站源代码制作百度视频下载
  • 刷会员网站怎么做程序界面设计
  • 手机网站 微信小程序网页设计报价表