前言
在数字化期间背景下,订单管理系统的高效性与灵活性成为企业竞争力的核心要素。本文档详细分析了一个基于 计谋模式 的度假订单导入系统,通过分层架构计划实现了多源异构数据的标准化处理。系统以 Spring Boot 为核心框架,结合 MyBatis Plus、Excel 工具库和 Swagger 文档化工具,构建了一个支持动态扩展、批量处理、事务安全的订单管明白决方案。
本文将从数据模型界说、计谋模式实现、核心业务流程三个维度展开,深入解读系统怎样通过 灵活的时间解析、高效的事务管理 和 可扩展的架构计划,实现从 Excel 文件到数据库记录的全链路处理。无论是架构师、开辟职员还是技能管理者,均可通过本文快速掌握系统计划精华。
阅读指引
为高效明白本系统,建议按以下路径阅读:
一、架构概览
- 核心模型:RouteOrderInfoDO(线路订单数据对象)
- 核心能力:字段映射、状态枚举关联、多租户支持
- 路径:数据层 > RouteOrderInfoDO
- 计谋模式:VacationOrderImportStrategy(计谋接口)与 TempOrderImportStrategy(具体计谋)
- 工厂模式:VacationProductCategoryFactory(计谋路由工厂)
- 路径:服务层 > 计谋 服务层 > 酒店品类工厂
- 核心接口:RouteOrderExcelController(Excel 导入/导出)
- 功能清单:订单导出、多计谋导入、模板下载
- 路径:控制层 > RouteOrderExcelController
二、核心流程
- 阶段分解:Excel 解析 → 数据转换 → 批量持久化
- 关键代码:TempOrderImportStrategy.importExcel()
- 路径:数据处理流程
- 双阶段解析:格式标准化 → 智能降级解析
- 计划亮点:parseDateTime() 方法的多格式兼容性
- 路径:时间处理
三、扩展指南
- 新增订单来源:扩展计谋接口与工厂路由
- 性能优化:批量 SQL 优化与异步处理建议
- 安全增强:文件校验与防 SQL 注入方案
核心总结
1. 架构亮点
维度
| 计划亮点
| 分层架构
| 清楚的 Controller-Service-DAO 分层,通过计谋模式实现业务逻辑解耦
| 扩展性
| 计谋接口标准化 + 工厂路由动态分发,新增订单来源只需实现新计谋类,符合开闭原则
| 性能
| 批量 SQL 操作(insertBatch/updateBatch)减少数据库交互,事务注解保障原子性
| 健壮性
| 双重时间解析机制(支持 3+ 时间格式)、非常分类处理(IO/格式/数据库非常)
| 2. 关键技能栈
- - 核心框架:Spring Boot + MyBatis Plus
- - 策略模式:策略接口 + 工厂路由
- - Excel 处理:Alibaba EasyExcel + 自定义 DictConvert 转换器
- - 事务管理:Spring @Transactional 注解
- - 文档化:Swagger3 + @Schema 注解
复制代码 3. 性能数据(示例)
指标
| 数值(单文件)
| 千级订单处理耗时
| ≤2s(含IO与DB操作)
| 内存占用峰值
| ≤50MB(万级订单)
| 批量插入效率
| 5000条/秒
| 4. 扩展建议
- 校验增强:添加 @Validated 参数校验与自界说校验注解
- 监控集成:通过 Micrometer 实现导入乐成率、耗时等指标采集
- 异步化改造:使用 @Async 注解实现大文件异步导入,提升接口相应速度
通过本文的系统解读,读者可快速掌握基于计谋模式的订单导入架构计划方法论,并基于现有代码扩展出符合业务需求的定制化功能。
数据层
RouteOrderInfoDO
服务层
计谋
TempOrderImportStrategy
数据处理流程
我来详细讲解 <mcsymbol name="TempOrderImportStrategy" filename="TempOrderImportStrategy.java" path="c:\project\centralservice\central-module-vacation\central-module-vacation-biz\src\main\java\cn\iocoder\central\module\vacation\service\order\excel\strategy\TempOrderImportStrategy.java" startline="1" type="class"></mcsymbol> 的数据处理流程:
1. 整体流程
这是一个实现 VacationOrderImportStrategy 接口的订单导入计谋类,专门处理临时订单的Excel导入,主要流程分为4个阶段:
- 读取Excel数据
- 初始化数据容器
- 逐条处理订单数据
- 批量数据库操作
2. 详细数据流转过程
2.1 读取Excel阶段
- List<TempVacationOrderVo> orderList = ExcelUtils.read(file, TempVacationOrderVo.class);
复制代码
- 输入:MultipartFile 类型的Excel文件
- 输出:List<TempVacationOrderVo> 订单VO列表
- 技能:使用 ExcelUtils.read() 将Excel自动映射为Java对象列表
2.2 数据容器初始化
- List<RouteOrderInfoDO> createRouteOrderList = new ArrayList<>(); // 待新增
- List<RouteOrderInfoDO> updateRouteOrderList = new ArrayList<>(); // 待更新
- List<String> addOrderCodes = new ArrayList<>(); // 新增订单号
- List<String> updateOrderCodes = new ArrayList<>(); // 更新订单号
复制代码
- 必要新增的DO对象
- 必要更新的DO对象
- 新增订单的编号(用于返回结果)
- 更新订单的编号(用于返回结果)
2.3 单条数据处理流程
对每条订单数据实行以下操作:
- RouteOrderInfoDO RouteOrderInfoDO = BeanUtils.toBean(order, RouteOrderInfoDO.class);
- RouteOrderInfoDO.setOrigin(origin); // 设置来源
复制代码
- 使用 BeanUtils.toBean() 进行对象属性拷贝
- 手动设置订单来源字段
- RouteOrderInfoDO.setBuyTime(parseDateTime(...));
- RouteOrderInfoDO.setPlayStartTime(parseDateTime(...));
- RouteOrderInfoDO.setPlayEndTime(parseDateTime(...));
复制代码
- 调用 parseDateTime() 方法统一处理各种时间格式
- 支持两种时间格式:
- 完备日期时间格式:yyyy-MM-dd'T'HH:mm:ss 或 yyyy-MM-dd HH:mm:ss
- 简单日期格式:yyyy-MM-dd (会自动补全时间为00:00:00)
- Long tableId = RouteOrderInfoMapper.selectIdBySystemCodeAndOrigin(
- RouteOrderInfoDO.getSystemCode(),
- RouteOrderInfoDO.getOrigin()
- );
复制代码
- 根据系统编号和来源查询是否已存在相同订单
- 返回已存在订单的ID或null
- if (tableId != null) {
- // 更新逻辑
- RouteOrderInfoDO.setId(tableId);
- updateRouteOrderList.add(RouteOrderInfoDO);
- updateOrderCodes.add(RouteOrderInfoDO.getSystemCode());
- } else {
- // 新增逻辑
- createRouteOrderList.add(RouteOrderInfoDO);
- addOrderCodes.add(RouteOrderInfoDO.getSystemCode());
- }
复制代码 2.4 批量数据库操作
- if (!createRouteOrderList.isEmpty()) {
- routeOrderInfoMapper.insertBatch(createRouteOrderList);
- }
- if (!updateRouteOrderList.isEmpty()) {
- routeOrderInfoMapper.updateBatch(updateRouteOrderList);
- }
复制代码
2.5 返回结果构造
- RouteImportRespVo respVo = new RouteImportRespVo();
- respVo.setAddOrderCodes(addOrderCodes);
- respVo.setUpdateOrderCodes(updateOrderCodes);
- respVo.setFailureOrderCodes(Collections.emptyList());
复制代码
- 构造包含处理结果的相应对象
- 当前实现没有失败订单(空列表)
3. 关键计划点
- 事务管理:@Transactional 确保整个导入过程原子性
- 批量处理:使用批量SQL提高性能
- 灵活的时间解析:parseDateTime() 方法支持多种时间格式
- 结果追踪:记录所有处理过的订单编号
- 计谋模式:实现标准接口,便于扩展其他导入方式
4. 数据流转图
- Excel文件
- → List<TempVacationOrderVo>
- → List<RouteOrderInfoDO> (分新增/更新)
- → 批量SQL操作
- → RouteImportRespVo (结果统计)
复制代码 这个实现很好地平衡了性能、可靠性和可维护性,是典型的批处理数据导入解决方案。
!!时间处理
我来详细讲解 <mcsymbol name="TempOrderImportStrategy" filename="TempOrderImportStrategy.java" path="c:\project\centralservice\central-module-vacation\central-module-vacation-biz\src\main\java\cn\iocoder\central\module\vacation\service\order\excel\strategy\TempOrderImportStrategy.java" startline="52" type="function"></mcsymbol> 中的时间处理逻辑:
1. 时间处理流程分解
这三行代码处理了三个时间字段(购买时间、游玩开始时间、游玩竣事时间),处理流程完全同等,分为两个关键步调:
- RouteOrderInfoDO.setBuyTime(parseDateTime(DateTimeFormatterUtils.formatDateTime(order.getBuyTime())));
复制代码
- 格式化阶段:DateTimeFormatterUtils.formatDateTime()
- 将原始时间对象格式化为标准字符串
- 确保时间格式统一化处理
- 将格式化后的字符串解析为 LocalDateTime 对象
- 支持多种时间格式的灵活解析
2. 关键技能点解析
2.1 格式化阶段
DateTimeFormatterUtils.formatDateTime() 的作用:
- 输入:大概是各种格式的时间对象(Date/LocalDateTime/String等)
- 输出:统一格式的字符串(如 yyyy-MM-dd HH:mm:ss)
- 确保后续解析阶段输入格式的同等性
2.2 解析阶段
parseDateTime() 方法的智能解析逻辑:
- 支持 ISO 格式:yyyy-MM-dd'T'HH:mm:ss
- 支持常规格式:yyyy-MM-dd HH:mm:ss
- 当完备时间解析失败时,尝试解析简单日期:yyyy-MM-dd
- 自动补全时间为 00:00:00
- 双重非常捕获确保解析可靠性
- 最终会抛出包含详细错误信息的 DateTimeParseException
3. 计划上风
- 可以处理来自差异数据源的多样化时间格式
- Excel、数据库、API等差异来源的时间数据都能适配
- 最终统一存储为 LocalDateTime 类型
- 确保业务逻辑处理时时间格式统一
- 通过格式化+解析的两阶段处理增长可靠性
- 清楚的错误提示便于题目排查
4. 处理流程图解
- 原始时间对象(order.getBuyTime())
- → DateTimeFormatterUtils.formatDateTime()
- → 标准化时间字符串
- → parseDateTime()
- → LocalDateTime对象
- → 设置到RouteOrderInfoDO
复制代码 5. 典型应用场景
这种处理方式特别适合:
- 从Excel导入的时间数据(大概有各种格式)
- 必要与数据库时间字段对接的场景
- 必要严格时间盘算的业务逻辑(如游玩时长盘算)
这种计划既包管了灵活性,又确保了最终数据的同等性,是时间处理的最佳实践。
VacationOrderImportStrategy
- package cn.iocoder.central.module.vacation.service.order.excel.strategy;
- import cn.iocoder.central.module.vacation.controller.admin.order.excel.vo.RouteImportRespVo;
- import org.springframework.web.multipart.MultipartFile;
- import java.io.IOException;
- public interface VacationOrderImportStrategy {
- /**
- * 导入Excel
- *
- * @param file
- * @param origin
- * @return
- */
- RouteImportRespVo importExcel(MultipartFile file, String origin) throws IOException;
- }
复制代码
我来详细讲解 <mcsymbol name="VacationOrderImportStrategy" filename="VacationOrderImportStrategy.java" path="c:\project\centralservice\central-module-vacation\central-module-vacation-biz\src\main\java\cn\iocoder\central\module\vacation\service\order\excel\strategy\VacationOrderImportStrategy.java" startline="1" type="interface"></mcsymbol> 这个计谋接口的核心作用:
核心定位
这是订单导入功能的标准计谋接口,采取计谋模式计划,主要作用包括:
- 界说所有订单导入计谋必须实现的importExcel方法
- 标准化输入参数和返回值格式
- 通过origin参数区分差异来源的订单
- 允许为差异来源实现定制化导入逻辑
- 将导入逻辑与业务调用方解耦
- 新增导入渠道只需实现新计谋,无需修改现有代码
方法详解
- RouteImportRespVo importExcel(MultipartFile file, String origin) throws IOException;
复制代码
- file:必要导入的Excel文件
- origin:订单来源标识(如"shanwenlv")
- 统一返回RouteImportRespVo结果对象
- 包含乐成/失败订单统计信息
- 声明抛出IOException处理文件读取非常
- 实现类可添加更多特定非常
计划上风
典型实现
如之前看到的TempOrderImportStrategy就是其具体实现,处理特定来源的订单导入。
这个接口是订单导入功能的核心抽象,为系统提供了灵活、可扩展的导入架构。
service-vo
- package cn.iocoder.central.module.vacation.service.order.excel.vo;
- import cn.iocoder.central.module.vacation.enums.DictTypeConstants;
- import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
- import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
- import com.alibaba.excel.annotation.ExcelProperty;
- import io.swagger.v3.oas.annotations.media.Schema;
- import lombok.AllArgsConstructor;
- import lombok.Builder;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import lombok.experimental.Accessors;
- import java.math.BigDecimal;
- @Data
- @Builder
- @AllArgsConstructor
- @NoArgsConstructor
- @Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
- public class TempVacationOrderVo {
- // 导入渠道订单号
- @ExcelProperty("订单编号")
- private String systemCode;
- @ExcelProperty(value = "订单状态", converter = DictConvert.class)
- @DictFormat(DictTypeConstants.ORDER_MODULE_ORDER_STATUS)
- private String orderStatus;
- @ExcelProperty("产品名称")
- private String routeName;
- @ExcelProperty("下单时间")
- private String buyTime;
- @ExcelProperty("游玩人数")
- private Integer playPersonNumber;
- @ExcelProperty("开始时间")
- private String playStartTime;
- @ExcelProperty("结束时间")
- private String playEndTime;
- @ExcelProperty("金额")
- private BigDecimal totalAmount;
- @ExcelProperty(value = "支付方式", converter = DictConvert.class)
- @DictFormat(DictTypeConstants.ORDER_MODULE_PAYMENT_METHOD)
- private String paymentMethod;
- @ExcelProperty(value = "支付状态", converter = DictConvert.class)
- @DictFormat(DictTypeConstants.ORDER_MODULE_PAYMENT_STATUS)
- private String paymentStatus;
- @ExcelProperty("联系人")
- private String orderUserName;
- @ExcelProperty("联系方式")
- private String orderUserPhone;
- }
复制代码
我来详细讲解 TempVacationOrderVo 这个类的作用和计划特点:
核心定位
这是一个Excel导入数据映射的VO(Value Object)类,专门用于临时度假订单的Excel导入场景,主要作用包括:
- 界说了Excel列名与Java字段的映射关系
- 通过注解实现Excel列到对象属性的自动转换
- 处理字典类型数据的转换(如订单状态、支付方式等)
- 规范时间、金额等特殊字段的格式
关键计划特点
- 使用@ExcelProperty注解配置Excel列名
- 支持自界说转换器(如字典转换)
- 通过@DictFormat关联字典常量
- 使用DictConvert实现字典值与显示文本的转换
- 金额使用BigDecimal包管精度
- 时间字段使用String保持原始格式
- 自动生成getter/setter等方法
- 禁用链式调用避免导入题目
业务代价
- 统一Excel导入的数据布局
- 确保差异来源订单的导入同等性
这个VO类在订单导入流程中起到了承上启下的关键作用,既对接了前端Excel文件的布局,又为后端业务处理提供了标准化的数据对象。
酒店品类工厂
- package cn.iocoder.central.module.vacation.service.order.excel;
- import cn.iocoder.central.module.vacation.service.order.excel.strategy.TempOrderImportStrategy;
- import cn.iocoder.central.module.vacation.service.order.excel.strategy.VacationOrderImportStrategy;
- import jakarta.annotation.Resource;
- import org.springframework.stereotype.Component;
- /**
- * 酒店品类工厂工厂
- */
- @Component
- public class VacationProductCategoryFactory {
- private static final String TEMP_TYPE = "shanwenlv";
- @Resource
- private TempOrderImportStrategy tempOrderImportStrategy;
- public VacationOrderImportStrategy getImportStrategy(String origin) {
- return switch (origin) {
- case TEMP_TYPE -> tempOrderImportStrategy;
- default -> null;
- };
- }
- }
复制代码
我来详细讲解 VacationProductCategoryFactory 这个工厂类的作用和计划特点:
核心定位
这是一个基于计谋模式的工厂类,专门用于管理和提供差异来源的订单导入计谋实现,主要作用包括:
- 统一管理所有订单导入计谋实现
- 作为计谋模式的入口点
- 根据订单来源标识动态返回对应计谋
- 隔离调用方与具体计谋实现的耦合
关键计划特点
- 通过静态常量界说支持的来源类型
- 使用switch-case返回对应计谋
- 预留了default分支便于扩展
- 新增来源只需添加case分支
业务代价
- 为订单导入提供标准化的计谋获取方式
- 简化调用方的使用复杂度
这个工厂类在订单导入系统中起到了计谋路由的关键作用,是计谋模式的核心实现组件。
控制层
RouteOrderExcelController
- package cn.iocoder.central.module.vacation.controller.admin.order.excel;
- import cn.hutool.core.util.ObjectUtil;
- import cn.iocoder.central.module.vacation.controller.admin.order.excel.vo.RouteImportRespVo;
- import cn.iocoder.central.module.vacation.controller.admin.order.excel.vo.RouteImportVo;
- import cn.iocoder.central.module.vacation.controller.admin.order.vo.RouteOrderInfoPageReqVO;
- import cn.iocoder.central.module.vacation.controller.admin.order.vo.RouteOrderInfoRespVO;
- import cn.iocoder.central.module.vacation.dal.dataobject.order.RouteOrderInfoDO;
- import cn.iocoder.central.module.vacation.service.order.RouteOrderInfoService;
- import cn.iocoder.central.module.vacation.service.order.excel.VacationProductCategoryFactory;
- import cn.iocoder.central.module.vacation.service.order.excel.strategy.TempOrderImportStrategy;
- import cn.iocoder.central.module.vacation.service.order.excel.strategy.VacationOrderImportStrategy;
- import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
- import cn.iocoder.yudao.framework.common.pojo.CommonResult;
- import cn.iocoder.yudao.framework.common.pojo.PageParam;
- import cn.iocoder.yudao.framework.common.pojo.PageResult;
- import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
- import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
- import io.swagger.v3.oas.annotations.Operation;
- import io.swagger.v3.oas.annotations.Parameter;
- import io.swagger.v3.oas.annotations.Parameters;
- import io.swagger.v3.oas.annotations.tags.Tag;
- import jakarta.annotation.Resource;
- import jakarta.servlet.http.HttpServletResponse;
- import jakarta.validation.Valid;
- import org.springframework.validation.annotation.Validated;
- import org.springframework.web.bind.annotation.*;
- import org.springframework.web.multipart.MultipartFile;
- import java.io.IOException;
- import java.util.List;
- import static cn.iocoder.central.module.vacation.enums.ErrorCodeConstants.*;
- import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
- import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
- import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
- @Tag(name = "管理后台 - 度假订单 Excel")
- @RestController
- @RequestMapping("/vacation/order/excel")
- @Validated
- public class RouteOrderExcelController {
- @Resource
- private RouteOrderInfoService routeOrderInfoService;
- @Resource
- private VacationProductCategoryFactory vacationProductCategoryFactory;
- @GetMapping("/export-excel")
- @Operation(summary = "导出度假订单信息 Excel")
- // @PreAuthorize("@ss.hasPermission('order:child-route-order-info:export')")
- @ApiAccessLog(operateType = EXPORT)
- public void exportChildRouteOrderInfoExcel(@Valid RouteOrderInfoPageReqVO pageReqVO,
- HttpServletResponse response) throws IOException {
- pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
- List<RouteOrderInfoRespVO> list = routeOrderInfoService.getRouteOrderInfoPage(pageReqVO).getList();
- // 导出 Excel
- ExcelUtils.write(response, "路线订单信息.xls", "数据", RouteOrderInfoRespVO.class,
- BeanUtils.toBean(list, RouteOrderInfoRespVO.class));
- }
- @PostMapping("/import")
- @Operation(summary = "导入度假订单信息")
- @Parameters({
- @Parameter(name = "file", description = "Excel 文件", required = true),
- @Parameter(name = "origin", description = "来源", example = "true")
- })
- // @PreAuthorize("@ss.hasPermission('order:child-route-order-info:import')")
- public CommonResult<RouteImportRespVo> importExcel(@RequestParam("file") MultipartFile file,
- @RequestParam("origin") String origin) throws Exception {
- VacationOrderImportStrategy importStrategy = vacationProductCategoryFactory.getImportStrategy(origin);
- if (ObjectUtil.isEmpty(importStrategy)) {
- return error(VACATION_NOT_FOUND_STRATEGY);
- }
- try {
- RouteImportRespVo orderImportRespVo = importStrategy.importExcel(file, origin);
- return success(orderImportRespVo);
- } catch (IOException e) {
- return error(VACATION_IMPORT_ERROR);
- }
- }
- @GetMapping("/get-route-import-template")
- @Operation(summary = "获取度假导入模板")
- public void RouteImportTemplate(HttpServletResponse response) throws IOException {
- ExcelUtils.write(response, "度假导入模板.xlsx", "度假列表", RouteImportVo.class, null);
- }
- }
复制代码
是一个Spring Boot的RESTful控制器,用于处理与度假订单Excel文件相关的操作。具体功能如下:1. 提供导出度假订单信息到Excel文件的接口。2. 提供导入度假订单信息的接口,根据差异来源选择差异的导入计谋。3. 提供获取度假导入模板的接口。
`@Tag(name = "管理后台 - 度假订单 Excel")` :这是Swagger的注解,用于为API文档添加标签,方便在API文档工具(如Swagger UI)中对接口进行分组和展示。这里将该控制器下的所有接口归为“管理后台 - 度假订单 Excel”这一类别。2.`@RestController` :这是Spring框架的注解,它是`@Controller` 和`@ResponseBody` 的组合注解。表示该类是一个控制器,而且其方法返回的对象会自动序列化为JSON格式的相应体,用于构建RESTful风格的API。3.`@RequestMapping("/vacation/order/excel")` :这也是Spring框架的注解,用于映射HTTP请求的URL路径。它将该控制器下的所有处理方法的URL前缀都设置为`/vacation/order/excel` ,即访问该控制器中的任何接口时,URL都必要以这个前缀开头。4.`@Validated` :这是Spring框架的注解,用于开启方法级别的数据验证。当控制器的方法参数使用了`@Valid` 注解进行验证时,`@Validated` 注解会确保验证逻辑收效。
RouteImportRespVo
复制代码
文件界说了一个名为`RouteImportRespVo` 的类,它是一个用于管理后台的路线订单导入相应视图对象(VO)。该类使用了`@Schema` 注解来形貌类的用途,方便生成API文档。类中包含三个`List<String>` 类型的属性,分别记录导入乐成、更新乐成和导入失败的订单编号数组,便于前端展示导入结果。同时,使用了`@Data` 注解自动生成getter、setter等方法。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |