前言
在很多JavaWeb系统中,不同的业务模块都要求有Excel数据导入功能。由于不同的业务表的关系,对应Excel导入功能处理数据业务逻辑不一样,很多同学都是针对各自不同的业务表写不同的导入功能接口,导致多了一些例如下载Excel模板和导入Excel模板等重复性的工作。Java是面对对象的编程语言,在此,在下针对Excel数据导入的功能,剥离其共性与个性,封装了一个公用导入数据模块,让开发者根据专注于业务要点开发。
基础类
package com.rocky.pubimport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 公共导入记录
* @author rocky
* @date 2022/4/13 10:11
*/
@Data
@TableName("pub_import_record")
@EqualsAndHashCode(callSuper = false)
public class PubImportRecord extends BaseEntity {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 业务模块 */
private String model;
/** 批次号 */
private String batchNo;
/** 导入状态 */
private String importStatus;
/** 成功导入条数 */
private Integer successImportNum;
/** 失败导入条数 */
private Integer errorImportNum;
/** 成功插入条数 */
private Integer successInsertNum;
/** 失败插入条数 */
private Integer errorInsertNum;
/** 插入状态 */
private String insertStatus;
/** 成功插入数据excel */
private String successInsertFile;
/** 失败插入数据excel */
private String errorInsertFile;
/** 开始生成时间 */
private Date insertStartTime;
/** 结束生成时间 */
private Date insertEndTime;
}
package com.rocky.pubimport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 公共导入数据
* @author rocky
* @date 2022/4/13 10:24
*/
@Data
@TableName("pub_import_data")
@EqualsAndHashCode(callSuper = false)
public class PubImportData extends BaseEntity {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 导入记录ID */
private Long recordId;
private String value1;
private String value2;
private String value3;
private String value4;
private String value5;
private String value6;
private String value7;
private String value8;
private String value9;
/** 生成状态 */
private Boolean insertStatus;
/** 生成信息 */
private String insertErrorMsg;
}
接口类
package com.rocky.pubimport.service;
import com.rocky.pubimport.common.ImportInfo;
import com.rocky.pubimport.common.ResponseImportResult;
import com.rocky.pubimport.entity.PubImportRecord;
import javax.servlet.http.HttpServletResponse;
/**
* 数据导入公共处理服务接口
* @author rocky
* @date 2022/4/13 16:54
*/
public interface IPubImportRecordProcessService<T> {
/**
* 获取业务模块标识
* @return 业务模块
*/
String getModel();
/**
* 下载excel模板
* @param response 响应内容
* @return ByteArrayOutputStream
*/
void downloadTemplate(HttpServletResponse response);
/**
* 导入excel
* @param info 导入信息
* @return ResponseImportResult 处理信息
*/
ResponseImportResult importExcel(ImportInfo info);
/**
* 处理excel数据
* @param record 导入记录
*/
void processData(PubImportRecord record);
}
抽象类
这里是重点之一。PubImportRecordProcessServiceImpl采用模板方法设计模式,将一些公共的例如下载模板、读取模板数据和处理导入数据的工作先一步实现,让其后面子类省去这些重复性工作,专注于其具体业务逻辑。
**
* PubImportRecordProcessServiceImpl
* @author rocky
* @date 2022/4/13 17:01
*/
public abstract class PubImportRecordProcessServiceImpl<T> implements IPubImportRecordProcessService<T> {
@Resource
private PubImportRecordMapper pubImportRecordMapper;
@Resource
private IPubImportRecordService pubImportRecordService;
@Resource
private IPubImportDataService pubImportDataService;
/** 允许上传的文件后缀名 */
protected static final List<String> FILE_SUFFIX = Arrays.asList(".xls", ".xlsx");
/**
* 物理地址根路径
*/
@Value("${file.rootPath}")
private String rootPath;
/**
* 获取业务模块
* @return 业务模块
*/
protected abstract String getModelCode();
/**
* 获取下载模板
* @return PubExcelTemplate excel模板
*/
protected abstract PubExcelTemplate getExcelTemplate();
/**
* 验证数据
* @param data 数据
*/
protected abstract void checkParams(T data);
/**
* 将中间表数据转换对应的数据对象
* @param data 中间数据
* @return T 对应的数据对象
*/
protected abstract T readData(PubImportData data);
/**
* 保持对应的业务数据
* @param data 业务数据
*/
protected abstract void saveData(T data);
/**
* 回写保存成功业务对象的主键信息到导入记录里面
* @param importData 导入记录
* @param businessData 业务对象
*/
protected abstract void writeExpand(PubImportData importData, T businessData);
@Override
public String getModel() {
return getModelCode();
}
@Override
public void downloadTemplate(HttpServletResponse response) {
Map<String, Object> titleRow = new LinkedHashMap<>();
PubExcelTemplate template = getExcelTemplate();
for (String title : template.getTitleRow()) {
titleRow.put(title, "");
}
ArrayList<Map<String, Object>> rows = CollUtil.newArrayList(titleRow);
ExcelWriter writer = ExcelUtil.getWriter(true);
// 设置单元格式为文本
DataForma