1. 创建项目,导入easy excel的依赖
<!-- easy excel 依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
<!-- mybatis 依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<!-- lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.0</version>
<scope>provided</scope>
</dependency>
<!--mybatis-plus 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
2. 配值application.yml
文件
server:
port: 8081
# 配置数据库连接
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/portdemo?serverTimezone=UTC&characterEncoding=utf-8
username: root
password: 123456
application:
name: demoExport
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 配置mybatis-plus 打印控制台日志
3.创建数据库表实体
/**
* @Description 用户表对应实体
* @Author small Geng
* @Data 2022/11/17 12:59
*/
@Data
@TableName("sys_user")
@ContentRowHeight(18)//内容行高
@HeadRowHeight(25)//标题行高
@ColumnWidth(20)//列宽,可设置成员变量上
public class User {
@ExcelProperty(index = 0, value = "申请人ID")
private Integer userId;
@ExcelProperty(index = 1, value = "申请人姓名")
private String userName;
@ExcelProperty(index = 2, value = "申请人身份证号")
private String userCard;
@ExcelProperty(index = 3, value = "申请人班级")
private String userClass;
@ExcelProperty(index = 4, value = "申请人邮箱")
private String userMail;
}
4. 业务逻辑
4.1 导出excel
/**
* 导出excel
* @param response
*/
@GetMapping("downLoad")
public void downLoad(HttpServletResponse response) throws IOException {
List<User> users = exportService.list();
exportService.downLoad(response, users);
}
// serviceImpl实现
@Override
public void downLoad(HttpServletResponse response, List<User> users) throws IOException {
// 设置响应内容
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// 设置编码格式
response.setCharacterEncoding("UTF-8");
//设置文件名
String fileName = URLEncoder.encode("userExcel", "UTF-8").replaceAll("\\+", "%20");
//设置响应头
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
//获取写出流
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), User.class).build();
// 创建sheet
WriteSheet writeSheet = EasyExcel.writerSheet("学生记录").build();
// 读出
excelWriter.write(users, writeSheet);
// 关闭流
excelWriter.finish();
}
4.2 导入excel
/**
* 导入excel
* @param response
*/
@PostMapping("upload")
public String upload(@RequestPart("file")MultipartFile file) throws IOException {
exportService.upload(file);
return "success";
}
// serviceImpl 实现
@Override
public void upload(MultipartFile file) throws IOException {
// 读取excel
ExcelReader reader = EasyExcel.read(file.getInputStream(), User.class,
new ExportListener(exportMapper)).build();
ReadSheet sheet = EasyExcel.readSheet(0).build();// 读取第一个sheet
// 读取
reader.read(sheet);
// 关闭流
reader.finish();
}
4.3 工具类 ExportListener
/**
* @Description 导入excel的监听器
* @Author small Geng
* @Data 2022/11/17 14:03
*/
@Slf4j
public class ExportListener extends AnalysisEventListener<User> {
// 每隔一百条数据存储数据库 然后清理list 方便内存回收
private static final int BATCH_COUNT = 100;
// 缓存的数据
private List<User> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
private ExportMapper exportMapper;
public ExportListener(ExportMapper exportMapper) {
this.exportMapper = exportMapper;
}
// 每解析一条数据都会进行调用
@Override
public void invoke(User user, AnalysisContext context) {
log.info("解析到一条数据:{}", JSON.toJSONString(user));
// 将解析的数据添加到缓存集合中
user.setUserId(null);
cachedDataList.add(user);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
// 向数据库中插入数据
exportMapper.insert(user);
// 清理一次list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有数据解析完成之后就会调用该方法
* 防止出现数据量没有达到BATCH_COUNT条的时候,依然进行数据库插入操作
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 数据保存到数据库中
saveData();
log.info("所有数据解析完成,进入doAfterAllAnalysed方法");
}
/**
* 保存数据
*/
private void saveData() {
log.info("{}条数据,开始存储数据库...", cachedDataList.size());
for (User user : cachedDataList) {
exportMapper.insert(user);
}
log.info("存储数据完成!!");
}
}