由于apache poi和jxl,excelPOI都有一个严重的问题,就是非常消耗内存,特别处理数据量多时,速度慢并且时有异常发生,所以改用由阿里研发的easyExcel更可靠一些,它的官方建议对于1000行以内的采用原来poi的写法一次读写,但于1000行以上的数据,有用了一行行进行解析的方案,这样避免了内存的溢出。
其实可以直接去看官方文档或者去github拉源码,地址:https://www.yuque.com/easyexcel/doc/easyexcel,以下是我根据官方文档写的demo,有不对或者可以优化的地方欢迎指出来
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.6.RELEASE
com.zjh
designmodel
0.0.1-SNAPSHOT
designmodel
Demo project for Spring Boot
1.8
commons-lang
commons-lang
2.5
org.springframework.boot
spring-boot-starter-web
com.baomidou
mybatis-plus-boot-starter
3.2.0
com.baomidou
mybatis-plus
3.2.0
com.alibaba
easyexcel
2.0.5
com.alibaba
druid
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.projectlombok
lombok
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-maven-plugin
package com.zjh.designmodel.easyexcel.entiy;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 9:56
* Modified by:
*/
@Data
@TableName("user")
public class User extends Common{
@TableId(type = IdType.AUTO)
private Integer id;
//学生学号
@TableField(value = "number")
@ExcelProperty("学号")
private Integer number;
}
package com.zjh.designmodel.easyexcel.entiy;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zjh.designmodel.easyexcel.converter.PositionConverter;
import lombok.Data;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 18:30
* Modified by:
*/
@TableName("teacher")
@Data
public class Teacher extends Common{
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value = "position")
@ExcelProperty(value = "职位",converter = PositionConverter.class)
//1.班主任 2.普通教师
private Integer position;
//教师编号
@TableField(value = "number")
@ExcelProperty("教师编号")
private Integer number;
}
package com.zjh.designmodel.easyexcel.entiy;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.TableField;
import com.zjh.designmodel.easyexcel.converter.SexConverter;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 14:14
* Modified by:
*/
@Data
public class Common {
@TableField(value = "name")
@ExcelProperty("名字")
private String name;
@TableField(value = "sex")
@ExcelProperty(value = "性别",converter = SexConverter.class)
//1.男 2.女
private Integer sex;
@TableField(value = "create_time")
@ExcelProperty("创建时间")
private Long createTime;
}
持久层
package com.zjh.designmodel.easyexcel.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zjh.designmodel.easyexcel.entiy.Teacher;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/28 11:41
* Modified by:
*/
@Mapper
public interface TeacherMapper {
@Insert({""})
int save(@Param("teacherList") List teacherList);
@Select("select * from teacher")
List getTeacherList();
}
package com.zjh.designmodel.easyexcel.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zjh.designmodel.easyexcel.entiy.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 10:04
* Modified by:
*/
@Mapper
public interface UserMapper {
@Insert({""})
int save(@Param("userList") List userList);
@Select("select * from user")
List getUserList();
}
package com.zjh.designmodel.easyexcel.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zjh.designmodel.easyexcel.entiy.Teacher;
import com.zjh.designmodel.easyexcel.entiy.User;
import org.apache.poi.ss.formula.functions.T;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 11:48
* Modified by:
*/
public interface CommonService {
void saveUser (List userList) throws IllegalAccessException, InstantiationException;
void saveTeacher (List teacherList) throws IllegalAccessException, InstantiationException;
void downLoad(HttpServletResponse response,Integer type) throws IllegalAccessException, IOException, InstantiationException;
}
package com.zjh.designmodel.easyexcel.service.impl;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjh.designmodel.easyexcel.entiy.Teacher;
import com.zjh.designmodel.easyexcel.entiy.User;
import com.zjh.designmodel.easyexcel.mapper.TeacherMapper;
import com.zjh.designmodel.easyexcel.mapper.UserMapper;
import com.zjh.designmodel.easyexcel.service.CommonService;
import com.zjh.designmodel.easyexcel.util.EasyExcelUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 11:53
* Modified by:
*/
@Service
@Repository
public class CommonServiceImpl implements CommonService {
@Autowired
UserMapper userMapper;
@Autowired
TeacherMapper teacherMapper;
@Override
public void saveUser(List list) throws IllegalAccessException, InstantiationException {
userMapper.save(list);
}
@Override
public void saveTeacher(List teacherList) throws IllegalAccessException, InstantiationException {
teacherMapper.save(teacherList);
}
@Override
public void downLoad(HttpServletResponse response, Integer type) throws IllegalAccessException, IOException, InstantiationException {
if (type==1){//学生
List users = userMapper.getUserList();
EasyExcelUtils.download(response,User.class,users);
}else {
List teachers = teacherMapper.getTeacherList();
EasyExcelUtils.download(response,Teacher.class,teachers);
}
}
}
package com.zjh.designmodel.easyexcel.controller;
import com.alibaba.excel.EasyExcel;
import com.zjh.designmodel.easyexcel.entiy.Teacher;
import com.zjh.designmodel.easyexcel.entiy.User;
import com.zjh.designmodel.easyexcel.listen.CommonListen;
import com.zjh.designmodel.easyexcel.service.CommonService;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/20 10:06
* Modified by:
*/
@RestController
@RequestMapping("/easyexcel")
public class EasyExcelController {
@Autowired
CommonService commonService;
@PostMapping("/import")
//type=1代表导入的是学生的模板。type=2代表的是老师的模板
public void simpleRead(MultipartFile file,HttpServletRequest request,Integer type) throws IOException {
if(type==1){
EasyExcel.read(file.getInputStream(), User.class,new CommonListen(commonService,User.class,"saveUser")).sheet().doRead();
}else {
EasyExcel.read(file.getInputStream(), Teacher.class,new CommonListen(commonService,Teacher.class,"saveTeacher")).sheet().doRead();
}
}
@GetMapping("/downLoad")
//type=1代表导入的是学生的模板。type=2代表的是老师的模板
public void downLoad(HttpServletResponse response,Integer type) throws IOException, InstantiationException, IllegalAccessException {
commonService.downLoad(response,type);
}
}
package com.zjh.designmodel.easyexcel.listen;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.zjh.designmodel.easyexcel.entiy.Common;
import com.zjh.designmodel.easyexcel.entiy.Teacher;
import com.zjh.designmodel.easyexcel.entiy.User;
import com.zjh.designmodel.easyexcel.service.CommonService;
import lombok.SneakyThrows;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
/**
* @Author: zjh
* @Description: 通用的监听,这样就不用一个模板一个监听了
* @Date: Created in 2020/5/20 11:29
* Modified by:
*/
public class CommonListen extends AnalysisEventListener {
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BAUserCH_COUNUser = 5;
//模板对应的实体类
private Class tClass;
//Controller层对应调用的方法名
private String methodName;
List
package com.zjh.designmodel.easyexcel.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
/**
* 职责自定义转换器
*/
public class PositionConverter implements Converter {
@Override
public Class supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里读的时候会调用
*
* @param cellData
* NotNull
* @param contentProperty
* Nullable
* @param globalConfiguration
* NotNull
* @return
*/
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
switch (cellData.getStringValue()){
case "班主任":
return 1;
case "普通教师":
return 2;
default:
return 0;
}
}
/**
* 这里是写的时候会调用
*
* @param value
* NotNull
* @param contentProperty
* Nullable
* @param globalConfiguration
* NotNull
* @return
*/
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
switch (value){
case 1:
return new CellData("班主任");
case 2:
return new CellData("普通教师");
default:
return new CellData(String.valueOf(value));
}
}
}
package com.zjh.designmodel.easyexcel.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
/**
* 性别自定义转换器
*/
public class SexConverter implements Converter {
@Override
public Class supportJavaTypeKey() {
return Integer.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里读的时候会调用
*
* @param cellData
* NotNull
* @param contentProperty
* Nullable
* @param globalConfiguration
* NotNull
* @return
*/
@Override
public Integer convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
switch (cellData.getStringValue()){
case "男":
return 1;
case "女":
return 2;
default:
return 0;
}
}
/**
* 这里是写的时候会调用 不用管
*
* @param value
* NotNull
* @param contentProperty
* Nullable
* @param globalConfiguration
* NotNull
* @return
*/
@Override
public CellData convertToExcelData(Integer value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
switch (value){
case 1:
return new CellData("男");
case 2:
return new CellData("女");
default:
return new CellData(String.valueOf(value));
}
}
}
package com.zjh.designmodel.easyexcel.util;
import com.alibaba.excel.EasyExcel;
import com.zjh.designmodel.easyexcel.entiy.User;
import org.apache.poi.ss.formula.functions.T;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/28 15:24
* Modified by:
*/
public class EasyExcelUtils {
public static void download(HttpServletResponse response, Class t, List list) throws IOException, IllegalAccessException, InstantiationException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=demo.xlsx");
EasyExcel.write(response.getOutputStream(), t).sheet("模板").doWrite(list);
}
}