利用阿里easyexcel 将excel文件批量导入数据库

 easyexcel是阿里开源的excel解析工具,相对比其他组建poi , jxl 它对内存溢出有很好的决绝方案!

  1.  首先下载easyexcel的依赖包:


   com.alibaba
   easyexcel
   1.1.2-beta4

注解:如果在运行的时候还缺包加入这个包


   org.apache.poi
   poi
   3.17



   org.apache.poi
   poi-ooxml
   3.17

2. 读取Excel信息代码

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * Excel处理工具
 * @Author: zhaiyh
 * @Date: 2019/6/25 21:11
 */
public class ExcelUtil {
    /**
     * 读取 Excel(多个 sheet)
     *
     * @param excel    文件
     * @param rowModel 实体类映射,继承 BaseRowModel 类
     * @return Excel 数据 list
     */
    public static ResultInfo readExcel(MultipartFile excel, BaseRowModel rowModel) {
        ExcelListener excelListener = new ExcelListener();
        ExcelReader reader = getReader(excel, excelListener);
        if (reader == null) {
            return null;
        }
        for (Sheet sheet : reader.getSheets()) {
            if (rowModel != null) {
                sheet.setClazz(rowModel.getClass());
            }
            reader.read(sheet);
        }
        return excelListener.getDatas();
    }

    /**
     * 读取某个 sheet 的 Excel
     *
     * @param excel    文件
     * @param rowModel 实体类映射,继承 BaseRowModel 类
     * @param sheetNo  sheet 的序号 从1开始
     * @return Excel 数据 list
     */
    public static ResultInfo readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo) {
        return readExcel(excel, rowModel, sheetNo, 1);
    }

    /**
     * 读取某个 sheet 的 Excel
     *
     * @param excel       文件
     * @param rowModel    实体类映射,继承 BaseRowModel 类
     * @param sheetNo     sheet 的序号 从1开始
     * @param headLineNum 表头行数,默认为1
     * @return Excel 数据 list
     */
    public static ResultInfo readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo,
                                         int headLineNum) {
        ExcelListener excelListener = new ExcelListener();
        ExcelReader reader = getReader(excel, excelListener);
        if (reader == null) {
            return null;
        }
        reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass()));
        return excelListener.getDatas();
    }

    /**
     * 导出文件时为Writer生成OutputStream
     */
    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
        //创建本地文件
        String filePath = fileName + ".xlsx";
        File dbfFile = new File(filePath);
        try {
            if (!dbfFile.exists() || dbfFile.isDirectory()) {
                dbfFile.createNewFile();
            }
            fileName = new String(filePath.getBytes(), "ISO-8859-1");
            response.addHeader("Content-Disposition", "filename=" + fileName);
            return response.getOutputStream();
        } catch (IOException e) {
            throw new ExcelException("创建文件失败!");
        }
    }

    /**
     * 返回 ExcelReader
     *
     * @param excel         需要解析的 Excel 文件
     * @param excelListener new ExcelListener()
     */
    private static ExcelReader getReader(MultipartFile excel,
                                         ExcelListener excelListener) {
        String filename = excel.getOriginalFilename();
        if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) {
            throw new ExcelException("文件格式错误!");
        }
        InputStream inputStream;
        try {
            inputStream = new BufferedInputStream(excel.getInputStream());
            return new ExcelReader(inputStream, null, excelListener, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3、将监听的信息进行处理

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.ijovo.billionbottle.util.BStringUtils;

import java.util.ArrayList;
import java.util.List;
/**
 * Excel文档导入监控
 * @Author: zhaiyh
 * @Date: 2019/6/25 21:11
 */
public class ExcelListener extends AnalysisEventListener {

    //自定义用于暂时存储data。
    //可以通过实例获取该值
    private List datas = new ArrayList<>();
    private volatile long failureNum=0;
    //这个减1是因为有一个目录栏
    private volatile long successNum=-1;

    /**
     * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
     */
    @Override
    public void invoke(Object object, AnalysisContext context) {
        //数据存储到list,供批量处理,或后续自己业务逻辑处理。
//        System.out.println(object.getClass().getSimpleName());
        //第一种业务逻辑:用户Excel导入
        if("ImportInfo".equals(object.getClass().getSimpleName())){
            ImportInfo result=(ImportInfo)object;
            //验证没有空以及简介长度有限制
            if(result.getNick_name()!=null && result.getBrief()!=null && result.getSex()!=null){
                if(result.getBrief().length()<=255){
                    //将memberId改成Java生成的
                    result.setMemberId(BStringUtils.getUUIDString());
                    datas.add(object);
                    //这个是线程不安全的,真正的不是这样写
                    successNum++;
                }else{
                    //验证失败的数量
                    failureNum++;
                }
            }
        }


        //第二种种业务逻辑:问题Excel导入
        if("QImportInfo".equals(object.getClass().getSimpleName())){
            QImportInfo result=(QImportInfo)object;
            //验证没有空以及简介长度有限制
//            System.out.println("等于 QImportInfo ");
            //验证没有空以及简介长度有限制
            if(result.getTitle()!=null && result.getContent()!=null){
                datas.add(object);
                //这个是线程不安全的,真正的不是这样写
                successNum++;

            }else{
                //验证失败的数量
                failureNum++;
            }

        }


        //第三种业务逻辑:回答Excel 导入
        if("AImportInfo".equals(object.getClass().getSimpleName())){
            AImportInfo result=(AImportInfo)object;
            //验证没有空以及简介长度有限制
//            System.out.println("等于 AImportInfo ");
            //验证没有空以及简介长度有限制
            if( result.getContent()!=null){
                datas.add(object);
                //这个是线程不安全的,真正的不是这样写
                successNum++;

            }else{
                //验证失败的数量
                failureNum++;
            }

        }

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
       //datas.clear();
    }


    public ResultInfo getDatas() {
        ResultInfo resultInfo= new ResultInfo();
        //把文本框的第一条数据删掉
        datas.remove(0);
        resultInfo.setSuccessInfo(datas);
        resultInfo.setSuccessNum(successNum);
        resultInfo.setFailureNum(failureNum);
        return resultInfo;
    }

    public void setDatas(List datas) {
        this.datas = datas;
    }
}

4、异常信息

/**
 * 异常处理
 * @Author: zhaiyh
 * @Date: 2019/6/25 21:11
 */
public class ExcelException extends RuntimeException {
    public ExcelException(String message) {
        super(message);
    }
}

5、结果信息

/**
 *
 * 返回结果,显示成果结果,失败数目
 * @Author: zhaiyh
 * @Date: 2019/6/27 12:06
 */
public class ResultInfo {
    //成功的结果
    List successInfo;
    //成功的数量
    long successNum;
    //失败的数量
    long failureNum;

    public List getSuccessInfo() {
        return successInfo;
    }

    public long getSuccessNum() {
        return successNum;
    }

    public long getFailureNum() {
        return failureNum;
    }

    public void setSuccessInfo(List successInfo) {
        this.successInfo = successInfo;
    }

    public void setSuccessNum(long successNum) {
        this.successNum = successNum;
    }

    public void setFailureNum(long failureNum) {
        this.failureNum = failureNum;
    }
}

备注:能够实现批量导入!

你可能感兴趣的:(web后台开发)