# trace-logistics-service **Repository Path**: record-x/trace-logistics-service ## Basic Information - **Project Name**: trace-logistics-service - **Description**: 拉取物流轨迹 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-11-22 - **Last Updated**: 2026-03-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 物流轨迹追踪服务 (Trace Logistics Service) ## 项目简介 基于 Spring Boot 的物流轨迹自动追踪服务,集成 Track718 API,提供物流单号的自动查询、数据存储和状态管理功能。支持多种时间间隔的定时拉取策略,实现物流轨迹的全生命周期管理。 ## 技术栈 - **框架**: Spring Boot 2.x - **数据库**: MySQL 8.0+ - **ORM**: MyBatis-Plus - **JDK**: Java 17 - **构建工具**: Maven - **第三方 API**: Track718 物流查询 API V3 --- ## 一、配置文件描述 ### 1.1 应用配置 (application.properties) 配置文件位置: `src/main/resources/application.properties` #### 基础配置 ```properties # 服务端口 server.port=8080 # 应用名称 spring.application.name=trace-logistics-service # 日志级别 logging.level.root=info logging.level.com.trace.logistics.core.mapper=debug ``` #### 数据库配置 ```properties # MySQL 数据源配置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.url=jdbc:mysql://127.0.0.1:3306/trace_logistics?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true spring.datasource.username=root spring.datasource.password=root123 ``` **说明**: - 数据库名称: `trace_logistics` - 字符编码: UTF-8 - 连接池: HikariCP (高性能连接池) #### 安全配置 ```properties # Spring Security 基础认证 spring.security.user.name=admin spring.security.user.password=#1Q2w3e4r# spring.security.user.roles=ADMIN ``` **访问控制**: - 所有 API 接口需要 HTTP Basic 认证 - 用户名: `admin` - 密码: `#1Q2w3e4r#` #### Track718 API 配置 ```properties # Track718 物流查询接口配置 track718.api.url=https://apigetway.track718.net/v2 track718.api.v3.url=https://apigetway.track718.net/v3 track718.api.key=your-api-key-here ``` **说明**: - `track718.api.url`: V2 版本 API 地址(用于批量新增单号) - `track718.api.v3.url`: V3 版本 API 地址(用于查询物流轨迹) - `track718.api.key`: Track718 平台申请的 API Key --- ## 二、调度任务描述 ### 2.1 主调度任务 **类**: `TraceLogisticsJobService` **定时规则**: `@Scheduled(cron = "0/10 * * * * ?")` - 每 10 秒执行一次 **执行流程**: ``` ┌─────────────────────────────────────────────────────────┐ │ 物流轨迹拉取定时任务执行流程 │ └─────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 1. 归档已完成或已取消的任务 │ │ track_status IN (100, 80) │ │ → 移至 trace_logistics_task_bak │ └─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 2. 标记超过重试次数的失败任务 │ │ track_status = 20 AND pull_status = 2 │ │ actual_send_count >= max_send │ │ → 更新为 track_status = 99 │ └─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 3. 处理新增任务 (track_status=0) │ │ → 调用 Track718 批量新增 API │ │ → 成功: track_status = 20 │ │ → 失败: 重试计数+1 │ └─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 4. 分时间间隔拉取物流轨迹数据 │ │ 循环处理: [0.5h, 1h, 2h, 3h, │ │ 4h, 5h, 6h, 12h, 24h] │ └─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 4.1 每个时间间隔执行: │ │ • 查询符合条件的任务 │ │ • 调用 Track718 查询 API │ │ • 保存包裹和轨迹明细数据 │ │ • 检查是否已签收 (status=40) │ │ • 已签收自动完成 (status=100) │ └─────────────────────────────────────┘ ``` ### 2.2 任务状态流转 ``` track_status 状态码说明: ┌──────┬──────────┬────────────────────────────────┐ │ 状态码 │ 状态名称 │ 说明 │ ├──────┼──────────┼────────────────────────────────┤ │ 0 │ 待跟踪 │ 新创建的任务,等待调用API新增单号 │ │ 20 │ 跟踪中 │ 单号已添加,正在定时拉取轨迹数据 │ │ 40 │ 已签收 │ 包裹已签收 (仅 package 表) │ │ 80 │ 已取消 │ 任务已取消,等待归档 │ │ 99 │ 失败 │ 超过最大重试次数,拉取失败 │ │ 100 │ 已完成 │ 包裹已签收且任务完成,等待归档 │ └──────┴──────────┴────────────────────────────────┘ ``` ### 2.3 时间间隔配置 任务根据 `job_value` 字段决定拉取频率: | job_value | 拉取间隔 | 使用场景 | |-----------|--------|-----------| | 0 | 0.5 小时 | 高频监控,重要包裹 | | 1 | 1 小时 | 常规跟踪 | | 2 | 2 小时 | 运输中包裹 | | 3 | 3 小时 | 一般优先级 | | 4 | 4 小时 | 低频跟踪 | | 5 | 5 小时 | 低频跟踪 | | 6 | 6 小时 | 低频跟踪 | | 12 | 12 小时 | 海运/慢速物流 | | 24 | 24 小时 | 超长周期物流 | **拉取逻辑**: - 系统查询 `last_update_time <= 当前时间 - 间隔时长` 的任务 - 每批次最多拉取 20 个单号 - 自动更新 `last_update_time` 为当前时间 ### 2.4 自动完成机制 **新增功能**: 包裹签收自动完成任务 当物流轨迹数据拉取成功后,系统会自动检查包裹状态: ```java if(trace_tracking_package.track_status ==40){ // 40 = Delivered (已签收) trace_logistics_task.track_status =100; // 100 = 已完成 pull_result ="包裹已签收,任务自动完成"; } ``` **优势**: - 无需人工干预,自动识别签收状态 - 减少无效的轨迹查询请求 - 任务自动进入归档流程 --- ## 三、表结构清单 ### 3.1 任务管理表 #### **trace_logistics_task** - 物流轨迹追踪任务表 核心业务表,存储待跟踪的物流单号和任务配置。 | 字段名 | 类型 | 说明 | |-------------------|-------------|------------------------------------| | id | BIGINT | 主键ID,自增 | | job_value | INT | 任务定时类型 (0=0.5h, 1=1h, ..., 24=24h) | | track_num | VARCHAR(64) | 物流单号(必填) | | ref_bill_no | VARCHAR(64) | 来源单号/内部单号 | | if_point | TINYINT | 是否重点监测 (1=是, 0=否) | | track_status | INT | 订单轨迹状态 (0/20/80/99/100) | | pull_status | TINYINT | 拉取状态 (1=成功, 2=失败) | | pull_result | TEXT | 拉取结果或失败原因 | | last_update_time | DATETIME | 最新物流轨迹获取时间 | | lang_code | VARCHAR(32) | 轨迹翻译语种 (如: zh-CN, en) | | max_send_count | BIGINT | 最大重试次数 (默认: 20) | | actual_send_count | BIGINT | 实际发送次数 | | create_time | DATETIME | 创建时间 | | update_time | DATETIME | 更新时间 | **索引**: - `idx_last_update_time_job_value_status`: 定时任务查询优化 - `idx_create_time_status`: 新任务查询优化 - `idx_update_time`: 更新时间索引 #### **trace_logistics_task_bak** - 任务归档表 结构与 `trace_logistics_task` 完全一致,用于存储已完成 (100) 或已取消 (80) 的任务。 **归档触发条件**: - `track_status = 100` (已完成) - `track_status = 80` (已取消) --- ### 3.2 轨迹数据表 #### **trace_tracking_package** - 物流轨迹包裹主表 存储物流包裹的基础信息和关键节点。 **核心字段分类**: | 分类 | 字段示例 | 说明 | |-------|-----------------------------------------|---------------| | 基础信息 | track_num, carrier_code | 物流单号、物流商代码 | | 物流状态 | track_status, track_sub_status | 主状态码、子状态码 | | 时效信息 | residence_time, haulage_time, sign_time | 停留/运输/签收时效(天) | | 首程物流商 | from_carrier_code, from_carrier_name | 头程承运商信息 | | 末程物流商 | to_carrier_code, to_carrier_name | 尾程承运商信息 | | 发件人信息 | shipper_contact, shipper_country | 发件人联系方式、国家 | | 收件人信息 | recipient_contact, recipient_country | 收件人联系方式、国家 | | 包裹信息 | package_weight_value, package_pieces | 重量、件数 | | 关键节点 | online_date, sign_date, latest_date | 上网/签收/最新时间 | **唯一索引**: - `udx_track_num_carrier`: (track_num, carrier_code) - 保证单号+物流商唯一 **物流状态码** (track_status): - 0 - 查询不到 - 8 - 运输途中 - 10 - 暂未上线 - 11 - 已上网 - 20 - 投递失败 - 30 - 到达待取 - 31 - 派送途中 - **40 - 签收成功** ⭐ (触发任务自动完成) - 50 - 可能异常 - 65 - 包裹退回 #### **trace_tracking_detail** - 物流轨迹明细表 存储物流包裹的每一条轨迹记录(行存储)。 | 字段名 | 类型 | 说明 | |--------------------|---------------|-------------------------| | id | BIGINT | 主键ID | | package_id | BIGINT | 关联包裹主表ID | | track_num | VARCHAR(64) | 物流单号 | | detail_type | VARCHAR(20) | 轨迹类型 (from=发件国, to=目的国) | | track_date | DATETIME | 轨迹状态时间 | | track_status | VARCHAR(1000) | 轨迹状态描述 | | track_address | TEXT | 轨迹地址信息 | | track_result | INT | 物流状态码 | | track_sub_result | INT | 子状态码 | | status_translation | VARCHAR(1000) | 翻译后的轨迹状态 | | addr_country | VARCHAR(50) | 国家 | | addr_city | VARCHAR(100) | 城市 | | addr_longitude | DECIMAL(10,6) | 经度 | | addr_latitude | DECIMAL(10,6) | 纬度 | **关联关系**: ``` trace_logistics_task (1) ──── (N) trace_tracking_package │ └──── (N) trace_tracking_detail ``` --- ## 四、如何新增物流轨迹任务管理 ### 4.1 API 接口 **基础URL**: `http://localhost:8080/api/trace/task` **认证方式**: HTTP Basic Auth (admin / #1Q2w3e4r#) #### 4.1.1 新增任务 **接口**: `POST /api/trace/task/save` **请求示例**: ```bash curl -X POST "http://localhost:8080/api/trace/task/save" \ -u admin:#1Q2w3e4r# \ -H "Content-Type: application/json" \ -d '{ "trackNum": "YT2345678901234", "refBillNo": "ORDER-2024-001", "jobValue": 1, "ifPoint": 0, "trackStatus": 0, "langCode": "zh-CN", "maxSendCount": 20, "creator": "system" }' ``` **响应示例**: ```json { "code": "0000", "message": "操作成功", "data": 1 } ``` ### 4.2 请求参数详细说明 #### 必填参数 | 参数名 | 类型 | 必填 | 说明 | |----------|---------|----|--------------------------------| | trackNum | String | ✅ | 物流单号,最大长度 64 字符 | | jobValue | Integer | ✅ | 拉取间隔类型,取值: 0/1/2/3/4/5/6/12/24 | #### 可选参数 | 参数名 | 类型 | 默认值 | 说明 | |-----------------|---------|------|---------------------------| | refBillNo | String | null | 内部订单号/参考单号,最大长度 64 字符 | | ifPoint | Integer | 0 | 是否重点监测: 0=否, 1=是 | | trackStatus | Integer | 0 | 初始状态,建议填 0 (待跟踪) | | langCode | String | null | 轨迹翻译语言: zh-CN=简体中文, en=英文 | | maxSendCount | Long | 20 | 最大重试次数,建议 10-50 之间 | | actualSendCount | Long | 0 | 实际发送次数,新任务填 0 | | creator | String | null | 创建人标识 | ### 4.3 参数使用建议 #### jobValue 选择策略 ``` ┌─────────────────────────────────────────────────────┐ │ 物流类型 推荐 job_value 原因 │ ├─────────────────────────────────────────────────────┤ │ 国际快递 0 或 1 时效快,需高频监控 │ │ 国内快递 1 或 2 时效较快 │ │ 跨境电商小包 2 或 3 时效中等 │ │ 海运包裹 6 或 12 周期长,低频即可 │ │ 重点监控包裹 0 最高频率监控 │ │ 测试单号 24 避免频繁调用 API │ └─────────────────────────────────────────────────────┘ ``` #### 重点监控 (ifPoint) 使用场景 设置 `ifPoint = 1` 的场景: - 高价值商品 - VIP 客户包裹 - 时效要求高的订单 - 需要特别关注的异常件 ### 4.4 批量新增示例 **场景**: 导入 100 个物流单号 ```bash # 方式1: 循环调用 API for trackNum in YT001 YT002 YT003 ...; do curl -X POST "http://localhost:8080/api/trace/task/save" \ -u admin:#1Q2w3e4r# \ -H "Content-Type: application/json" \ -d "{\"trackNum\": \"$trackNum\", \"jobValue\": 1}" done # 方式2: 直接插入数据库 (生产环境推荐) INSERT INTO trace_logistics_task (job_value, track_num, ref_bill_no, if_point, track_status, max_send_count, actual_send_count, create_time) VALUES (1, 'YT001', 'ORDER-001', 0, 0, 20, 0, NOW()), (1, 'YT002', 'ORDER-002', 0, 0, 20, 0, NOW()), (1, 'YT003', 'ORDER-003', 0, 0, 20, 0, NOW()); ``` ### 4.5 任务生命周期监控 #### 查询任务状态 ```bash # 分页查询任务列表 curl -X POST "http://localhost:8080/api/trace/task/page?current=1&size=20" \ -u admin:#1Q2w3e4r# \ -H "Content-Type: application/json" \ -d '{ "trackStatus": 20 }' ``` #### 根据ID查询任务 ```bash curl -X GET "http://localhost:8080/api/trace/task/get/1" \ -u admin:#1Q2w3e4r# ``` ### 4.6 常见问题处理 #### Q1: 任务一直处于 track_status=0 状态 **原因**: - Track718 API 调用失败 - 网络连接问题 - API Key 无效 **排查**: ```sql -- 查看失败原因 SELECT id, track_num, pull_result, actual_send_count FROM trace_logistics_task WHERE track_status = 0 AND pull_status = 2; ``` #### Q2: 包裹已签收但任务未完成 **原因**: - 旧版本未实现自动完成功能 - 包裹状态码不是 40 **解决**: ```sql -- 手动更新任务为已完成 UPDATE trace_logistics_task SET track_status = 100, pull_result = '手动完成' WHERE track_num = 'YT1234567890'; ``` #### Q3: 如何暂停某个任务的拉取 ```sql -- 方式1: 修改为已取消状态 (会被归档) UPDATE trace_logistics_task SET track_status = 80 WHERE id = 123; -- 方式2: 设置超大的 job_value (降低拉取频率) UPDATE trace_logistics_task SET job_value = 24 WHERE id = 123; ``` --- ## 五、开发与部署 ### 5.1 本地开发 ```bash # 1. 切换 JDK 版本 sdk use java 17.0.9-amz # 2. 编译项目 mvn clean compile # 3. 运行测试 mvn test # 4. 启动应用 mvn spring-boot:run ``` ### 5.2 打包部署 ```bash # 1. 打包 mvn clean package -DskipTests # 2. 生成的 jar 包位置 target/trace-logistics-service-1.1.0-SNAPSHOT.jar # 3. 运行 java -Xms512m -Xmx1024m -XX:MaxMetaspaceSize=256m \ -jar trace-logistics-service-1.1.0-SNAPSHOT.jar \ --spring.config.location=file:./application.properties ``` ### 5.3 数据库初始化 ```bash # 1. 创建数据库 CREATE DATABASE trace_logistics DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 2. 导入表结构 mysql -u root -p trace_logistics < dev-note/trace_tracking_tables.sql ``` ### 5.4 健康检查 ```bash # 检查应用是否正常运行 curl -u admin:#1Q2w3e4r# http://localhost:8080/api/trace/task/page?current=1&size=1 # 预期响应: HTTP 200 ``` --- ## 六、技术亮点 ### 6.1 性能优化 - ✅ **批量处理**: 每次最多 20 个单号批量查询,减少 API 调用次数 - ✅ **索引优化**: 关键查询字段建立联合索引,提升查询效率 - ✅ **连接池**: 使用 HikariCP 高性能连接池 - ✅ **定时锁机制**: ReentrantLock 防止任务重复执行 ### 6.2 可靠性保障 - ✅ **失败重试**: 支持配置最大重试次数,自动重试失败任务 - ✅ **幂等性**: 轨迹数据采用先删除后插入策略,保证数据一致性 - ✅ **事务控制**: 关键操作使用 `@Transactional` 保证原子性 - ✅ **归档机制**: 自动归档已完成/已取消任务,保持主表性能 ### 6.3 智能化 - ✅ **自动完成**: 包裹签收后自动更新任务状态为已完成 - ✅ **多频率策略**: 支持 9 种时间间隔,灵活应对不同场景 - ✅ **状态管理**: 完整的任务状态流转,覆盖全生命周期 --- ## 七、联系与支持 - **项目维护**: trace-logistics - **创建日期**: 2025-11-22 - **版本**: 1.1.0-SNAPSHOT --- ## 附录: 物流状态码完整清单 ### 主状态码 (track_status) | 代码 | 英文名称 | 中文描述 | |----|--------------------|--------| | 0 | NotFound | 查询不到 | | 8 | InTransit | 运输途中 | | 10 | NotOnline | 暂未上线 | | 11 | FirstOnline | 已上网 | | 12 | HasTransit | 已交航 | | 13 | ArrivesDestination | 到达目的国 | | 20 | Undelivered | 投递失败 | | 30 | PickUp | 到达待取 | | 31 | OnDelivery | 派送途中 | | 40 | Delivered | 签收成功 ⭐ | | 50 | Alert | 可能异常 | | 51 | TransitTooLong | 运输过久 | | 65 | Returned | 包裹退回 | ### 子状态码 (track_sub_status) 详细子状态参考 `TrackSubStatusEnum` 枚举类,共 30 个子状态。 --- **📝 备注**: 本文档最后更新于 2025-11-23,如有疑问请查阅代码注释或联系项目维护人员。