SpringBoot项目中使用easyexcel导入大量数据,正常运行后,一段时间后,出现cache creation in EhcacheManager failed,重启功能又恢复正常。

      最近项目中要求用excel导入大量交易数据的需求,就使用阿里巴巴的easyexcel工具包,进行导入。

 1、添加依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.0.5</version>
</dependency>

 2、创建excel实体类,easyexcel 根据value值去匹配excel的表头。

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class InQueryBalanceExerciseCashFlowExcel{

    @ExcelProperty(value = "日切日期")
    private String cutDayDate;

    @ExcelProperty(value = "交易编号")
    private String transactionNumber;

    @ExcelProperty(value = "备注")
    private String remarks 
}

 3、配置限制文件上传大小

servlet:
   multipart:
     max-file-size:200MB
     max-request-size:200MB  

4、同步配置nginx上传文件大小限制

5、Controller层通过MultipartFile的方式接收文件、因为需求是多个文件,同时导入,所以用list

 public ApiResult batcUploadFile(@RequestParam List<MutipartFile> mutipartFileList,
                                 @RequestParam List<String> fileTypeList,
                                 @RequestParam String engineDate,
                                 @RequestParam String dayType){
       LocalDateTime begintime = LocalDateTime.now();
       .........
       这里实现自己的逻辑,因为我这里是多线程同时
       导入5个文件,所以这里用List<MutipartFile> mutipartFileList 接收文件
       同时传了个fileTypeList进来。
       LocalDateTime endtime = LocalDateTime.now();
       System.out.println("总计耗时"+ChronoUnit.SECONDS.between(begintime,endtime))
}

6、service层,编写处理逻辑

protect String fileParsing(FileUploadVO vo,String waterNumber){
   List<MultipartFile> filelist = vo.getMultipartFile();
   List<String> filetypelist = vo.getFileType();
   CountDownLatch countDownLatch = new CountDownLatch(filetypelist.size())
   Map<String,Future> map = new HashMap<>();
   //循环处理文件,每个文件都构建一个task,通过线程池,多线程并发导入。
   int num = 0;
   for(MultipartFile file : filelist ){
       String filetype = filetypelist.get(num );
       //将各种参数,传递给task,最主要,将countDownLatch 传进去,控制并发
       TradeDataTask task = new TradeDataTask(....,countDownLatch);
       Future ftask = pool.submit(task);
       map.put(filetype,ftask)
   }
   //等待上面任务全部做完
   countDownLatch.await();
   ........
   //下面可以循环map,取出任务完成信息
   for(Map.Entry<String,Future> entry:map.entrySet()){
       Future ftask = entry.getValue();
       if(ftask.isDone() && !ftask.isCancelled()){
          message.append(ftask.get()).append(System.lineSeparator())
       }
   }
   return message.toString();
}

7、创建TradeDataTask类,处理文件

public class TradeDataTask implements Callable<String>{
    private MultipartFile multipartFile;
    
    private String fileType;
    
    private Class excel;
    //因为是多线程,所以这里把用的dao传进来
    private BaseDao baseDao
  //jpa保存,比较慢,所以这里新建了5个文件对应的jdbc保存数据库操作的接口,构建的时候,由外部传入
    private TradeDataInsertInte tradeDataInsert;
    
    private CountDownLatch countNum;

    .........
    @Override
    public String call() throws Exception{
      try{
          // 主要就是这一行,处理文件,excel变量,就是第二步创建的实体类class
           EasyExcel.read(multipartFile.getInputStream(),excel,new 
                      TradeDataListenner(baseDao,tradeDataInsert))
           //读取excel第一个sheet并指定表头是第二行
          .sheet(0).headRowNumber(2).doRead();
          return "文件处理成功,或者失败"
      }catch(Exception e){
          ....... 处理异常
      }finally{
         //处理完成,这里要释放资源,否则会一直卡住
         countNum.countDown();
      }
    }
}

8、最终拿到数据,进行校验,保存入库

public class TradeDataListener extends CommonAnalysisEventListenner{
     privte TradeDataInsertInte tradeDataInsert;
     
     private BaseDao baseDao;
      
     @Override
     void saveData(List list){
        ........
        //这里,list就拿到了,excel中的数据了,这里可以进行一些,数据校验
        tradeDataInsert.saveLargeData(list);
     }
     
}

9、一切核心就是这个EasyExcel监听器

//主要是继承的这个AnalysisEventListenner抽象类
public abstract class CommonAnalysisEventListenner<T> extends AnalysisEventListenner<T>{
    
    //决定多所少行保存一次
    private static final int BATCH_COUNT = 10000;
    
    final List<T> catchList = new LinkedList<>();

    //由子类去实现
    abastract void saveData(List<T> list)
    
    //这个方法,每解析一行,就会调用一次
    @Override
    public void invoke(T t,AnalysisContext analysisContext){
        this.catchList.add(t)
        if(this.catchList.size() >= this.BATCH_COUNT){
             this.saveData(catchList)
             this.catchList.clear();
        }
    }


    //所有数据解析完成,调用
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext){saveData(catchList)}
}

   现在所有的工作,都完成了,跑起来一切都OK了,大功告成。可过了十天半个月,测试服务器上导入,突然报错了,cache XXXXXXXX creation in EhcacheManager failed 一脸懵逼,

      最后查询问题发现是由于springboot 启动的时候,默认会再/tmp目录下,创建一些临时文件夹,以及文件。但是linux系统,对/tmp目录下的文件,如果十天没有更新,就会自动清除,导致我们导入失败。

解决方法,网络上有人说是更改默认的目录,配置文件配置 server.tomcat.basedir=/tmp/tomcat 指定目录。经过测试,没有效果,导入文件的临时目录仍然创建在/tmp下。

其实只需要在启动springboot的时候,加上参数-Djava.io.tmpdir=/xxxx/xx(注意这个路径,必须要存在)

自己记录一下,工作中遇到的问题。好记性不如烂笔头

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
是的,如果你想在SpringBoot项目使用EasyExcel读取对象List集合的数据进行导出功能,需要通过以下步骤添加EasyExcel的依赖版本3.0.5: 1. 在pom.xml文件添加EasyExcel的依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> ``` 2. 在实体类定义需要导出的List集合,例如: ```java public class User { private String name; private Integer age; private List<String> hobbies; // 省略getter和setter方法 } ``` 3. 在Controller编写导出Excel的方法,例如: ```java @GetMapping("/export") public void export(HttpServletResponse response) throws IOException { List<User> userList = userService.getUserList(); List<List<String>> data = new ArrayList<>(); for (User user : userList) { List<String> rowData = new ArrayList<>(); rowData.add(user.getName()); rowData.add(user.getAge().toString()); rowData.addAll(user.getHobbies()); data.add(rowData); } ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build(); WriteSheet writeSheet = EasyExcel.writerSheet(0, "用户信息").build(); excelWriter.write(data, writeSheet); excelWriter.finish(); } ``` 在这个例子,我们首先获取了用户列表,然后将每个用户的信息以List<String>的形式添加到一个二维List。接着,使用EasyExcel的ExcelWriter将数据写入到Excel,并通过WriteSheet指定了导出的Sheet名称。最后,通过finish方法关闭ExcelWriter并将数据写入到输出流,实现导出Excel的功能。 希望这个例子可以帮助你使用EasyExcel实现导出对象List集合的数据到Excel的功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值