EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析, 并将一行的解析结果以观察者的模式通知处理。
导入pom依赖,需要注意poi的版本最好版本一致,而且使用3.15以上的版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
以前端上传文件的形式,后端接收文件在进行解析,就以序号为例,然后对其进行解析查询
Controller
@Autowired
private DemoService demoService;
@PostMapping("/test/matching")
public List<StudentVo> matchingQuery(MultipartFile excel) {
List<StudentVo> studentVos = demoService.matchingQuery(excel);
return studentVos;
}
Service
这里我把监听写成了一个内部类,然后直接就给service中的成员变量赋值了
注意,这里有个坑,controller,service,dao默认都是单例模式的,在这里操作成员变量是线程不安全的,所以应该注意把service改为多例模式@Scope("prototype")
@Service
@Scope("prototype")
public class DemoServiceImpl implements DemoService {
private List<ExcelMatching> excelMembers;
@Override
public List<StudentVo> matchingQuery(MultipartFile excel) {
try {
EasyExcel.read(excel.getInputStream(),
ExcelMatching.class,
new ExcelMemberListener()).sheet().doRead();
} catch (Exception e) {
System.out.println(e.getMessage());
}
List<Integer> ids = excelMembers.stream().map(ExcelMatching::getId).collect(Collectors.toList());
List<StudentVo> studentVos = this.getStudentVos();
return ids.stream().map(id -> {
return studentVos.stream().filter(studentVo -> {
return studentVo.getId() == id;
}).collect(Collectors.toList());
}).flatMap(List::stream).collect(Collectors.toList());
}
//封装数据
public List<StudentVo> getStudentVos() {
List<StudentVo> vos = new ArrayList<>();
vos.add(new StudentVo(1, "张三", 18));
vos.add(new StudentVo(2, "李四", 20));
vos.add(new StudentVo(3, "王五", 21));
vos.add(new StudentVo(4, "赵六", 25));
vos.add(new StudentVo(5, "田七", 17));
return vos;
}
/**
* 解析Excel监听
*/
class ExcelMemberListener extends AnalysisEventListener<ExcelMatching> {
private List<ExcelMatching> memberList = new ArrayList<>();
@Override
public void invoke(ExcelMatching data, AnalysisContext analysisContext) {
System.out.println("解析每一行的数据 , 数据内容: " + data);
memberList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
//解析完后
excelMembers = this.memberList;
}
}
}
接下来看实际结果,这里有个问题一致还是没解决,就是不知道怎么让它只解析非空的列,可以看到int类型的数据如果没有的话就是个0,实际用还是会有一些小问题.