Files
light/README.md

539 lines
15 KiB
Markdown
Raw Normal View History

# 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接口查询当前位置信息
位置信息现在存储在服务器内存缓存中,而不是持久化到数据库,以提高访问速度和减少数据库负载。
2025-10-18 22:20:07 +08:00
#### WebSocket接口和交互逻辑
系统通过WebSocket实现实时位置同步端点为`/ws/location`
##### 连接建立
2025-10-19 05:41:24 +08:00
客户端通过WebSocket连接到`/ws/location?userId={userId}`端点建立连接需要在查询参数中提供用户ID。
2025-10-18 22:20:07 +08:00
##### 消息格式
所有消息都使用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": "张三",
2025-10-19 05:41:24 +08:00
"role": "DELIVERY_PERSON",
"userStatus": true,
"lastUpdateTime": 1634567890000,
"locationData": {
"latitude": 25.0342,
"longitude": 102.7057,
"timestamp": 1634567890000
}
2025-10-18 22:20:07 +08:00
}
]
}
```
2025-10-19 05:41:24 +08:00
3. **userLocationList用户位置列表** - 服务器每30秒发送所有在线用户的位置列表
2025-10-18 22:20:07 +08:00
```json
{
2025-10-19 05:41:24 +08:00
"type": "userLocationList",
"users": [
{
"userId": 123,
"locationData": {
"latitude": 25.0342,
"longitude": 102.7057,
"timestamp": 1634567890000
}
}
]
2025-10-18 22:20:07 +08:00
}
```
##### 交互流程
```
2025-10-19 05:41:24 +08:00
[用户签到] --> B{签到成功?}
2025-10-18 22:20:07 +08:00
B -->|是| C[建立WebSocket连接]
B -->|否| D[签到失败]
C --> E[自动订阅位置更新]
E --> F[接收subscribed确认]
F --> G[接收在线用户列表]
G --> H[开始位置更新循环]
H --> I[发送位置更新]
2025-10-19 05:41:24 +08:00
I --> J[每30秒接收一次位置列表]
2025-10-18 22:20:07 +08:00
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表中找不到对应记录则默认为游客角色
这种设计确保了数据的一致性,避免了在多个表中维护相同信息可能带来的问题。
2025-10-15 20:42:49 +08:00
## 本地开发与测试
### 环境配置
项目支持多种运行环境配置:
1. **本地开发环境** (`local`)
- 端口: 8080
2025-10-15 20:42:49 +08:00
- 数据库: 远程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"
2025-10-15 20:42:49 +08:00
# 或者使用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
```
2025-10-18 22:20:07 +08:00
在PowerShell中也可以使用以下命令运行本地环境
```powershell
$env:SPRING_PROFILES_ACTIVE = "local"
mvn spring-boot:run
```
2025-10-15 20:42:49 +08:00
### 运行Docker容器
```bash
# 构建本地Docker镜像
build-local.bat
# 运行容器
docker run -d --name light-delivery -p 8080:8080 light-delivery-app
2025-10-15 20:42:49 +08:00
```
## 部署说明
2025-10-15 20:42:49 +08:00
### 服务打包
使用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` - 用户签到
2025-10-19 05:41:24 +08:00
- `POST /user/signout` - 用户签退
- `POST /user/register` - 注册为配送员
### 订单相关
- `GET /orders` - 获取订单列表
- `GET /orders/{id}` - 获取订单详情
- `POST /orders/{id}/assign` - 指派订单
### 配送员相关
- `GET /delivery-persons` - 获取配送员列表
- `GET /delivery-persons/{id}` - 获取配送员详情
2025-10-19 05:41:24 +08:00
- `GET /delivery-persons/{id}/orders` - 获取配送员订单
### 员工管理相关(仅限管理员访问)
- `GET /employees` - 获取员工列表
- `POST /employees` - 添加员工
- `PUT /employees/{id}` - 更新员工信息
- `DELETE /employees/{id}` - 删除员工
### 位置同步相关
- `GET /location-sync/delivery-persons/locations` - 获取所有配送员位置
2025-10-18 22:20:07 +08:00
- 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": "张三",
2025-10-19 05:41:24 +08:00
"role": "DELIVERY_PERSON",
"userStatus": true,
"lastUpdateTime": 1634567890000,
"locationData": {
"latitude": 25.0342,
"longitude": 102.7057,
"timestamp": 1634567890000
}
2025-10-18 22:20:07 +08:00
}
]
}
```
2025-10-19 05:41:24 +08:00
3. **userLocationList用户位置列表** - 服务器每30秒发送所有在线用户的位置列表
2025-10-18 22:20:07 +08:00
```json
{
2025-10-19 05:41:24 +08:00
"type": "userLocationList",
"users": [
{
"userId": 123,
"locationData": {
"latitude": 25.0342,
"longitude": 102.7057,
"timestamp": 1634567890000
}
}
]
2025-10-18 22:20:07 +08:00
}
```
2025-10-19 15:59:05 +08:00
## API接口响应格式
### 用户签到接口 `/user/signin`
#### 请求参数
- Method: `POST`
- Headers: `Authorization: Bearer <token>`
- 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 <token>`
#### 成功响应
```json
{
"success": true,
"message": "签退成功"
}
```
#### 失败响应
```json
{
"success": false,
"message": "错误信息"
}
```
## 最近更新
2025-10-18 22:20:07 +08:00
### WebSocket使用方式变更重要变更
为了更好地分离关注点和提高系统安全性我们对WebSocket使用方式进行了重要变更
- 移除了WebSocket中的签到/签退功能这些操作现在完全通过REST API进行
- WebSocket现在仅用于位置同步不再处理用户状态变更
- 用户需要先通过REST API签到然后才能建立WebSocket连接并接收位置更新
- 用户签退时服务器会自动取消订阅并关闭WebSocket连接
- 客户端不再需要发送subscribe/unsubscribe消息这些操作由服务器自动处理
2025-10-19 05:41:24 +08:00
- 服务器现在每30秒批量发送一次所有在线用户的位置信息而不是实时发送单个用户位置更新
2025-10-18 22:20:07 +08:00
### 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. 员工管理接口仅限管理员角色访问
2025-10-18 22:20:07 +08:00
6. 用户角色信息现在通过员工表动态获取,确保数据一致性
7. WebSocket位置同步现在支持所有已签到用户包括管理员和配送员
8. WebSocket仅用于位置同步签到/签退操作需通过REST API完成