springboot整合easyexcel实现导入导出

1 引入依赖

 <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.10</version>
        </dependency>
        <!-- hutool-all -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.9</version>
        </dependency>
        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>

2 定义导入导出实体类

导出

package com.grm.pojo;


import java.util.Date;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.grm.converter.StringConverter;

import lombok.Data;
 
/**
 *desc:  导出模型
 *
 * ContentRowHeight 内容行高
 * HeadRowHeight 表头行高
 * ColumnWidth 列宽
 *
 * @author gaorimao
 * @date 2021/08/19
 */
@ContentRowHeight(20)
@HeadRowHeight(25)
@ColumnWidth(25)
@Data
public class ExportModel {
    /**
     * desc: 字段映射,第几列
     */
    @ExcelProperty(value = "姓名" ,index = 0)
    private String name;
 
    @ExcelProperty(value = "性别" ,index = 1)
    private String sex;
 
    @ExcelProperty(value = "年龄" ,index = 2)
    private Integer age;
    
    @ExcelProperty(value = "创建日期" ,index = 3)
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    
    //百分比数字
    @ExcelProperty(value = "百分比" ,index = 4)
    @NumberFormat("#.##%")
    private Double doubleData;
    
    //自定义转换格式
    @ExcelProperty(value = "转换格式" ,index = 5,converter = StringConverter.class)
    private String stringTest;
}

导入

package com.grm.pojo;

import java.util.Date;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.grm.converter.StringConverter;

import lombok.Data;
 
/**
 * desc: 导入模型
 *
 * @author gaorimao
 * @date 2021/08/19
 */
@Data
public class ImportModel {
	 /**
     * desc: 字段映射,第几列
     */
    @ExcelProperty(value = "姓名" ,index = 0)
    private String name;
 
    @ExcelProperty(value = "性别" ,index = 1)
    private String sex;
 
    @ExcelProperty(value = "年龄" ,index = 2)
    private Integer age;
    
    @ExcelProperty(value = "创建日期" ,index = 3)
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    
    //百分比数字
    @ExcelProperty(value = "百分比" ,index = 4)
    @NumberFormat("#.##%")
    private Double doubleData;
    
    //自定义转换格式
    @ExcelProperty(value = "转换格式" ,index = 5,converter = StringConverter.class)
    private String stringTest;
}

3 自定义格式转换类

package com.grm.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;

/**
 * desc: 自定义String格式转换器
 * 
 * @author: gaorimao
 * @since: 2021-8-19
 */
public class StringConverter implements Converter<String> {
    @Override
    public Class supportJavaTypeKey() {
        return String.class;
    }
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    /**
     * desc: 这里读的时候会调用
     *
     * @param cellData
     *            NotNull
     * @param contentProperty
     *            Nullable
     * @param globalConfiguration
     *            NotNull
     * @return
     */
    @Override
    public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) {
        return "自定义读:"+cellData.getStringValue();
    }
    /**
     * desc: 这里是写的时候会调用
     *
     * @param value
     *            NotNull
     * @param contentProperty
     *            Nullable
     * @param globalConfiguration
     *            NotNull
     * @return
     */
    @Override
    public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) {
        //return new CellData(value);
    	return new CellData("自定义写:" + value);
    }
}

4 定义Listener

package com.grm.listener;

import java.util.ArrayList;
import java.util.List;
 
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.grm.mapper.UserMapper;

import lombok.extern.slf4j.Slf4j;
 
/**
 * excel监听类
 *
 * @author gaorimao
 * @date 2021/08/19
 */
@Slf4j
public class ExcelListener extends AnalysisEventListener {
	 /**
     * desc: 每隔3000条存储数据库,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 3000;
    /**
     * desc: 可以通过实例获取该值
     */
    private List<Object> dataList = new ArrayList<>();
    
//    /**
//     * desc: 假设这个是一个mapper,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
//     */
//    private UserMapper userMapper;
//    
//    /**
//     * desc: 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
//     *
//     * @param userMapper
//     */
//    public ExcelListener(UserMapper userMapper) {
//        this.userMapper = userMapper;
//    }
    
    /**
     * desc: 这个每一条数据解析都会来调用
     *
     * @param data
     * @param context
     */
    @Override
    public void invoke(Object object, AnalysisContext context) {
    	log.info("解析到一条数据:{}", JSON.toJSONString(object));
        //数据存储到list,供批量处理,或后续自己业务逻辑处理。
        dataList.add(object);
        
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (dataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            dataList.clear();
        }
    }
 
    /**
     * desc: 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
    	// 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }
 
    //根据业务自行实现该方法,例如将解析好的dataList存储到数据库中
    private void saveData() {
    	//userMapper.save();
    }
 
    public List<Object> getDataList() {
        return dataList;
    }
 
    public void setDataList(List<Object> dataList) {
        this.dataList = dataList;
    }
}

5 easyexcel工具类

package com.grm.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;

import cn.hutool.core.convert.Convert;
import com.grm.listener.ExcelListener;

/**
 * excel工具类
 *
 * @author gaorimao
 * @date 2021/08/19
 */
public class ExcelUtil {
    /**
     * 读取Excel(多个sheet可以用同一个实体类解析)
     * @param excelInputStream
     * @param fileName
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> readExcel(InputStream excelInputStream, String fileName,Class<T> clazz) {
        ExcelListener excelListener = new ExcelListener();
        ExcelReader excelReader = getReader(excelInputStream, fileName,clazz, excelListener);
        if (excelReader == null) {
            return new ArrayList<>();
        }
        List<ReadSheet> readSheetList = excelReader.excelExecutor().sheetList();
        for (ReadSheet readSheet : readSheetList) {
            excelReader.read(readSheet);
        }
        excelReader.finish();
        return Convert.toList(clazz, excelListener.getDataList());
    }

    /**
     * 导出Excel(一个sheet)
     *
     * @param response  HttpServletResponse
     * @param list      数据list
     * @param fileName  导出的文件名
     * @param sheetName 导入文件的sheet名
     * @param clazz     实体类
     */
    public static <T> void writeExcel(HttpServletResponse response, List<T> list, String fileName, String sheetName, Class<T> clazz) {

        OutputStream outputStream = getOutputStream(response, fileName);
        ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz).build();
        WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
        excelWriter.write(list, writeSheet);
        excelWriter.finish();
    }


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

    /**
     * 返回ExcelReader
     *
     * @param inputStream         输入流
     * @param filename         文件
     * @param clazz         实体类
     * @param excelListener
     */
    private static <T> ExcelReader getReader(InputStream inputStream, String filename, Class<T> clazz, ExcelListener excelListener) {
        try {
            if (filename == null ||
                (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) {
                return null;
            }
            ExcelReader excelReader = EasyExcel.read(inputStream, clazz, excelListener).build();
            inputStream.close();
            return excelReader;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

6 controller

package com.grm.controller;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import javax.servlet.http.HttpServletResponse;
 
import com.alibaba.fastjson.JSON;
 
import com.grm.pojo.ExportModel;
import com.grm.pojo.ImportModel;
import com.grm.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
 
/**
 * @author gaorimao
 * @date 2021/08/19
 */
@RestController
@Slf4j
@RequestMapping("/excel")
public class ExcelController {
    @PostMapping("/import")
    public List<ImportModel> read(@RequestParam("file")MultipartFile excel) throws IOException {
        List<ImportModel> datas = ExcelUtil.readExcel(excel.getInputStream(), excel.getOriginalFilename(),
            ImportModel.class);
        log.info("[excel] datas = {}", JSON.toJSONString(datas));
        return datas;
    }
 
    @GetMapping("/export")
    public String writeExcel(HttpServletResponse response) {
        List<ExportModel> list = getList();
        String fileName = "Excel导出测试";
        String sheetName = "sheet1";
        ExcelUtil.writeExcel(response, list, fileName, sheetName, ExportModel.class);
        return "success";
    }
 
    /**
     * desc: 模拟数据
     *
     * @return {@link List<ExportModel>}
     */
    private List<ExportModel> getList() {
        List<ExportModel> modelList = new ArrayList<>();
        ExportModel firstModel = new ExportModel();
        firstModel.setName("李明");
        firstModel.setSex("男");
        firstModel.setAge(20);
        firstModel.setCreateTime(new Date());
        firstModel.setDoubleData(0.2683);
        firstModel.setStringTest("gaorimao");
        modelList.add(firstModel);
 
        ExportModel secondModel = new ExportModel();
        secondModel.setName("珍妮");
        secondModel.setSex("女");
        secondModel.setAge(19);
        secondModel.setCreateTime(new Date());
        secondModel.setDoubleData(0.2015);
        secondModel.setStringTest("tieren");
        modelList.add(secondModel);
 
        return modelList;
    }
}

6 测试

测试导出

测试导入

用这个excel测试

测试结果,ok

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值