编辑 | blame | 历史 | 原始文档

Excel导入

一、普通导入

  1. 在读取接口的基础上增加逻辑,代码如下
    ~~~java
    @PostMapping("write-notice")
    public R writeNotice(MultipartFile file) {
    List noticeList = new ArrayList<>();
    List list = ExcelUtil.read(file, NoticeExcel.class);
    list.forEach(noticeExcel -> {
    String category = DictCache.getKey("notice", noticeExcel.getCategoryName());
    noticeExcel.setCategory(Func.toInt(category));
    Notice notice = BeanUtil.copy(noticeExcel, Notice.class);
    noticeList.add(notice);
    });
    return R.data(noticeService.saveBatch(noticeList));
    }
    ~~~
  2. 主要核心为这几行代码,其中使用了BeanUtilNoticeExcel转换成了Notice,性能层面可以放心,它与new完再set相差无几,要注意的就是两个bean的字段需要保持一致,才可以转换成功。
  • List<Notice> noticeList = new ArrayList<>();
  • Notice notice = BeanUtil.copy(noticeExcel, Notice.class);
  • noticeList.add(notice);
  • noticeService.saveBatch(noticeList)
  1. 重启服务,使用postman调用对应接口,可以看到返回成功
    ![](../../images/screenshot_1586830089871.png)
  2. 刷新下数据库,可以看到5条数据已经入库成功
    ![](../../images/screenshot_1586830167625.png)
  3. 以上为普通导入,仅作为一种demo方式快速实现功能,不推荐大家使用到实际业务。因为很多时候需要导入的Excel会非常大,java的List容量是有限的,若数据量太大将会导致OOM,所以这种方式不推荐,那么下面就来实操下针对实际业务场景的excel导入方案。

二、进阶导入

  1. 在开动之前,我们先看一下官方文档,找到监听器的例子
    ![](../../images/screenshot_1586832729944.png)
    ![](../../images/screenshot_1586832747026.png)
  2. 从例子可以看出,针对每一个Bean,都需要新建一个Listener,继承AnalysisEventListener,指定类型。这样调用API读取的时候,就会将数据写入监听器从而实现我们的业务逻辑
  3. ExcelUtil对其进行了封装,抽出了通用的Listener,这样不需要每个Bean都实现AnalysisEventListener,只需要编写最简的导入逻辑便可
  4. 实现主要逻辑代码如下,为了防止大数据量OOM,设定了每3000条便会执行一次入库操作。
    ![](../../images/screenshot_1586833101484.png)
    ![](../../images/screenshot_1586833110128.png)
  5. 新建NoticeImporter,并迁移上一节相关代码
    ~~~java
    /**
  • 用户数据导入类
    *
  • @author Chill
    */
    @RequiredArgsConstructor
    public class NoticeImporter implements ExcelImporter {

private final INoticeService service;

@Override
public void save(List data) {
data.forEach(noticeExcel -> {
String category = DictCache.getKey("notice", noticeExcel.getCategoryName());
noticeExcel.setCategory(Func.toInt(category));
Notice notice = BeanUtil.copy(noticeExcel, Notice.class);
service.save(notice);
});
}
}
~~~
![](../../images/screenshot_1586833283736.png)
6. 改造readNotice方法,传入NoticeImporter
~~~java
@PostMapping("write-notice")
public R writeNotice(MultipartFile file) {
NoticeImporter importer = new NoticeImporter(noticeService);
ExcelUtil.save(file, importer, NoticeExcel.class);
return R.success("操作成功");
}
~~~
7. 重启服务,调用postman查看结果,发现数据导入成功,业务也完全解耦
![](../../images/screenshot_1586833513313.png)
![](../../images/screenshot_1586833571237.png)
8. 在导入的数据中,发现create_user、create_dept、update_user三个字段为空,是因为我们一开始对其进行了接口放行,没有传递token,所以未获取到。现在加上token再次调用接口查看返回结果,发现正确无误
![](../../images/screenshot_1586833698178.png)
![](../../images/screenshot_1586833789465.png)