一、 EasyExcel 实体类注解 - 数据的导入/导出

一、 EasyExcel 实体类注解 - 数据的导入/导出

(1)jar 的maven坐标配置
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>${easyexcel.version}</version>
    </dependency>
(2) 字典实体类

SysDictData

package com.rocia.common.core.domain.entity;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.rocia.common.annotation.Excel;
import com.rocia.common.annotation.Excel.ColumnType;
import com.rocia.common.constant.UserConstants;
import com.rocia.common.core.domain.BaseEntity;

/**
 * 字典数据表 sys_dict_data
 */
@ApiModel(value = "数据字典")
public class SysDictData {
	/** 字典编码 */
	@ApiModelProperty(name = "dictCode",value = "字典编码")
	private Long dictCode;
	
	/** 字典排序 */
	@ApiModelProperty(name = "dictSort",value = "字典排序")
	private Long dictSort;
	
	/** 字典标签 */
	@ApiModelProperty(name = "dictLabel",value = "名称",required = true)
	private String dictLabel;
	
	/** 字典键值 */
	@ApiModelProperty(name = "dictValue",value = "字典键值",required = true)
	private String dictValue;
	
	/** 字典类型 */
	@ApiModelProperty(name = "dictType",value = "字典类型",required = true)
	private String dictType;
	
	/** 样式属性(其他样式扩展) */
	@ApiModelProperty(name = "cssClass",value = "样式属性")
	private String cssClass;
	
	/** 表格字典样式 */
	@ApiModelProperty(name = "listClass",value = "表格字典样式")
	private String listClass;
	
	/** 是否默认(Y是 N否) */
	@ApiModelProperty(name = "isDefault",value = "Y=是,N=否")
	private String isDefault;
	
	/** 状态(0正常 1停用) */
	@ApiModelProperty(name = "status",value = "0=正常,1=停用")
	private String status;
 }

SysDictType

package com.rocia.common.core.domain.entity;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.rocia.common.core.domain.BaseEntity;

/**
 * 字典类型表 sys_dict_type
 */
@ApiModel(value = "字典类型")
public class SysDictType {
    private static final long serialVersionUID = 1L;

    /** 字典主键 */
    @ApiModelProperty(name = "dictId" ,value = "字典主键")
    private Long dictId;

    /** 字典名称 */
    @ApiModelProperty(name = "dictName" ,value = "字典类型")
    private String dictName;

    /** 字典类型 */
    @ApiModelProperty(name = "dictType" ,value = "字典类型")
    private String dictType;

    @ApiModelProperty(name = "type" ,value = "数据类型(1=系统数据 2=业务数据")
    private Integer type;

    /** 状态(0正常 1停用) */
    @ApiModelProperty(name = "status" ,value = "数据类型(0=正常,1=停用)")
    private String status;
}

(3)导出实体类

** SysDictDateExcelBody**

package com.rocia.common.core.domain.model;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

@Data
public class SysDictDataExcelBody {

    /**
     * 字典类别
     */
    @ExcelProperty(index = 0, value = "字典类别描述") private String dictTypeName;

    /**
     * 字典类别
     */
    @ExcelProperty(index = 1, value = "字典类别") private String dictType;

    /**
     * 字典值
     */
    @ExcelProperty(index = 2, value = "字典值") private String dictValue;

    /**
     * 字典标签值
     */
    @ExcelProperty(index = 3, value = "字典标签值") private String dictLabel;

    /**
     * 系统功能类型
     */
    @ExcelProperty(index = 4, value = "系统功能类型") private String type;
}

Excel 导出

(1)实体类注解导出
    public void downloadTemplate(HttpServletResponse response) {
        String fileName = null;
        try {
            fileName = URLEncoder.encode( "sys-dictType-" + System.currentTimeMillis(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

        try {
            List<SysDictDataExcelBody> objects = new ArrayList<>();
            // 生成示例数据到 excel 中
            SysDictDataExcelBody excelBody = new SysDictDataExcelBody();
            excelBody.setType("8");
            excelBody.setDictType("job_category");
            excelBody.setDictTypeName("工作种类");
            excelBody.setDictLabel("人事");
            excelBody.setDictValue("1");
            objects.add(excelBody);

            SysDictDataExcelBody excelBody1 = new SysDictDataExcelBody();
            excelBody1.setType("8");
            excelBody1.setDictType("job_category");
            excelBody1.setDictTypeName("工作种类");
            excelBody1.setDictLabel("销售");
            excelBody1.setDictValue("2");
            objects.add(excelBody1);

            EasyExcel.write(response.getOutputStream(), SysDictDataExcelBody.class).sheet("字典模板").doWrite(objects);
        } catch (IOException e) {
            throw new CustomException(fileName + "模板下载失败!");
        }
    }

Excel 导入

(1) excel 数据监听器定义 SysDictReadListener
package com.rocia.web.controller.excellistener;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.rocia.common.core.domain.entity.SysDictData;
import com.rocia.common.core.domain.entity.SysDictType;
import com.rocia.common.core.domain.model.SysDictDataExcelBody;
import com.rocia.system.service.ISysDictDataService;
import com.rocia.system.service.ISysDictTypeService;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class SysDictReadListener implements ReadListener<SysDictDataExcelBody> {

    /**
     * 每隔50条存储数据库,实际使用中可以50条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 50;
    private List<SysDictDataExcelBody> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private Map<String, SysDictType> sysDictTypeMap = new HashMap<>();


    private ISysDictTypeService sysDictTypeService;

    private ISysDictDataService sysDictDataService;


    public SysDictReadListener(ISysDictTypeService sysDictTypeService, ISysDictDataService sysDictDataService) {
        this.sysDictTypeService = sysDictTypeService;
        this.sysDictDataService = sysDictDataService;
    }

    @Override
    public void invoke(SysDictDataExcelBody data, AnalysisContext context) {
        List<SysDictType> sysDictTypes = sysDictTypeService.selectDictTypeAll();
        if (CollectionUtil.isNotEmpty(sysDictTypes)){
            sysDictTypeMap = sysDictTypes.stream().collect(Collectors.toMap(SysDictType::getDictType, Function.identity()));
        }

        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }


    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        if (CollectionUtil.isEmpty(cachedDataList)){
            return;
        }

        Map<String, List<SysDictDataExcelBody>> collectMap = cachedDataList.stream().collect(Collectors.groupingBy(SysDictDataExcelBody::getDictType));

        for (Map.Entry<String, List<SysDictDataExcelBody>> entry : collectMap.entrySet()) {
            List<SysDictDataExcelBody> excelBodies = entry.getValue();
            String dictType = entry.getKey();

            SysDictDataExcelBody sysDictDataExcelBody = excelBodies.get(0);
            SysDictType sysDictType = new SysDictType();

            if (!sysDictTypeMap.containsKey(dictType)){
                //新增Type
                sysDictType.setDictName(sysDictDataExcelBody.getDictTypeName());
                sysDictType.setDictType(dictType);
                sysDictType.setStatus("0");
                sysDictType.setType(Integer.parseInt(sysDictDataExcelBody.getType()));
                sysDictType.setCreateBy("admin");
                sysDictType.setCreateTime(new Date());
                sysDictTypeService.insertDictType(sysDictType);
            }else {
                sysDictType = sysDictTypeMap.get(dictType);
            }

            for (int i = 0; i < excelBodies.size(); i++) {
                SysDictDataExcelBody excelBody = excelBodies.get(i);
                SysDictData sysDictData = new SysDictData();
                sysDictData.setDictSort((long) i);
                sysDictData.setDictLabel(excelBody.getDictLabel());
                sysDictData.setDictValue(excelBody.getDictValue());
                sysDictData.setDictType(dictType);
                sysDictData.setIsDefault("N");
                sysDictData.setStatus("0");
                sysDictType.setCreateBy("admin");
                sysDictType.setCreateTime(new Date());
                sysDictDataService.insertDictData(sysDictData);
            }
        }
        log.info("存储数据库成功!");
    }
}
(2)Excel 数据上传导入,将自定义的读取监听器进行注册
    /**
     * 文件上传
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link SysDictDataExcelBody}
     * <p>
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link SysDictReadListener}
     * <p>
     * 3. 直接读即可
     */
    @PostMapping("/upload/excel")
    @ResponseBody
    public R uploadDictExcel(MultipartFile file){
        try {
            EasyExcel.read(file.getInputStream(), SysDictDataExcelBody.class, new SysDictReadListener(dictTypeService,dictDataService)).sheet(0).doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return R.ok();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值