使用EasyExcel实现数据导入功能 监听器配置 直接用!!!

本文介绍了阿里巴巴的EasyExcel库,它在Java中提供了一种内存友好的方式来处理Excel文件,对比了ApachePOI和jxl等框架,并展示了如何在项目中引入依赖、创建实体类和监听器以实现数据导入功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.介绍

阿里巴巴的EasyExcel是一种Java语言编写的开源库,用于简化Excel文件的导入和导出操作。在Java中解析Excel,比有名的框架有Apache POI和jxl,但是他们都有个严重的问题就是非常耗内存。相比EasyExcel在处理大型Excel文件时,EasyExcel能够有效地管理内存,避免出现内存溢出等问题,而且也比较简单。

 二.需要引入的pom依赖
 <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
 </dependency>
三.导入数据

1.准备ExcelModel实体类对应Excel表格

 

@Data
public class ExcelModel {

  @ExcelProperty("ID")
  private Long id;
  @ExcelProperty("姓名")
  private String name;
  @ExcelProperty("性别")
  private String sex;
  @ExcelProperty("年龄")
  private Integer age;

@ExcelProperty()注解里面的值对应Excel表格里面的第一行的内容,循序无所谓

2.准备 文件读取监听器

1.创建一个DataListener监听器类,然后直接implements实现ReadListener接口,接口里面放写好的Excel实体类,只需要重写invoke()方法和doAfterAllAnalysed()方法

invoke()方法的参数是你对应的Excel实体类 (ExcelModel) 和(AnalysisContext context)

咱们直接看代码

@Component
public class DataListener implements ReadListener<ExcelModel> {
  //日志 
  private static final Logger LOGGER = LoggerFactory.getLogger(DataListener.class);
  //每次最多导入条数
  private static final int BATCH_COUNT = 2000;

  //执行批量添加的service
  @Resource
  private SysUserService sysUserService;

  //数据集合
  List<SysUser> poList = new ArrayList<>();
  //读取失败的Excel文件索引行数集合
  List<Integer> failedRowIndexList = new ArrayList<>();

  //无参构造方法
  public MailDataListener() {

  }

  //使用这个构造方法,Listener是不被spring所管理的
  //所以我们自己在外面new Listener的时候把service传进来
  public MailDataListener(SysUserService sysUserService) {
    this.sysUserService = sysUserService;
  }

  //这个是按照Excel表格来进行每行读取的 一行一行读取
  @Override
  public void invoke(ExcelModel excelModel, AnalysisContext context) {
    ReadRowHolder readRowHolder = context.readRowHolder();
    //Excel的行索引
    Integer rowIndex = readRowHolder.getRowIndex() + 1;
    try {
      //对应数据库的实体类
      SysUser sysUser = new SysUser();
      //通过get获取Excel中的数据
      //可以在这做一些数据处理,看自己需求
      Long id = excelModel.getId();
      String name = excelModel.getName();
      ....
      sysUser.setId(id);
      sysUser.setName(name);
      ....

      //把实体类存到集合中
      poList.add(sysUser);

      //读取数超过2000进行一次数据写入
      //防止一次读取的数据量过大做的一个限制
      //因为在doAfterAllAnalysed()方法里面执行批量导入,这个方法是在读取完Excel才会执行
      if (poList.size() >= BATCH_COUNT) {
        sysUserService.insertByPoListCheck(poList);
        poList.clear();//清除list中的数据
      }
      LOGGER.info("行索引数: [%s] -> Excel数据: [%s]", rowIndex,
        JsonUtil.toJsonString(excelModel));
    //try catch 用的Exception这样不管什么异常都捕获得到出错的Excel行数
    } catch (Exception e) {
      LOGGER.error("行索引数: [%s] -> 失败的Excel数据: [%s]", rowIndex,
        JsonUtil.toJsonString(excelModel));
      //收集失败的Excel行索引 通过getFailedRows()返回
      failedRowIndexList.add(rowIndex);
    }
  }

  //最后执行,读取完整个Excel执行
  //先打印下日志,然后直接批量导入操作
  @Override
  public void doAfterAllAnalysed(AnalysisContext context) {
    LOGGER.info("所有数据读取完毕!");
    try {
      if (!poList.isEmpty()) {
        sysUserService.insertByPoListCheck(poList);
      }
    } catch (ResDBEffectCheckException e) {
      throw new RuntimeException("Insert User Check Error!");
    }
  }

  //获取读取失败的Excel行索引数集合
  public List<Integer> getFailedRows() {
    return failedRowIndexList;
  }

}

JsonUtil的方法就是自己封装的ObjectMapper的writeValueAsString方法

public class JsonUtil {

  private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);

  private static final ObjectMapper objectMapper = new ObjectMapper();

  public static <T> String toJsonString(T obj) {
    try {
      return objectMapper.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
      LOGGER.error("Failed to convert object to JSON string", e);
      return null;
    }
  }

}

 剩下的就比较简单了

3.service层和mapper层代码

service 对应 controller

public class SendService {

  @Resource
  private SysUserService sysUserService;

  public List<Integer> batchSending(MultipartFile file) {
      if (file == null) {
        throw new NullInvokeParamRuntimeException();
      }
      try {
        //文件转成流的形式
        InputStream inputStream = file.getInputStream();
        //new一个监听器  把service传进去 
        DataListener dataListener = new DataListener(sysUserService);
        //使用这个的.read方法 参数为 文件 对应excel的实体类 new好的监听器
        EasyExcelFactory.read(inputStream, ExcelModelBo.class, dataListener)
          .sheet(0) //指定读取第一个工作表
          .headRowNumber(1)  //指定标题行在第一行
          .doRead();  //执行实际的读取操作

        //最后返回监听器里写好的获取读取失败行数的方法
        return dataListener.getFailedRows();

      } catch (IOException e) {
        throw new RuntimeException();
      }
    }

}

service 对应mapper

public class SysUserService {

  @Resource
  private SysUserMapper sysUserMapper;

  public int insertByPoList(List<SysUser> poList) {
    return sysUserMapper.insertByPoList(poList);
  }

  public void insertByPoListCheck(List<SysUser> poList) throws ResDBEffectCheckException {
    int i = insertByPoList(poList);
    if (i == 0) {
      throw new ResDBEffectCheckException("Insert Mail DB Effect Check Error! Source [%s]", 
  poList);
    }
  }
}

mapper

  @Insert("""
    <script>
    INSERT INTO sys_user_
      (id, name, sex, age)
    VALUES
    <foreach collection='list' item='item' index='index' separator=','>
      (#{item.id}, #{item.name}, #{item.sex}, #{item.age})
    </foreach>
    </script>
    """)
  int insertByPoList(@Param("list") List<SysUser> list);

4.controller层代码

@Resource
SendService sendService


@PostMapping("/batch")
public ResponseEntity<Object> batchSend(@RequestPart("file") MultipartFile file) {
  return new ResponseEntity<>(ResponseCode.OK, sendService.batchSending(file));
}

                                             有用的话大家可以点个赞啊  蟹蟹!!!

### 回答1: EasyExcel是一个Java语言开发的开源框架,可以帮助开发人员快速读写Excel文件。如果你想使用EasyExcel实现批量导入,你可以使用以下步骤: 1. 引入EasyExcel依赖:在项目的pom.xml文件中加入如下代码: ``` <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.8</version> </dependency> ``` 2. 定义Excel数据模型:定义一个Java Bean类,表示Excel中的一行数据,如: ``` @Data public class ImportData { @ExcelProperty(value = "姓名", index = 0) private String name; @ExcelProperty(value = "年龄", index = 1) private Integer age; @ExcelProperty(value = "邮箱", index = 2) private String email; } ``` 3. 实现批量导入:编写代码读取Excel文件,并将每行数据映射到ImportData对象中,如: ``` InputStream inputStream = new FileInputStream(file); EasyExcel.read(inputStream, ImportData.class, new DataListener()).sheet().doRead(); ``` 以上代码可以实现从Excel文件批量导入数据功能。更详细的使用方法可以参考EasyExcel的官方文档。 ### 回答2: 使用easyExcel实现批量导入需要以下步骤: 1. 引入easyExcel库:通过在项目的依赖中添加easyExcel库的引用。 2. 创建实体类:根据需要导入的Excel数据结构,创建对应的实体类,每个字段要与Excel中的列一一对应。 3. 创建解析监听器:创建一个类实现AnalysisEventListener接口,并重写相应的方法,用于处理解析后的每一行数据。可以在process方法中进行业务逻辑的处理,比如将数据存入数据库或者其他操作。 4. 创建导入任务:在需要进行批量导入的地方,创建导入任务。可以通过指定实体类和解析监听器,调用EasyExcel的read方法来进行导入。 5. 配置导入参数:可以通过使用ReadSheet对象的setHeadRowNumber方法指定Excel中的表头所在的行数。还可以通过使用ReadSheet对象的setClazz方法指定导入数据的实体类。 6. 执行导入:调用EasyExcel的read方法,并传入导入任务、解析监听器导入参数,开始执行导入操作。 7. 处理解析结果:在解析监听器中,可以重写doAfterAllAnalysed方法,在导入完成后进行一些后续操作,比如进行结果统计和提示。 以上是使用easyExcel实现批量导入的基本步骤。根据不同的业务需求,可能还需要进行一些额外的配置和处理。总的来说,easyExcel提供了简单易用的API,使得批量导入数据变得更加方便和高效。 ### 回答3: 使用easyExcel实现批量导入可以分为以下几个步骤: 1. 引入依赖:首先,在项目的pom.xml文件中引入easyExcel的依赖。例如: ``` <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.3.4</version> </dependency> ``` 2. 创建Excel读取监听器:通过继承`AnalysisEventListener`类,创建一个自定义的监听器类,用于处理导入的Excel数据。可以重写其中的`invoke()`方法,在该方法中对每一行数据进行处理。例如: ```java public class ExcelListener extends AnalysisEventListener<User> { private List<User> userList = new ArrayList<>(); @Override public void invoke(User data, AnalysisContext context) { userList.add(data); } @Override public void doAfterAllAnalysed(AnalysisContext context) { // 导入完成后的操作 } public List<User> getUserList() { return userList; } public void setUserList(List<User> userList) { this.userList = userList; } } ``` 3. 执行导入操作:通过`EasyExcel.read()`方法,将导入的Excel文件解析成一个个对象。可以指定读取的起始位置、监听器等。例如: ```java String fileName = "导入文件.xlsx"; InputStream inputStream = new FileInputStream(fileName); ExcelListener listener = new ExcelListener(); EasyExcel.read(inputStream, User.class, listener).sheet().headRowNumber(2).doRead(); List<User> userList = listener.getUserList(); // 对导入数据进行处理或保存到数据库等操作 ``` 4. 处理导入数据:获取到导入数据后,可以根据业务需求进行进一步的处理,比如验证数据的有效性、保存到数据库等。例如: ```java for (User user : userList) { // 验证数据的有效性 if (user.getName() != null && user.getAge() != null) { // 保存到数据库或其他操作 } else { // 忽略无效数据或进行错误提示 } } ``` 通过以上步骤,就可以使用easyExcel实现批量导入功能。这个库提供了很多灵活的配置选项,可以根据具体需求进行调整和扩展。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值