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

专业设计vi公司推广优化seo

专业设计vi公司,推广优化seo,什么叫网站收录提交,网站搭建北京前提导出数据到Excel是非常常见的后端需求之一#xff0c;今天来推荐一款阿里出品的Excel操作神器#xff1a;EasyExcel。EasyExcel从其依赖树来看是对apache-poi的封装#xff0c;笔者从开始接触Excel处理就选用了EasyExcel#xff0c;避免了广泛流传的apache-poi导致的内… 前提导出数据到Excel是非常常见的后端需求之一今天来推荐一款阿里出品的Excel操作神器EasyExcel。EasyExcel从其依赖树来看是对apache-poi的封装笔者从开始接触Excel处理就选用了EasyExcel避免了广泛流传的apache-poi导致的内存泄漏问题。引入EasyExcel依赖引入EasyExcel的Maven如下dependencygroupIdcom.alibaba/groupIdartifactIdeasyexcel/artifactIdversion${easyexcel.version}/version /dependency 当前2020-09的最新版本为2.2.6。API简介Excel文件主要围绕读和写操作进行处理EasyExcel的API也是围绕这两个方面进行设计。先看读操作的相关API// 新建一个ExcelReaderBuilder实例 ExcelReaderBuilder readerBuilder  EasyExcel.read(); // 读取的文件对象可以是File、路径字符串或者InputStream实例 readerBuilder.file(); // 文件的密码 readerBuilder.password(); // 指定sheet可以是数字序号sheetNo或者字符串sheetName若不指定则会读取所有的sheet readerBuilder.sheet(); // 是否自动关闭输入流 readerBuilder.autoCloseStream(true); // Excel文件格式包括ExcelTypeEnum.XLSX和ExcelTypeEnum.XLS readerBuilder.excelType(ExcelTypeEnum.XLSX); // 指定文件的标题行可以是Class对象结合ExcelProperty注解使用或者ListListString实例 readerBuilder.head(Collections.singletonList(Collections.singletonList(head))); // 注册读取事件的监听器默认的数据类型为MapInteger,String第一列的元素的下标从0开始 readerBuilder.registerReadListener(new AnalysisEventListener() {Overridepublic void invokeHeadMap(Map headMap, AnalysisContext context) {// 这里会回调标题行文件内容的首行会认为是标题行}Overridepublic void invoke(Object o, AnalysisContext analysisContext) {// 这里会回调每行的数据}Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {} }); // 构建读取器 ExcelReader excelReader  readerBuilder.build(); // 读取数据 excelReader.readAll(); excelReader.finish(); 可以看到读操作主要使用Builder模式和事件监听或者可以理解为「观察者模式」的设计。一般情况下上面的代码可以简化如下MapInteger, String head  new HashMap(); ListMapInteger, String data  new LinkedList(); EasyExcel.read(文件的绝对路径).sheet().registerReadListener(new AnalysisEventListenerMapInteger, String() {Overridepublic void invokeHeadMap(MapInteger, String headMap, AnalysisContext context) {head.putAll(headMap);}Overridepublic void invoke(MapInteger, String row, AnalysisContext analysisContext) {data.add(row);}Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 这里可以打印日志告知所有行读取完毕}}).doRead(); 如果需要读取数据并且转换为对应的对象列表则需要指定标题行的Class结合注解ExcelProperty使用文件内容|订单编号|手机号| |ORDER_ID_1|112222| |ORDER_ID_2|334455|Data private static class OrderDTO {ExcelProperty(value  订单编号)private String orderId;ExcelProperty(value  手机号)private String phone; }MapInteger, String head  new HashMap(); ListOrderDTO data  new LinkedList(); EasyExcel.read(文件的绝对路径).head(OrderDTO.class).sheet().registerReadListener(new AnalysisEventListenerOrderDTO() {Overridepublic void invokeHeadMap(MapInteger, String headMap, AnalysisContext context) {head.putAll(headMap);}Overridepublic void invoke(OrderDTO row, AnalysisContext analysisContext) {data.add(row);}Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 这里可以打印日志告知所有行读取完毕}}).doRead(); 「如果数据量巨大建议使用MapInteger, String类型读取和操作数据对象否则大量的反射操作会使读取数据的耗时大大增加极端情况下例如属性多的时候反射操作的耗时有可能比读取和遍历的时间长」。接着看写操作的API// 新建一个ExcelWriterBuilder实例 ExcelWriterBuilder writerBuilder  EasyExcel.write(); // 输出的文件对象可以是File、路径字符串或者OutputStream实例 writerBuilder.file(); // 指定sheet可以是数字序号sheetNo或者字符串sheetName可以不设置由下面提到的WriteSheet覆盖 writerBuilder.sheet(); // 文件的密码 writerBuilder.password(); // Excel文件格式包括ExcelTypeEnum.XLSX和ExcelTypeEnum.XLS writerBuilder.excelType(ExcelTypeEnum.XLSX); // 是否自动关闭输出流 writerBuilder.autoCloseStream(true); // 指定文件的标题行可以是Class对象结合ExcelProperty注解使用或者ListListString实例 writerBuilder.head(Collections.singletonList(Collections.singletonList(head))); // 构建ExcelWriter实例 ExcelWriter excelWriter  writerBuilder.build(); ListListString data  new ArrayList(); // 构建输出的sheet WriteSheet writeSheet  new WriteSheet(); writeSheet.setSheetName(target); excelWriter.write(data, writeSheet); // 这一步一定要调用否则输出的文件有可能不完整 excelWriter.finish(); ExcelWriterBuilder中还有很多样式、行处理器、转换器设置等方法笔者觉得不常用这里不做举例内容的样式通常在输出文件之后再次加工会更加容易操作。写操作一般可以简化如下ListListString head  new ArrayList(); ListListString data  new LinkedList(); EasyExcel.write(输出文件绝对路径).head(head).excelType(ExcelTypeEnum.XLSX).sheet(target).doWrite(data); 实用技巧下面简单介绍一下生产中用到的实用技巧。多线程读使用EasyExcel多线程读建议在限定的前提条件下使用源文件已经被分割成多个小文件并且每个小文件的标题行和列数一致。机器内存要充足因为并发读取的结果最后需要合并成一个大的结果集全部数据存放在内存中。❝经常遇到外部反馈的多份文件需要紧急进行数据分析或者交叉校对为了加快文件读取笔者通常使用这种方式批量读取格式一致的Excel文件❞一个简单的例子如下Slf4j public class EasyExcelConcurrentRead {static final int N_CPU  Runtime.getRuntime().availableProcessors();public static void main(String[] args) throws Exception {// 假设I盘的temp目录下有一堆同格式的Excel文件String dir  I:\\temp;ListMapInteger, String mergeResult  Lists.newLinkedList();ThreadPoolExecutor executor  new ThreadPoolExecutor(N_CPU, N_CPU * 2, 0, TimeUnit.SECONDS,new LinkedBlockingQueue(), new ThreadFactory() {private final AtomicInteger counter  new AtomicInteger();Overridepublic Thread newThread(NotNull Runnable r) {Thread thread  new Thread(r);thread.setDaemon(true);thread.setName(ExcelReadWorker-  counter.getAndIncrement());return thread;}});Path dirPath  Paths.get(dir);if (Files.isDirectory(dirPath)) {ListFutureListMapInteger, String futures  Files.list(dirPath).map(path - path.toAbsolutePath().toString()).filter(absolutePath - absolutePath.endsWith(.xls) || absolutePath.endsWith(.xlsx)).map(absolutePath - executor.submit(new ReadTask(absolutePath))).collect(Collectors.toList());for (FutureListMapInteger, String future : futures) {mergeResult.addAll(future.get());}}log.info(读取[{}]目录下的文件成功,一共加载:{}行数据, dir, mergeResult.size());// 其他业务逻辑.....}RequiredArgsConstructorprivate static class ReadTask implements CallableListMapInteger, String {private final String location;Overridepublic ListMapInteger, String call() throws Exception {ListMapInteger, String data  Lists.newLinkedList();EasyExcel.read(location).sheet().registerReadListener(new AnalysisEventListenerMapInteger, String() {Overridepublic void invoke(MapInteger, String row, AnalysisContext analysisContext) {data.add(row);}Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info(读取路径[{}]文件成功,一共[{}]行, location, data.size());}}).doRead();return data;}} } 这里采用ThreadPoolExecutor#submit()提交并发读的任务然后使用Future#get()等待所有任务完成之后再合并最终的读取结果。❝注意一般文件的写操作不能并发执行否则很大的概率会导致数据错乱❞多Sheet写多Sheet写其实就是使用同一个ExcelWriter实例写入多个WriteSheet实例中每个Sheet的标题行可以通过WriteSheet实例中的配置属性进行覆盖代码如下public class EasyExcelMultiSheetWrite {public static void main(String[] args) throws Exception {ExcelWriterBuilder writerBuilder  EasyExcel.write();writerBuilder.excelType(ExcelTypeEnum.XLSX);writerBuilder.autoCloseStream(true);writerBuilder.file(I:\\temp\\temp.xlsx);ExcelWriter excelWriter  writerBuilder.build();WriteSheet firstSheet  new WriteSheet();firstSheet.setSheetName(first);firstSheet.setHead(Collections.singletonList(Collections.singletonList(第一个Sheet的Head)));// 写入第一个命名为first的SheetexcelWriter.write(Collections.singletonList(Collections.singletonList(第一个Sheet的数据)), firstSheet);WriteSheet secondSheet  new WriteSheet();secondSheet.setSheetName(second);secondSheet.setHead(Collections.singletonList(Collections.singletonList(第二个Sheet的Head)));// 写入第二个命名为second的SheetexcelWriter.write(Collections.singletonList(Collections.singletonList(第二个Sheet的数据)), secondSheet);excelWriter.finish();} } 效果如下分页查询和批量写在一些数据量比较大的场景下可以考虑分页查询和批量写其实就是分页查询原始数据 - 数据聚合或者转换 - 写目标数据 - 下一页查询....。其实数据量少的情况下一次性全量查询和全量写也只是分页查询和批量写的一个特例因此可以把查询、转换和写操作抽象成一个可复用的模板方法int batchSize  定义每篇查询的条数; OutputStream outputStream  定义写到何处; ExcelWriter writer  new ExcelWriterBuilder().autoCloseStream(true).file(outputStream).excelType(ExcelTypeEnum.XLSX).head(ExcelModel.class); for (;;){ListOriginModel list  originModelRepository.分页查询();if (list.isEmpty()){writer.finish();break;}else {list 转换- ListExcelModel excelModelList;writer.write(excelModelList);} } 参看笔者前面写过的一篇非标题党生产应用文章《百万级别数据Excel导出优化》适用于大数据量导出的场景代码如下Excel上传与下载❝下面的例子适用于Servlet容器常见的如Tomcat应用于spring-boot-starter-web❞Excel文件上传跟普通文件上传的操作差不多然后使用EasyExcel的ExcelReader读取请求对象MultipartHttpServletRequest中文件部分抽象的InputStream实例即可PostMapping(path  /upload) public ResponseEntity? upload(MultipartHttpServletRequest request) throws Exception {MapString, MultipartFile fileMap  request.getFileMap();for (Map.EntryString, MultipartFile part : fileMap.entrySet()) {InputStream inputStream  part.getValue().getInputStream();MapInteger, String head  new HashMap();ListMapInteger, String data  new LinkedList();EasyExcel.read(inputStream).sheet().registerReadListener(new AnalysisEventListenerMapInteger, String() {Overridepublic void invokeHeadMap(MapInteger, String headMap, AnalysisContext context) {head.putAll(headMap);}Overridepublic void invoke(MapInteger, String row, AnalysisContext analysisContext) {data.add(row);}Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info(读取文件[{}]成功,一共:{}行......, part.getKey(), data.size());}}).doRead();// 其他业务逻辑}return ResponseEntity.ok(success); } 使用Postman请求如下使用EasyExcel进行Excel文件导出也比较简单只需要把响应对象HttpServletResponse中携带的OutputStream对象附着到EasyExcel的ExcelWriter实例即可GetMapping(path  /download) public void download(HttpServletResponse response) throws Exception {// 这里文件名如果涉及中文一定要使用URL编码,否则会乱码String fileName  URLEncoder.encode(文件名.xlsx, StandardCharsets.UTF_8.toString());// 封装标题行ListListString head  new ArrayList();// 封装数据ListListString data  new LinkedList();response.setContentType(application/force-download);response.setHeader(Content-Disposition, attachment;filename  fileName);EasyExcel.write(response.getOutputStream()).head(head).autoCloseStream(true).excelType(ExcelTypeEnum.XLSX).sheet(Sheet名字).doWrite(data); } 这里需要注意一下文件名如果包含中文需要进行URL编码否则一定会乱码。无论导入或者导出如果数据量大比较耗时使用了Nginx的话记得调整Nginx中的连接、读写超时时间的上限配置。使用SpringBoot需要调整spring.servlet.multipart.max-request-size和spring.servlet.multipart.max-file-size的配置值避免上传的文件过大出现异常。小结EasyExcel的API设计简单易用可以使用他快速开发有Excel数据导入或者导出的场景真是广大 Javaer 人的福音。 往期推荐 Java新特性数据类型可以扔掉了多图带你彻底理解Java中的21种锁JDK 竟然是这样实现栈的关注下方二维码收获更多干货
http://www.pierceye.com/news/54473/

相关文章:

  • 东莞教育平台网站建设砍柴网wordpress
  • 海晏县公司网站建设好用的wordpress主题
  • 专业的个人网站建设网站做系统叫什么软件有哪些
  • 自助建站系统官方版学网页设计大概需要多少钱?
  • 个人电影网站做APP违法吗wordpress添加优酷视频播放器
  • 小松建设官方网站网站制作费用大概多少
  • 哪家网站做旅游攻略好北京网络推广公司
  • php 读取网站文件wordpress 纯文字主题
  • 做网站备案需要啥资料杭州万户网络
  • 福州网上商城网站建设wordpress外卖
  • 怎么做论坛的网站哪些网站是用vue做的
  • 河北建设厅网站首页专业网站建设质量推荐
  • 手把手教你做网站7网站开发培训班 上地
  • 四川网站建设 四川冠辰科技免费crm网站下载
  • 网站平面设计完成后 与客户怎样沟通山西建设注册中心网站
  • 品牌网站建设找顺的长沙人才网最新招聘信息
  • 免费网站域名注册个人门户网站界面设计模板下载
  • 旅游搜索网站开发网站源码下载教程
  • 娄底市城乡建设局网站色块设计网站
  • 北京高端网站建设系统什么是网站设计
  • 自己切片做网站沈阳市住房和城乡建设局网站
  • 企业网站建设的总体目标自己做蛋糕有什么网站吗
  • 织梦做第一个网站平面设计报价明细表
  • 住房和城乡建设部中国建造师网站可以直接进入的正能量网站老狼
  • 课题网站建设验收总结报告成都建设银行招聘网站
  • 南京市建设档案馆网站邢台市建设银行网站
  • 皖icp阜阳网站建设设置网站关键词
  • 潜江公司做网站网站建设需要多少钱
  • 云南省文山州网站建设网站怎么更改后台登陆密码
  • 网站建设流程策划方案北京朝阳区属于几环