# Light Delivery 后端项目 ## 项目概述 Light Delivery 是一个为小程序配送服务设计的后端系统,提供了用户管理、订单管理、配送员管理、位置同步等核心功能。 ## 技术栈 - Java 17 - Spring Boot 3.1.4 - Spring Data JPA - Spring WebSocket - MySQL - Maven ## 主要功能模块 ### 1. 用户管理 - 微信小程序登录 - 用户角色管理(管理员、配送员、游客) - 用户签到功能 ### 2. 订单管理 - 订单创建与查询 - 订单状态跟踪 - 订单指派给配送员 ### 3. 配送员管理 - 配送员注册 - 配送员位置实时同步 - 配送员状态管理 ### 4. 位置同步 - 基于WebSocket的实时位置同步 - REST API位置查询接口 - 位置过期处理机制 ### 5. 员工管理(新增) - 员工信息维护(仅限管理员) - 员工增删改查功能 - 员工角色管理(管理员/配送员) ## 项目结构 ``` src ├── main │ ├── java │ │ └── com │ │ └── light │ │ └── delivery │ │ ├── config # 配置类 │ │ ├── controller # 控制器层 │ │ ├── dto # 数据传输对象 │ │ ├── exception # 异常处理 │ │ ├── model # 实体模型 │ │ ├── repository # 数据访问层 │ │ ├── service # 业务逻辑层 │ │ │ └── impl # 业务逻辑实现 │ │ └── util # 工具类 │ └── resources │ ├── application.properties # 配置文件 │ └── db # 数据库脚本 └── test # 测试代码 ``` ## 核心设计 ### 认证授权机制 系统采用基于JWT的无状态认证机制: 1. 用户通过微信登录获取code 2. 后端通过code换取用户openid 3. 根据openid查找或创建用户 4. 生成JWT Token返回给前端 5. 前端在后续请求中通过Authorization头携带Token 6. 后端通过拦截器验证Token有效性 ### 实时位置同步 位置同步采用双通道设计: 1. WebSocket实时推送:建立长连接,服务器主动推送位置更新 2. REST API查询:提供HTTP接口查询当前位置信息 位置信息现在存储在服务器内存缓存中,而不是持久化到数据库,以提高访问速度和减少数据库负载。 #### WebSocket接口和交互逻辑 系统通过WebSocket实现实时位置同步,端点为:`/ws/location`。 ##### 连接建立 客户端通过WebSocket连接到`/ws/location?userId={userId}`端点建立连接,需要在查询参数中提供用户ID。 ##### 消息格式 所有消息都使用JSON格式。 ###### 1. 客户端发送的消息类型 1. **updateLocation(位置更新)** - 更新用户位置 ```json { "type": "updateLocation", "userId": 123, "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } ``` ###### 2. 服务器发送的消息类型 1. **subscribed(订阅成功响应)** - 服务器确认订阅成功 ```json { "type": "subscribed", "userId": 123 } ``` 2. **onlineUserList(在线用户列表)** - 服务器发送当前在线用户列表 ```json { "type": "onlineUserList", "users": [ { "userId": 123, "name": "张三", "role": "DELIVERY_PERSON", "userStatus": true, "lastUpdateTime": 1634567890000, "locationData": { "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } } ] } ``` 3. **userLocationList(用户位置列表)** - 服务器每30秒发送所有在线用户的位置列表 ```json { "type": "userLocationList", "users": [ { "userId": 123, "locationData": { "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } } ] } ``` ##### 交互流程 ``` [用户签到] --> B{签到成功?} B -->|是| C[建立WebSocket连接] B -->|否| D[签到失败] C --> E[自动订阅位置更新] E --> F[接收subscribed确认] F --> G[接收在线用户列表] G --> H[开始位置更新循环] H --> I[发送位置更新] I --> J[每30秒接收一次位置列表] K[用户签退] --> L{签退成功?} L -->|是| M[自动取消订阅并关闭WebSocket连接] L -->|否| N[签退失败] ``` ##### 角色区分 - 管理员(ADMIN)和配送员(DELIVERY_PERSON)都可以接收位置更新 - 位置广播消息中包含用户角色信息,便于客户端区分显示 - 只有已签到用户才会收到位置更新广播 ### 数据模型 主要实体包括: - User:用户基础信息实体(所有用户通用) - Employee:员工信息实体(后台配置数据,用于验证用户身份) - DeliveryPerson:配送员扩展信息实体 - Order:订单实体 用户系统架构说明: - 所有用户首先以游客身份静默登录,创建User记录 - 用户签到或注册时,系统根据手机号在Employee表中查找匹配记录 - 如果匹配成功,将用户的openid写入Employee表,表示该员工已成为系统用户 - 根据Employee中的角色信息动态确定User的角色 - 对于配送员,还会创建或更新DeliveryPerson记录 ### 用户角色管理优化(新增) 为了解决数据一致性问题,我们对用户角色管理进行了优化: 1. 移除了User表中的role字段,避免在User表和Employee表中重复维护角色信息 2. 用户角色现在完全通过Employee表进行管理 3. 当需要获取用户角色时,系统会根据用户的手机号在Employee表中查找对应记录 4. 如果用户未注册(没有手机号)或在Employee表中找不到对应记录,则默认为游客角色 这种设计确保了数据的一致性,避免了在多个表中维护相同信息可能带来的问题。 ## 本地开发与测试 ### 环境配置 项目支持多种运行环境配置: 1. **本地开发环境** (`local`) - 端口: 8080 - 数据库: 远程MySQL (与生产环境相同) - SSL: 禁用 - 日志级别: DEBUG 2. **测试环境** (`test`) - 端口: 8443 - 数据库: H2内存数据库 - SSL: 禁用 - 日志级别: DEBUG 3. **生产环境** (`prod`) - 端口: 443 - 数据库: 远程MySQL - SSL: 启用 - 日志级别: INFO ### 本地运行方式 #### 方式一:IDE直接运行(推荐用于开发调试) 1. 在IDE中打开[LightApplication.java](file:///E:/StudyProject/Light/src/main/java/com/light/delivery/LightApplication.java) 2. 添加运行参数: `-Dspring.profiles.active=local` 3. 直接运行main方法 #### 方式二:Maven命令运行 ```bash # 使用local配置文件运行 mvn spring-boot:run -D"spring.profiles.active"="local" # 或者使用test配置文件运行(使用内存数据库) mvn spring-boot:run -Dspring-boot.run.profiles=test ``` #### 方式三:打包后运行 ```bash # 打包项目 mvn clean package -DskipTests # 使用local配置运行 java -jar target/light-delivery-1.0.0.jar --spring.profiles.active=local # 使用test配置运行 java -jar target/light-delivery-1.0.0.jar --spring.profiles.active=test ``` 在PowerShell中也可以使用以下命令运行本地环境: ```powershell $env:SPRING_PROFILES_ACTIVE = "local" mvn spring-boot:run ``` ### 运行Docker容器 ```bash # 构建本地Docker镜像 build-local.bat # 运行容器 docker run -d --name light-delivery -p 8080:8080 light-delivery-app ``` ## 部署说明 ### 服务打包 使用Maven将项目打包为可执行JAR文件: ```bash # 清理并打包,跳过测试 mvn clean package -DskipTests # 或者运行测试后打包 mvn clean package ``` 打包后的文件位于: `target/light-delivery-1.0.0.jar` ### Docker镜像构建 项目支持多种Docker镜像构建方式: #### 方式一:使用Jib插件(推荐) ```bash # 构建Docker镜像到本地Docker守护进程 mvn compile jib:dockerBuild # 构建Docker镜像到tar文件 mvn compile jib:buildTar ``` #### 方式二:使用Dockerfile ```bash # 构建Docker镜像 docker build -t light-delivery-app . ``` ### 云端部署 使用提供的部署脚本将应用部署到云服务器: ```bash # Windows环境下运行 deploy.bat ``` 脚本将执行以下操作: 1. 构建Docker镜像 2. 导出为tar文件 3. 通过SCP上传到云服务器 4. 在云服务器上加载镜像并运行容器 ## API接口 主要API接口包括: ### 用户相关 - `POST /user/wxlogin` - 微信登录 - `GET /user/info` - 获取用户信息 - `POST /user/logout` - 用户登出 - `POST /user/signin` - 用户签到 - `POST /user/signout` - 用户签退 - `POST /user/register` - 注册为配送员 ### 订单相关 - `GET /orders` - 获取订单列表 - `GET /orders/{id}` - 获取订单详情 - `POST /orders/{id}/assign` - 指派订单 ### 配送员相关 - `GET /delivery-persons` - 获取配送员列表 - `GET /delivery-persons/{id}` - 获取配送员详情 - `GET /delivery-persons/{id}/orders` - 获取配送员订单 ### 员工管理相关(仅限管理员访问) - `GET /employees` - 获取员工列表 - `POST /employees` - 添加员工 - `PUT /employees/{id}` - 更新员工信息 - `DELETE /employees/{id}` - 删除员工 ### 位置同步相关 - `GET /location-sync/delivery-persons/locations` - 获取所有配送员位置 - WebSocket端点: `/ws/location` - 实时位置同步 ### WebSocket消息格式 客户端和服务器通过WebSocket发送JSON格式的消息。 #### 客户端发送的消息类型 1. **updateLocation(位置更新)** - 更新用户位置 ```json { "type": "updateLocation", "userId": 123, "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } ``` #### 服务器发送的消息类型 1. **subscribed(订阅成功响应)** - 服务器确认订阅成功 ```json { "type": "subscribed", "userId": 123 } ``` 2. **onlineUserList(在线用户列表)** - 服务器发送当前在线用户列表 ```json { "type": "onlineUserList", "users": [ { "userId": 123, "name": "张三", "role": "DELIVERY_PERSON", "userStatus": true, "lastUpdateTime": 1634567890000, "locationData": { "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } } ] } ``` 3. **userLocationList(用户位置列表)** - 服务器每30秒发送所有在线用户的位置列表 ```json { "type": "userLocationList", "users": [ { "userId": 123, "locationData": { "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } } ] } ``` ## API接口响应格式 ### 用户签到接口 `/user/signin` #### 请求参数 - Method: `POST` - Headers: `Authorization: Bearer ` - Body: ```json { "latitude": 25.0342, "longitude": 102.7057, "timestamp": 1634567890000 } ``` #### 成功响应 ```json { "success": true, "userInfo": { "id": 123, "name": "张三", "phone": "13800138000", "role": "DELIVERY_PERSON", "openid": "oK4fS5ABCDEF123456" } } ``` #### 失败响应 ```json { "success": false, "message": "错误信息" } ``` ### 用户签退接口 `/user/signout` #### 请求参数 - Method: `POST` - Headers: `Authorization: Bearer ` #### 成功响应 ```json { "success": true, "message": "签退成功" } ``` #### 失败响应 ```json { "success": false, "message": "错误信息" } ``` ## 最近更新 ### WebSocket使用方式变更(重要变更) 为了更好地分离关注点和提高系统安全性,我们对WebSocket使用方式进行了重要变更: - 移除了WebSocket中的签到/签退功能,这些操作现在完全通过REST API进行 - WebSocket现在仅用于位置同步,不再处理用户状态变更 - 用户需要先通过REST API签到,然后才能建立WebSocket连接并接收位置更新 - 用户签退时,服务器会自动取消订阅并关闭WebSocket连接 - 客户端不再需要发送subscribe/unsubscribe消息,这些操作由服务器自动处理 - 服务器现在每30秒批量发送一次所有在线用户的位置信息,而不是实时发送单个用户位置更新 ### WebSocket位置同步增强(新增) 为了支持管理员和配送员都能接收位置更新信息,我们对WebSocket位置同步功能进行了增强: - 修改了LocationWebSocketHandler,使其支持所有用户类型(包括管理员和配送员) - 在位置消息中添加了用户角色信息,便于客户端区分并使用不同图标显示 - 重构了WebSocket处理逻辑,使其更加通用和可扩展 - 实现了在线用户列表管理和广播机制 ### 用户角色管理优化(新增) 为解决数据一致性问题,我们优化了用户角色管理机制: - 移除了User表中的role字段 - 用户角色现在完全通过Employee表进行管理 - 系统会根据用户的手机号在Employee表中动态查找角色信息 - 未注册用户默认为游客角色 ### 员工管理功能(新增) 为便于管理员维护员工信息,我们新增了员工管理功能: - 新增EmployeeController控制器,提供员工信息的增删改查接口 - 新增EmployeeService服务层,处理员工相关的业务逻辑 - 新增EmployeeDto数据传输对象,用于前后端数据交互 - 添加权限控制,仅管理员可访问员工管理接口 - 添加全局异常处理机制 ### 位置历史记录功能移除 为了简化系统架构并提高性能,我们移除了位置历史记录功能。具体变更包括: - 删除了`LocationHistory`实体类 - 删除了`LocationHistoryRepository`数据访问接口 - 删除了`LocationService`服务接口及其实现类`LocationServiceImpl` - 删除了`LocationController`控制器及相关API端点 位置信息现在完全基于实时同步机制,存储在服务器内存中,不再持久化到数据库。 ## 注意事项 1. 系统仅支持微信登录,不再支持用户名密码登录 2. 所有敏感接口都需要通过JWT Token认证 3. 配送员位置信息具有时效性,默认5分钟内有效 4. 位置历史记录功能已被移除,如有需要可使用第三方服务进行位置追踪 5. 员工管理接口仅限管理员角色访问 6. 用户角色信息现在通过员工表动态获取,确保数据一致性 7. WebSocket位置同步现在支持所有已签到用户(包括管理员和配送员) 8. WebSocket仅用于位置同步,签到/签退操作需通过REST API完成