前言
传统ERP系统中,和Excel的交互比较频繁。主要步骤分为:导入,基础数据校验,业务等特殊校验,返回导入结果。工作中的系统原版是手动解析,然后进行校验,有很多共性的基础校验没有整合,代码冗余过多。现打算重构代码,主要使用了策略模式和责任链模式进行改造。不多说直接上代码。
代码实现
各种类的基本功能
策略模式:
通过
ImportHandler
和ExportHandler
接口定义导入导出的行为具体实现类如
UserImportHandler
实现特定类型的导入逻辑ExcelProcessor
作为上下文,根据类型选择合适的处理器
责任链模式:
Validator
接口定义校验行为ValidatorChain
管理校验器链基本字段校验器和业务校验器依次执行
注解驱动的基本校验:
使用
@Required
、@MaxLength
、@NumberRange
等注解定义字段约束BasicValidator
通过反射检查字段注解进行基本校验
可扩展的业务校验:
BusinessValidationRule
接口允许自定义业务校验规则BusinessValidator
动态添加和执行这些规则
策略模式部分
策略模式主要定义导入导出的,通过实现接口来自定义导入导出逻辑
ImportHandler(定义导入行为),BaseImportHandler(基础导入步骤)UserImportHandler(导入最终实现方案)
public interface ImportHandler {
ImportResult handleImport(InputStream inputStream) throws IOException;
}
public abstract class BaseImportHandler implements ImportHandler {
private List<Validator> validators = new ArrayList<>();
public BaseImportHandler() {
// 添加基本字段校验器
validators.add(createBasicValidator());
// 添加业务校验器
validators.add(createBusinessValidator());
}
protected abstract Validator createBasicValidator();
protected abstract Validator createBusinessValidator();
@Override
public ImportResult handleImport(InputStream inputStream) throws IOException {
// 1. 解析Excel
List<Map<String, Object>> records = parseExcel(inputStream);
// 2. 构建责任链
ValidatorChain chain = new ValidatorChain(validators);
// 3. 执行校验
ImportResult result = new ImportResult();
for (Map<String, Object> record : records) {
ValidationResult validationResult = chain.validate(record);
if (validationResult.isValid()) {
// 4. 校验通过,执行数据插入
insertRecord(record);
result.getSuccessRecords().add(record);
} else {
result.getFailedRecords().add(record);
result.getErrorMessages().addAll(validationResult.getErrorMessages());
}
}
return result;
}
protected abstract List<Map<String, Object>> parseExcel(InputStream inputStream) throws IOException;
protected abstract void insertRecord(Map<String, Object> record);
}
public class UserImportHandler extends BaseImportHandler {
@Override
protected Validator createBasicValidator() {
return new BasicValidator(User.class);
}
@Override
protected Validator createBusinessValidator() {
BusinessValidator businessValidator = new BusinessValidator();
// 添加业务校验规则
businessValidator.addValidationRule("age", new BusinessValidationRule() {
@Override
public boolean validate(Object value) {
if (value == null) return false;
try {
int age = Integer.parseInt(value.toString());
return age >= 18 && age <= 60;
} catch (NumberFormatException e) {
return false;
}
}
@Override
public String getErrorMessage() {
return "年龄必须在18到60岁之间";
}
});
return businessValidator;
}
@Override
protected List<Map<String, Object>> parseExcel(InputStream inputStream) throws IOException {
// 实际实现中使用Apache POI或EasyExcel解析Excel文件
// 这里仅作示例,返回模拟数据
List<Map<String, Object>> records = new ArrayList<>();
Map<String, Object> record1 = new HashMap<>();
record1.put("name", "张三");
record1.put("age", 25);
record1.put("email", "zhangsan@example.com");
records.add(record1);
Map<String, Object> record2 = new HashMap<>();
record2.put("name", "李四");
record2.put("age", 17); // 不合法年龄
record2.put("email", "lisi@example.com");
records.add(record2);
return records;
}
@Override
protected void insertRecord(Map<String, Object> record) {
// 实际实现中插入数据库
System.out.println("插入用户数据: " + record);
}
}
@Service
public class ExcelProcessor {
private final Map<String, ImportHandler> importHandlers = new HashMap<>();
private final Map<String, ExportHandler> exportHandlers = new HashMap<>();
// 注册导入处理器
public void registerImportHandler(String type, ImportHandler handler) {
importHandlers.put(type, handler);
}
// 注册导出处理器
public void registerExportHandler(String type, ExportHandler handler) {
exportHandlers.put(type, handler);
}
// 执行导入
public ImportResult importExcel(String type, InputStream inputStream) throws IOException {
ImportHandler handler = importHandlers.get(type);
if (handler == null) {
throw new IllegalArgumentException("不支持的导入类型: " + type);
}
return handler.handleImport(inputStream);
}
// 执行导出
public void exportExcel(String type, OutputStream outputStream, List<?> data) throws IOException {
ExportHandler handler = exportHandlers.get(type);
if (handler == null) {
throw new IllegalArgumentException("不支持的导出类型: " + type);
}
handler.handleExport(outputStream, data);
}
}