springboot使用EasyExcel导入数据
1. 引入依赖
<!-- Easy Excel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
2. 建立对应实体类
假如,我想要读取的excel数据如下所示
那么我的实体类为
@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. 测试结果
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/