springboot使用EasyExcel导入数据

2023-12-13 22:11:13

springboot使用EasyExcel导入数据

1. 引入依赖

<!-- Easy Excel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.2.1</version>
</dependency>

2. 建立对应实体类

假如,我想要读取的excel数据如下所示

image-20231213140048360.png

那么我的实体类为

@Getter
@Setter
@ToString
public class UserInfoForExcel {
    @ExcelProperty(value = "ID")
    private String userId;
    @ExcelProperty(value = "账号")
    private String account;
    @ExcelProperty(value = "邮箱")
    private String email;
    @ExcelProperty(value = "昵称")
    private String nickname;
    @ExcelProperty(value = "年龄")
    private Integer age;
    @ExcelProperty(value = "生日")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date birthday;
}

3. 读取代码

前端是以file的形式将excel表传过来的,springboot默认用MultipartFile类型接收,假设读取处理过程在service层

@Service
public class UserService {

    public void handleExcelImport(MultipartFile excelFile) throws IOException {
        InputStream inputStream = excelFile.getInputStream();
        List<UserInfoForExcel> userInfoForExcels = EasyExcel.read(inputStream)
            	.head(UserInfoForExcel.class)	// 行头类型匹配
                .sheet(0)				// sheet(0)为第一张表位置
                .headRowNumber(1)       // 行头所在行位置
                .doReadSync();			// 同步结果返回
        System.out.println(userInfoForExcels);
    }
}

4. 测试接口

@RestController
@RequestMapping("userinfo")
public class UserInfoController {

    @Autowired
    UserService userService;

    @PostMapping("import")
    public String handleExcelImport(MultipartFile file) throws IOException {
        userService.handleExcelImport(file);
        return "读取成功";
    }
}

5. 测试结果

image-20231213185235689.png

6. 补充

以上是最简单的读,且读的时候将所有数据读取到内存中,再进行处理,这样数据量一大,会导致占用内存过高甚至OOM,EasyExcel提供了自定义Listener,在读取时进行自定义操作,例如每次只读取5条数据,避免大量数据占用内存。

这只是举个简单的例子,事实上Listener还可以做很多复杂的操作,详情可以搜索EasyExcel官网,看看其API

7. 自定义监听器

/**
 * 自定义EasyExcel监听器
 */
public class UserInfoListener implements ReadListener<UserInfoForExcel> {
    // 设置缓存数据量
    private static final int BATCH_COUNT = 5;

    // 缓存数据List
    private List<UserInfoForExcel> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    /**
     * 每条数据都会调用该方法
     * @param userInfoForExcel 读取的一行数据
     * @param analysisContext 上下文对象,包含excel表的很多基本信息
     */
    @Override
    public void invoke(UserInfoForExcel userInfoForExcel, AnalysisContext analysisContext) {
        cachedDataList.add(userInfoForExcel);
        if (cachedDataList.size()>=BATCH_COUNT){
            // 达到预定数据量,进行插入数据库操作
            // …… todo
            // 然后清空缓存数据
            cachedDataList.clear();
        }
    }

    /**
     * 所有数据执行完invoke,会调用该方法
     * 由于最后的数据可能没有达到缓存定义的BATCH_COUNT,导致最后缓存中的数据没有进行插入数据库操作,所以需要在此进行数据插入
     * @param analysisContext 上下文对象,包含excel表的很多基本信息
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 缓存List中剩余的数据进行插入数据库操作
        // …… todo
    }
}

有一点需要注意的是,如果在插入数据库操作时使用spring管理的dao,不能将Listener对象交由spring管理(即是贪图方便在该Listener上添加@Component等注释),而应该将操作数据库的dao通过Listener的有参构造器传进来。EasyExcel官网有特别提醒

8. 使用自定义的监听器

创建完自定义的监听器后,在读取时注册该监听器,并且读时不需要使用doReadSync,改为doRead即可

@Service
public class UserService {

    public void handleExcelImport(MultipartFile excelFile) throws IOException {
        InputStream inputStream = excelFile.getInputStream();
        EasyExcel.read(inputStream).head(UserInfoForExcel.class)
                .sheet(0)
                .registerReadListener(new UserInfoListener()) // 注册自定义监听器
                .headRowNumber(1)       //行头所在行位置
                .doRead();
    }

}

至此,EasyExcel的简单读描述完毕。

事实上EasyExcel的监听器还能做很多有用的事情,强烈建议到官网看文档,基本能解决95%的需求

官网地址:https://easyexcel.opensource.alibaba.com/

文章来源:https://blog.csdn.net/weixin_42510217/article/details/134980427
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。