Java uses easyexcel to implement import and export functions

I used poi before. The poi analysis method is dom analysis, and the results are read into memory at one time. This kind of operation is usually not a problem, but when the amount of concurrency increases, OOM will appear. EasyExcel, the underlying object is actually Or use the set of poi package. It just extracts part of the poi package and discards most of the business-related attributes. Since it focuses on the import and export business, it can avoid OOM through local caching when dealing with the import and export of large amounts of data. In certain scenarios, the performance of EasyExcel is still acceptable.

1 Add dependencies first.

    <!-- EasyExcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.0-beta2</version>
        </dependency>

2 Before trying the import and export function again, write the interface for batch inserting data and the interface for querying data.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.demo.mapper.MedicnesMapper">
    <insert id="saveMedicnesList" parameterType="cn.demo.entity.Medicnes">
        insert into medices
        (food,remark)
        values
        <foreach collection="list" item="rm" separator=",">
            (#{rm.food},#{rm.remark})
        </foreach>
    </insert>
    <select id="medicnesList" parameterType="cn.demo.entity.Medicnes" resultType="cn.demo.entity.Medicnes">
        SELECT
        food,
        remark
        FROM
        medices
    </select>
</mapper>

3 Create an entity class that needs to export data.

package cn.demo.entity;

import com.alibaba.excel.annotation.ExcelProperty;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;



@Data
@AllArgsConstructor
@NoArgsConstructor
public class Medicnes {

    @ExcelProperty("食物名称")
    private String  food;

    @ExcelProperty("食物产地")
    private String  remark;



}

4 Create a class ExcelListener.

package cn.demo.config;

import cn.demo.entity.Medicnes;
import cn.demo.service.EmpService;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * 有个很重要的点 ExcelListener
 * 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
 */
public class ExcelListener extends AnalysisEventListener<Medicnes> {

    private List<Medicnes> list = new ArrayList<>();

    //每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
    private static final int BATCH_COUNT = 5;

    //假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象用
    @Autowired
    private EmpService empService;


    /**
     * 如果使用了spring,请使用这个构造方法。
     * 每次创建Listener的时候需要把spring管理的类传进来
     */
    public ExcelListener(EmpService empService) {
        this.empService = empService;
    }


    /**
     * 这个每一条数据解析都会来调用
     */
    @Override
    public void invoke(Medicnes goods, AnalysisContext analysisContext) {
        System.out.println("解析到一条数据:========================"+goods.toString());
        // 数据存储到data,供批量处理或后续自己业务逻辑处理。
        list.add(goods);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if(list.size() >= BATCH_COUNT){
            saveData();
            // 存储完成清理data
            list.clear();
        }

    }



    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        //确保所有数据都能入库
        saveData();
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        System.out.println("=============================="+list.size()+"条数据,开始存储到数据库");
        empService.saveMedicnesList(list);
    }
}

5 Next, write our tool class - help us to realize downloading excel

public class DownExcel {
    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); //用io流来写入数据
    }
}

//导出为Excel
@RequestMapping("/downloadexcel.do")
public void getExcel(HttpServletResponse response) throws IllegalAccessException, IOException, 
InstantiationException {
    List<Medicnes> list = sysUserService.medicnesList();
    DownExcel.download(response,Medicnes.class,list);
}

6 The controller adds our import action code

//导入Excel
@RequestMapping("/importexcel.do")
@ResponseBody
public String importexcel(@RequestParam(value = "excelFile") MultipartFile file) throws IOException{
    EasyExcel.read(file.getInputStream(), Medicnes.class, new ExcelListener(sysUserService)).sheet().doRead();
    return "success";
}

7 The export effect is as shown in the figure.

8 import direct call.

Guess you like

Origin blog.csdn.net/qq_40609490/article/details/125004176