1.导入依赖
<!-- excel依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.3</version>
</dependency>
2.导入监听器,这边需要注意是哪个实体类,根据实体类去创建监听器,监听器需要实体类的dao层,这里注入了UserMapper,用于插入数据库,
package com.kaocha.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.kaocha.dao.UserMapper;
import com.kaocha.domain.User;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
@Scope("prototype")
//多例模式
public class UserListener implements ReadListener<User> {
/**
* 每隔5条存储数据库,实际使用中可以1000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 1000;
public static HashMap<String,Integer> hashMap=new HashMap<>();
/**
* 缓存的数据
*/
private List<User> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
private List<User> list = new ArrayList<>();
public UserListener() {
}
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
@Resource
private UserMapper userMapper;
/* public UserListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
}*/
public UserListener(UserMapper userMapper) {
this.userMapper = userMapper;
}
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
* @param demoDAO
*/
/**
* 这个每一条数据解析都会来调用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(User data, AnalysisContext context) {
cachedDataList.add(data);
// System.out.println("data = " + data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
}
/**
* 加上存储数据库
*/
private void saveData() {
userMapper.insertUsers(cachedDataList);
}
}
3.解析excel,将文件从MultipartFile转换为File,然后调用EasyExcel的Read方法,去插入数据库,插入数据库这一步是在监听器中完成,我这里是使用将MultipartFile文件中的内容,复制到一个file文件中,然后再进行读取,需要在最后去进行删除,不然会在本地留一个文件,删除的时候不能立即删除,会删除失败,因为插入数据库还在进行,所以需要一个延时任务,这里是使用了线程池,让一个单独的线程去完成的插入,另一个线程等待删除,主线程则是直接返回。
@Override
public int inexcel(MultipartFile text) {
int total = 0;
System.out.println("Thread.currentThread().getName()main = " + Thread.currentThread().getName());
System.out.println("Thread.currentThread().getName()线程池 = " + Thread.currentThread().getName());
System.out.println("UserServiceImpl.inexcel([text])方法");
if (text!=null&&text.getSize()>0) {
String fileName = text.getOriginalFilename();
File file = new File(fileName);
OutputStream out = null;
try {
//获取文件流,以文件流的方式输出到新文件
//InputStream in = multipartFile.getInputStream();
out = new FileOutputStream(file);
byte[] ss = text.getBytes();
for (int i = 0; i < ss.length; i++) {
out.write(ss[i]);
}
UserListener userListener = new UserListener(userMapper);
InputStream in = new FileInputStream(file);
total = getTotalRowCount(file.getPath());
System.out.println("total = " + total);
UserListener.hashMap.put("total",total);
executor.execute(()->{
EasyExcel.read(in, User.class, userListener).sheet(0).headRowNumber(1).doRead();
});
} catch (IOException e) {
e.printStackTrace();
} finally {
executor.execute(()->{
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
File f = new File(file.toURI());
if (f.delete()) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
},20*1000);
});
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return total;
}
4.导出,直接向response写入,则访问该方法的时候就是直接下载导出的Excel文件。
@Override
public void outexcel(Select select, HttpServletResponse response) {
//先取出来要导出的数据
try {
List<User> list = userMapper.list(select);
//创建Excel写出对象
ExcelWriterBuilder write = EasyExcel.write(response.getOutputStream(), User.class);
ExcelWriterSheetBuilder sheet = write.sheet();
sheet.doWrite(list);
} catch (IOException e) {
throw new RuntimeException(e);
}