清理无用目录
This commit is contained in:
parent
11d677d95a
commit
840a441d9e
@ -1,260 +0,0 @@
|
||||
# 设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
本设计文档描述了 QAUP 项目的 Docker 容器化部署架构。该方案将整个项目打包为多个 Docker 容器,包括后端应用、前端应用、数据库和缓存服务,适用于在客户的 Ubuntu 系统上进行生产环境部署。
|
||||
|
||||
## 架构
|
||||
|
||||
### 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Docker Host (Ubuntu)"
|
||||
subgraph "qaup-network"
|
||||
nginx[Nginx容器<br/>端口: 80, 443]
|
||||
app[QAUP应用容器<br/>端口: 8080]
|
||||
postgres[(PostgreSQL容器<br/>端口: 5432)]
|
||||
redis[(Redis容器<br/>端口: 6379)]
|
||||
end
|
||||
|
||||
subgraph "Docker Volumes"
|
||||
db_data[数据库数据卷]
|
||||
app_logs[应用日志卷]
|
||||
upload_files[文件上传卷]
|
||||
nginx_conf[Nginx配置卷]
|
||||
end
|
||||
end
|
||||
|
||||
Client[客户端浏览器] --> nginx
|
||||
nginx --> app
|
||||
app --> postgres
|
||||
app --> redis
|
||||
|
||||
postgres -.-> db_data
|
||||
app -.-> app_logs
|
||||
app -.-> upload_files
|
||||
nginx -.-> nginx_conf
|
||||
```
|
||||
|
||||
### 容器组件
|
||||
|
||||
1. **Nginx 容器**: 反向代理和静态文件服务
|
||||
2. **QAUP 应用容器**: Spring Boot 应用(包含所有模块)
|
||||
3. **PostgreSQL 容器**: 数据库服务(包含 PostGIS 扩展)
|
||||
4. **Redis 容器**: 缓存和会话存储
|
||||
|
||||
## 组件和接口
|
||||
|
||||
### 1. QAUP 应用容器
|
||||
|
||||
**基础镜像**: `openjdk:17-jre-slim`
|
||||
|
||||
**功能**:
|
||||
- 运行 qaup-admin.jar(包含所有模块)
|
||||
- 提供 REST API 服务
|
||||
- 处理定时任务
|
||||
- 管理文件上传
|
||||
|
||||
**配置**:
|
||||
- JVM 参数优化
|
||||
- 环境变量配置
|
||||
- 健康检查端点
|
||||
|
||||
### 2. Nginx 容器
|
||||
|
||||
**基础镜像**: `nginx:alpine`
|
||||
|
||||
**功能**:
|
||||
- 反向代理到后端应用
|
||||
- 服务前端静态文件
|
||||
- SSL 终止(可选)
|
||||
- 负载均衡(单实例时作为代理)
|
||||
|
||||
**配置**:
|
||||
- 自定义 nginx.conf
|
||||
- 前端构建文件挂载
|
||||
- 日志配置
|
||||
|
||||
### 3. PostgreSQL 容器
|
||||
|
||||
**基础镜像**: `postgis/postgis:15-3.3`
|
||||
|
||||
**功能**:
|
||||
- 数据持久化存储
|
||||
- 空间数据支持(PostGIS)
|
||||
- 数据库初始化脚本
|
||||
|
||||
**配置**:
|
||||
- 数据库初始化
|
||||
- 性能参数调优
|
||||
- 数据卷挂载
|
||||
|
||||
### 4. Redis 容器
|
||||
|
||||
**基础镜像**: `redis:7-alpine`
|
||||
|
||||
**功能**:
|
||||
- 缓存存储
|
||||
- 会话管理
|
||||
- 数据持久化
|
||||
|
||||
**配置**:
|
||||
- Redis 配置文件
|
||||
- 持久化策略
|
||||
- 内存限制
|
||||
|
||||
## 数据模型
|
||||
|
||||
### Docker Compose 配置结构
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
qaup-app:
|
||||
# 应用服务配置
|
||||
qaup-nginx:
|
||||
# Nginx 服务配置
|
||||
qaup-postgres:
|
||||
# PostgreSQL 服务配置
|
||||
qaup-redis:
|
||||
# Redis 服务配置
|
||||
|
||||
volumes:
|
||||
# 数据卷定义
|
||||
|
||||
networks:
|
||||
# 网络定义
|
||||
```
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
**应用配置**:
|
||||
- `SPRING_PROFILES_ACTIVE`: 激活的配置文件
|
||||
- `DB_HOST`, `DB_PORT`, `DB_NAME`: 数据库连接
|
||||
- `REDIS_HOST`, `REDIS_PORT`: Redis 连接
|
||||
- `UPLOAD_PATH`: 文件上传路径
|
||||
|
||||
**数据库配置**:
|
||||
- `POSTGRES_DB`: 数据库名称
|
||||
- `POSTGRES_USER`: 数据库用户
|
||||
- `POSTGRES_PASSWORD`: 数据库密码
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 容器故障处理
|
||||
|
||||
1. **自动重启策略**
|
||||
- 所有服务配置 `restart: unless-stopped`
|
||||
- 健康检查失败时自动重启
|
||||
|
||||
2. **数据恢复**
|
||||
- 数据库数据通过卷持久化
|
||||
- 应用日志和上传文件持久化
|
||||
|
||||
3. **网络故障处理**
|
||||
- 容器间通信通过内部网络
|
||||
- 外部访问通过 Nginx 代理
|
||||
|
||||
### 监控和告警
|
||||
|
||||
1. **健康检查**
|
||||
- 应用: `/actuator/health`
|
||||
- 数据库: `pg_isready`
|
||||
- Redis: `redis-cli ping`
|
||||
|
||||
2. **日志管理**
|
||||
- 应用日志通过卷挂载
|
||||
- 容器日志通过 Docker 日志驱动
|
||||
- 日志轮转配置
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 部署测试
|
||||
|
||||
1. **容器启动测试**
|
||||
- 验证所有容器正常启动
|
||||
- 检查容器间网络连通性
|
||||
|
||||
2. **功能测试**
|
||||
- API 接口可访问性
|
||||
- 前端页面加载
|
||||
- 数据库连接正常
|
||||
|
||||
3. **持久化测试**
|
||||
- 容器重启后数据保持
|
||||
- 文件上传功能正常
|
||||
|
||||
### 性能测试
|
||||
|
||||
1. **资源使用测试**
|
||||
- 内存使用监控
|
||||
- CPU 使用监控
|
||||
- 磁盘 I/O 监控
|
||||
|
||||
2. **并发测试**
|
||||
- 多用户同时访问
|
||||
- 数据库连接池测试
|
||||
|
||||
## 安全考虑
|
||||
|
||||
### 网络安全
|
||||
|
||||
1. **网络隔离**
|
||||
- 使用自定义 Docker 网络
|
||||
- 仅暴露必要端口
|
||||
|
||||
2. **访问控制**
|
||||
- 数据库仅允许应用容器访问
|
||||
- Redis 仅允许内部网络访问
|
||||
|
||||
### 数据安全
|
||||
|
||||
1. **敏感信息管理**
|
||||
- 使用环境变量或 Docker secrets
|
||||
- 数据库密码加密存储
|
||||
|
||||
2. **文件权限**
|
||||
- 容器内使用非 root 用户
|
||||
- 挂载卷设置适当权限
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 离线部署准备阶段(在有网络环境中进行)
|
||||
|
||||
1. **Docker 镜像准备**
|
||||
- 构建所有自定义镜像
|
||||
- 拉取所有基础镜像
|
||||
- 导出镜像为 tar 文件
|
||||
|
||||
2. **应用构建**
|
||||
- Maven 构建 JAR 包
|
||||
- 创建应用 Docker 镜像
|
||||
|
||||
3. **前端构建**
|
||||
- npm 构建前端资源
|
||||
- 准备 Nginx 静态文件
|
||||
|
||||
4. **部署包打包**
|
||||
- 打包所有 Docker 镜像文件
|
||||
- 打包配置文件和脚本
|
||||
- 创建离线安装包
|
||||
|
||||
### 现场部署阶段(在客户内网环境中进行)
|
||||
|
||||
1. **环境准备**
|
||||
- 安装 Docker 和 Docker Compose
|
||||
- 创建必要目录和权限
|
||||
|
||||
2. **镜像导入**
|
||||
- 导入所有 Docker 镜像
|
||||
- 验证镜像完整性
|
||||
|
||||
3. **服务启动**
|
||||
- 启动数据库和缓存服务
|
||||
- 初始化数据库架构
|
||||
- 启动应用和 Nginx 服务
|
||||
|
||||
4. **验证部署**
|
||||
- 健康检查验证
|
||||
- 功能测试验证
|
||||
@ -1,99 +0,0 @@
|
||||
# 需求文档
|
||||
|
||||
## 介绍
|
||||
|
||||
本文档概述了在客户 Ubuntu 系统上使用 Docker 部署当前 QAUP 项目所有内容的需求。部署范围包括项目中的所有模块:qaup-admin(主应用)、qaup-framework(核心框架)、qaup-system(系统管理)、qaup-quartz(定时任务)、qaup-generator(代码生成)、qaup-common(通用工具)、qaup-collision(碰撞避免)、qaup-ui(前端界面),以及相关的数据库和缓存服务。这是面向生产环境的长期运行部署,需要确保稳定性、可维护性和数据持久化,而不是临时测试环境。
|
||||
|
||||
## 需求
|
||||
|
||||
### 需求 1
|
||||
|
||||
**用户故事:** 作为系统管理员,我希望使用 Docker 容器部署整个 QAUP 项目,以便在不同的 Ubuntu 环境中实现一致、可移植且易于管理的部署。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当执行 Docker 部署时,系统应创建后端应用、前端应用、PostgreSQL 数据库和 Redis 缓存的容器
|
||||
2. 当容器启动时,它们应能够通过 Docker 网络相互通信
|
||||
3. 当部署完成时,前端应用和后端 API 应可在配置的端口上访问
|
||||
4. 当容器重启时,数据应通过 Docker 卷持久化保存
|
||||
5. 当系统长期运行时,容器应配置为自动重启和故障恢复
|
||||
|
||||
### 需求 2
|
||||
|
||||
**用户故事:** 作为数据库管理员,我希望 PostgreSQL 在 Docker 容器中运行并具有适当的数据持久化,以便数据库数据在容器重启和更新时得到保留。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当 PostgreSQL 容器启动时,应自动使用所需的数据库架构进行初始化
|
||||
2. 当容器停止并重启时,所有数据应得到保留
|
||||
3. 当数据库初始化运行时,应创建所有必需的表,包括空间扩展
|
||||
4. 当需要备份时,数据库数据应通过 Docker 卷轻松访问
|
||||
5. 当系统长期运行时,数据库应配置适当的资源限制和性能优化
|
||||
|
||||
### 需求 3
|
||||
|
||||
**用户故事:** 作为 DevOps 工程师,我希望有特定环境的配置管理,以便相同的 Docker 镜像可以部署到不同的环境(开发、测试、生产)。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当部署到不同环境时,配置应通过环境变量外部化
|
||||
2. 当配置敏感数据时,应通过 Docker secrets 或环境文件管理
|
||||
3. 当配置更改时,容器应能够在不重建镜像的情况下重新加载
|
||||
4. 当部署时,数据库连接参数应可按环境配置
|
||||
|
||||
### 需求 4
|
||||
|
||||
**用户故事:** 作为系统操作员,我希望有全面的日志记录和监控,以便在生产环境中排除故障和监控系统健康状况。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当容器运行时,日志应通过 Docker 日志驱动程序访问
|
||||
2. 当系统部署时,应为所有服务配置健康检查
|
||||
3. 当需要监控时,应为外部监控系统公开指标
|
||||
4. 当需要日志轮转时,应配置以防止磁盘空间问题
|
||||
|
||||
### 需求 5
|
||||
|
||||
**用户故事:** 作为部署工程师,我希望有自动化部署脚本和文档,以便客户部署保持一致,并且可以由技术人员在最少培训的情况下执行。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当启动部署时,单个命令应部署整个系统
|
||||
2. 当提供部署文档时,应包括 Ubuntu 系统的分步说明
|
||||
3. 当需要更新时,部署应支持最小停机时间的滚动更新
|
||||
4. 当需要故障排除时,应提供诊断脚本
|
||||
|
||||
### 需求 6
|
||||
|
||||
**用户故事:** 作为安全管理员,我希望 Docker 部署遵循安全最佳实践,以便系统在客户环境中是安全的。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当创建容器时,应尽可能使用非 root 用户运行
|
||||
2. 当发生网络通信时,应仅限制为必要的端口
|
||||
3. 当挂载敏感文件时,应具有适当的权限
|
||||
4. 当系统部署时,应禁用或删除不必要的服务
|
||||
#
|
||||
## 需求 7
|
||||
|
||||
**用户故事:** 作为运维人员,我希望 Docker 部署配置适合生产环境长期运行,以便系统能够稳定可靠地为客户提供服务。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当容器配置时,应设置适当的重启策略(如 restart: unless-stopped)
|
||||
2. 当系统运行时,应配置资源限制防止单个容器消耗过多系统资源
|
||||
3. 当服务异常时,容器应能自动重启并恢复服务
|
||||
4. 当系统升级时,应支持零停机或最小停机时间的更新策略
|
||||
5. 当长期运行时,日志应配置轮转以防止磁盘空间耗尽
|
||||
#
|
||||
## 需求 8
|
||||
|
||||
**用户故事:** 作为现场部署工程师,我希望能够在无互联网连接的内网环境中部署系统,以便在客户的隔离网络环境中完成部署。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当客户服务器无法访问互联网时,部署应能够完全离线进行
|
||||
2. 当准备部署包时,应包含所有必需的 Docker 镜像文件
|
||||
3. 当进行离线部署时,不应依赖任何外部网络资源下载
|
||||
4. 当系统运行时,应能够在完全隔离的网络环境中正常工作
|
||||
5. 当需要更新时,应提供离线更新包和更新流程
|
||||
@ -1,85 +0,0 @@
|
||||
# 实施计划
|
||||
|
||||
- [x] 1. 创建 Docker 构建配置
|
||||
- 为 QAUP 应用创建 Dockerfile
|
||||
- 配置 Maven 构建优化以支持 Docker 构建
|
||||
- 创建 .dockerignore 文件排除不必要的文件
|
||||
- _需求: 1.1, 1.2_
|
||||
|
||||
- [x] 1.1 创建离线部署镜像准备脚本
|
||||
- 编写脚本拉取所有必需的基础镜像
|
||||
- 创建镜像导出和打包脚本
|
||||
- 配置镜像版本锁定以确保一致性
|
||||
- _需求: 8.2, 8.3_
|
||||
|
||||
- [x] 2. 创建前端构建和 Nginx 配置
|
||||
- 创建前端构建脚本
|
||||
- 配置 Nginx Dockerfile 和配置文件
|
||||
- 设置静态文件服务和反向代理规则
|
||||
- _需求: 1.3, 3.1_
|
||||
|
||||
- [x] 3. 配置数据库初始化
|
||||
- 创建 PostgreSQL 初始化脚本
|
||||
- 配置 PostGIS 扩展安装
|
||||
- 设置数据库架构导入脚本
|
||||
- _需求: 2.1, 2.3_
|
||||
|
||||
- [x] 4. 创建 Docker Compose 配置
|
||||
- 编写 docker-compose.yml 主配置文件
|
||||
- 配置服务间网络和依赖关系
|
||||
- 设置数据卷和持久化存储
|
||||
- _需求: 1.1, 1.4, 2.2_
|
||||
|
||||
- [x] 5. 配置环境变量和配置管理
|
||||
- 创建环境变量模板文件
|
||||
- 配置生产环境参数
|
||||
- 设置敏感信息管理方案
|
||||
- _需求: 3.1, 3.2, 6.2_
|
||||
|
||||
- [x] 6. 实现健康检查和监控
|
||||
- 为每个服务配置健康检查
|
||||
- 设置容器重启策略
|
||||
- 配置日志管理和轮转
|
||||
- _需求: 4.2, 4.4, 7.1_
|
||||
|
||||
- [x] 7. 创建部署脚本和文档
|
||||
- 编写自动化部署脚本
|
||||
- 创建 Ubuntu 系统部署指南
|
||||
- 编写故障排除和维护文档
|
||||
- _需求: 5.1, 5.2, 5.4_
|
||||
|
||||
- [x] 7.1 创建离线部署包和脚本
|
||||
- 编写离线部署包制作脚本
|
||||
- 创建镜像导入和验证脚本
|
||||
- 编写内网环境部署指南
|
||||
- _需求: 8.1, 8.4, 8.5_
|
||||
|
||||
- [x] 8. 配置生产环境优化
|
||||
- 设置容器资源限制
|
||||
- 配置 JVM 参数优化
|
||||
- 实现零停机更新策略
|
||||
- _需求: 7.2, 7.4, 7.5_
|
||||
|
||||
- [x] 9. 实现安全配置
|
||||
- 配置容器非 root 用户运行
|
||||
- 设置网络访问控制
|
||||
- 配置文件权限和安全策略
|
||||
- _需求: 6.1, 6.3, 6.4_
|
||||
|
||||
- [x] 10. 创建备份和恢复方案
|
||||
- 实现数据库备份脚本
|
||||
- 创建系统恢复文档
|
||||
- 测试备份恢复流程
|
||||
- _需求: 5.3, 2.4_
|
||||
|
||||
- [x] 11. 进行集成测试
|
||||
- 测试完整部署流程
|
||||
- 验证所有服务功能正常
|
||||
- 进行性能和稳定性测试
|
||||
- _需求: 1.3, 4.1, 7.3_
|
||||
|
||||
- [x] 12. 创建运维工具和脚本
|
||||
- 编写系统状态检查脚本
|
||||
- 创建日志查看和分析工具
|
||||
- 实现服务管理命令脚本
|
||||
- _需求: 4.3, 5.4_
|
||||
@ -1,369 +0,0 @@
|
||||
# Design Document
|
||||
|
||||
## Overview
|
||||
|
||||
本设计文档描述了为QAUP项目集成Flyway数据库迁移工具的技术方案。通过分析现有的SQL文件结构和部署流程,设计一个完整的数据库版本管理系统,包括基线迁移脚本的创建、Flyway配置集成、部署脚本修改以及开发流程规范。
|
||||
|
||||
## Architecture
|
||||
|
||||
### 系统架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A[开发环境] --> B[Maven构建]
|
||||
B --> C[Flyway迁移脚本]
|
||||
C --> D[应用启动]
|
||||
D --> E[Flyway自动迁移]
|
||||
E --> F[PostgreSQL数据库]
|
||||
|
||||
G[现有SQL文件] --> H[脚本整理工具]
|
||||
H --> I[基线迁移脚本]
|
||||
I --> C
|
||||
|
||||
J[部署脚本] --> K[Docker容器]
|
||||
K --> D
|
||||
|
||||
L[开发流程] --> M[新迁移脚本]
|
||||
M --> C
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
1. **Flyway Core**: 数据库迁移引擎
|
||||
2. **Migration Scripts**: 版本化的SQL迁移脚本
|
||||
3. **Baseline Migration**: 基于现有SQL文件的初始化脚本
|
||||
4. **Configuration Management**: Spring Boot集成配置
|
||||
5. **Deployment Integration**: 部署流程集成
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### 1. Flyway配置组件
|
||||
|
||||
#### Maven依赖配置
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-database-postgresql</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
#### Spring Boot配置
|
||||
```yaml
|
||||
spring:
|
||||
flyway:
|
||||
enabled: true
|
||||
locations: classpath:db/migration
|
||||
baseline-on-migrate: true
|
||||
baseline-version: 1.0.0
|
||||
baseline-description: "Initial baseline from existing database"
|
||||
validate-on-migrate: true
|
||||
clean-disabled: true
|
||||
out-of-order: false
|
||||
```
|
||||
|
||||
### 2. 迁移脚本组件
|
||||
|
||||
#### 目录结构
|
||||
```
|
||||
src/main/resources/
|
||||
└── db/
|
||||
└── migration/
|
||||
├── V1.0.0__Initial_baseline.sql
|
||||
├── V1.0.1__Add_traffic_light_tables.sql
|
||||
├── V1.0.2__Add_vehicle_filter_config.sql
|
||||
└── V1.0.3__Update_geofence_schema.sql
|
||||
```
|
||||
|
||||
#### 脚本命名规范
|
||||
- 格式: `V{version}__{description}.sql`
|
||||
- 版本号: 语义化版本控制 (major.minor.patch)
|
||||
- 描述: 英文下划线分隔,简洁明了
|
||||
|
||||
### 3. 基线脚本生成组件
|
||||
|
||||
#### SQL文件分析器
|
||||
```java
|
||||
public class SqlFileAnalyzer {
|
||||
public List<SqlScript> analyzeSqlFiles(Path sqlDirectory);
|
||||
public SqlScript mergeScripts(List<SqlScript> scripts);
|
||||
public void generateBaselineScript(SqlScript mergedScript, Path outputPath);
|
||||
}
|
||||
```
|
||||
|
||||
#### 脚本合并策略
|
||||
1. **表结构优先**: 先创建所有表结构
|
||||
2. **索引和约束**: 然后添加索引和外键约束
|
||||
3. **初始数据**: 最后插入基础数据
|
||||
4. **去重处理**: 移除重复的CREATE语句
|
||||
|
||||
### 4. 部署集成组件
|
||||
|
||||
#### Docker启动脚本修改
|
||||
```bash
|
||||
# 在应用启动前等待数据库就绪
|
||||
wait_for_database() {
|
||||
until pg_isready -h qaup-postgres -p 5432 -U qaup; do
|
||||
echo "等待数据库启动..."
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
|
||||
# 应用启动时自动执行Flyway迁移
|
||||
start_application() {
|
||||
wait_for_database
|
||||
java -jar /app/app.jar --spring.config.location=/app/config.yml
|
||||
}
|
||||
```
|
||||
|
||||
## Data Models
|
||||
|
||||
### 1. Flyway元数据表
|
||||
|
||||
Flyway会自动创建 `flyway_schema_history` 表来跟踪迁移历史:
|
||||
|
||||
```sql
|
||||
CREATE TABLE flyway_schema_history (
|
||||
installed_rank INTEGER NOT NULL,
|
||||
version VARCHAR(50),
|
||||
description VARCHAR(200) NOT NULL,
|
||||
type VARCHAR(20) NOT NULL,
|
||||
script VARCHAR(1000) NOT NULL,
|
||||
checksum INTEGER,
|
||||
installed_by VARCHAR(100) NOT NULL,
|
||||
installed_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
execution_time INTEGER NOT NULL,
|
||||
success BOOLEAN NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
### 2. 迁移脚本数据模型
|
||||
|
||||
```java
|
||||
public class MigrationScript {
|
||||
private String version;
|
||||
private String description;
|
||||
private String content;
|
||||
private LocalDateTime createdAt;
|
||||
private String author;
|
||||
private List<String> dependencies;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 基线数据模型
|
||||
|
||||
基于现有SQL文件分析,基线脚本将包含:
|
||||
|
||||
- **系统核心表**: sys_user, sys_role, sys_dept等RuoYi框架表
|
||||
- **业务表**: sys_vehicle_info, sys_driver_info, sys_vehicle_type等
|
||||
- **空间数据表**: vehicle_location, airport_area等PostGIS表
|
||||
- **配置表**: sys_config及其初始数据
|
||||
- **索引和约束**: 所有必要的数据库索引和外键约束
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 1. 迁移失败处理
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class FlywayMigrationHandler {
|
||||
|
||||
@EventListener
|
||||
public void handleMigrationFailure(FlywayMigrationFailureEvent event) {
|
||||
log.error("数据库迁移失败: {}", event.getException().getMessage());
|
||||
// 发送告警通知
|
||||
alertService.sendMigrationFailureAlert(event);
|
||||
// 记录详细错误信息
|
||||
errorLogService.logMigrationError(event);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleMigrationSuccess(FlywayMigrationSuccessEvent event) {
|
||||
log.info("数据库迁移成功完成,当前版本: {}", event.getTargetVersion());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 版本冲突处理
|
||||
|
||||
- **检测机制**: 启动时检查是否有版本冲突
|
||||
- **解决策略**:
|
||||
- 开发环境: 允许out-of-order迁移
|
||||
- 生产环境: 严格按版本顺序执行
|
||||
- **回滚机制**: 提供手动回滚工具和脚本
|
||||
|
||||
### 3. 数据完整性保护
|
||||
|
||||
```sql
|
||||
-- 在迁移脚本中添加数据验证
|
||||
DO $$
|
||||
BEGIN
|
||||
-- 验证关键数据完整性
|
||||
IF NOT EXISTS (SELECT 1 FROM sys_config WHERE config_key = 'sys.user.initPassword') THEN
|
||||
RAISE EXCEPTION '关键配置数据缺失,迁移中止';
|
||||
END IF;
|
||||
END $$;
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### 1. 迁移脚本测试
|
||||
|
||||
#### 单元测试
|
||||
```java
|
||||
@SpringBootTest
|
||||
@Testcontainers
|
||||
class FlywayMigrationTest {
|
||||
|
||||
@Container
|
||||
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgis/postgis:17-3.5-alpine")
|
||||
.withDatabaseName("qaup_test")
|
||||
.withUsername("test")
|
||||
.withPassword("test");
|
||||
|
||||
@Test
|
||||
void testBaselineMigration() {
|
||||
// 测试基线迁移脚本
|
||||
Flyway flyway = Flyway.configure()
|
||||
.dataSource(postgres.getJdbcUrl(), postgres.getUsername(), postgres.getPassword())
|
||||
.locations("classpath:db/migration")
|
||||
.load();
|
||||
|
||||
MigrateResult result = flyway.migrate();
|
||||
assertThat(result.migrationsExecuted).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIncrementalMigration() {
|
||||
// 测试增量迁移
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 集成测试
|
||||
```java
|
||||
@SpringBootTest
|
||||
@TestPropertySource(properties = {
|
||||
"spring.flyway.locations=classpath:db/migration,classpath:db/testdata"
|
||||
})
|
||||
class DatabaseIntegrationTest {
|
||||
|
||||
@Test
|
||||
void testDatabaseSchemaAfterMigration() {
|
||||
// 验证迁移后的数据库结构
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDataIntegrityAfterMigration() {
|
||||
// 验证数据完整性
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 性能测试
|
||||
|
||||
#### 迁移性能测试
|
||||
- **大数据量测试**: 模拟生产环境数据量
|
||||
- **并发测试**: 测试多实例启动时的迁移行为
|
||||
- **回滚性能**: 测试回滚操作的性能
|
||||
|
||||
#### 监控指标
|
||||
```java
|
||||
@Component
|
||||
public class FlywayMetrics {
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public void recordMigrationTime(String version, Duration duration) {
|
||||
Timer.Sample sample = Timer.start(meterRegistry);
|
||||
sample.stop(Timer.builder("flyway.migration.duration")
|
||||
.tag("version", version)
|
||||
.register(meterRegistry));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 环境测试
|
||||
|
||||
#### 多环境验证
|
||||
- **开发环境**: 频繁迁移测试
|
||||
- **测试环境**: 完整迁移流程验证
|
||||
- **预生产环境**: 生产数据迁移模拟
|
||||
- **生产环境**: 蓝绿部署迁移测试
|
||||
|
||||
#### Docker环境测试
|
||||
```yaml
|
||||
# docker-compose.test.yml
|
||||
services:
|
||||
qaup-postgres-test:
|
||||
image: postgis/postgis:17-3.5-alpine
|
||||
environment:
|
||||
POSTGRES_DB: qaup_test
|
||||
POSTGRES_USER: test
|
||||
POSTGRES_PASSWORD: test
|
||||
volumes:
|
||||
- ./test-data:/docker-entrypoint-initdb.d
|
||||
```
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: 基础设施搭建
|
||||
1. 添加Flyway依赖和配置
|
||||
2. 创建迁移脚本目录结构
|
||||
3. 开发SQL文件分析和合并工具
|
||||
|
||||
### Phase 2: 基线迁移创建
|
||||
1. 分析现有SQL文件依赖关系
|
||||
2. 生成统一的基线迁移脚本
|
||||
3. 验证基线脚本的完整性和正确性
|
||||
|
||||
### Phase 3: 部署集成
|
||||
1. 修改Docker配置支持Flyway
|
||||
2. 更新部署脚本
|
||||
3. 创建数据库初始化流程
|
||||
|
||||
### Phase 4: 开发流程规范
|
||||
1. 制定迁移脚本开发规范
|
||||
2. 创建代码审查检查清单
|
||||
3. 建立版本管理流程
|
||||
|
||||
### Phase 5: 监控和维护
|
||||
1. 实现迁移状态监控
|
||||
2. 创建故障排除工具
|
||||
3. 建立备份和回滚机制
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### 1. 权限控制
|
||||
- Flyway执行用户权限最小化
|
||||
- 生产环境禁用clean操作
|
||||
- 迁移脚本访问权限控制
|
||||
|
||||
### 2. 数据保护
|
||||
- 敏感数据迁移加密
|
||||
- 备份策略集成
|
||||
- 审计日志记录
|
||||
|
||||
### 3. 环境隔离
|
||||
- 不同环境使用不同的迁移配置
|
||||
- 生产环境额外的安全检查
|
||||
- 迁移脚本签名验证
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### 1. 迁移性能优化
|
||||
- 批量操作优化
|
||||
- 索引创建策略
|
||||
- 大表迁移分批处理
|
||||
|
||||
### 2. 启动性能优化
|
||||
- 并行迁移支持
|
||||
- 增量检查优化
|
||||
- 缓存机制集成
|
||||
|
||||
### 3. 资源使用优化
|
||||
- 内存使用控制
|
||||
- 连接池配置优化
|
||||
- 临时空间管理
|
||||
@ -1,62 +0,0 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
本功能旨在为QAUP项目集成Flyway数据库迁移工具,实现数据库版本控制和自动化迁移管理。通过整理现有的SQL文件形成Flyway初始化版本,并修改部署脚本以支持自动化数据库迁移,提高数据库管理的规范性和可维护性。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1
|
||||
|
||||
**User Story:** 作为开发人员,我希望使用Flyway管理数据库迁移,以便能够版本化控制数据库结构变更并确保环境间的一致性。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 项目启动时 THEN 系统 SHALL 自动执行Flyway数据库迁移
|
||||
2. WHEN 有新的数据库变更时 THEN 开发人员 SHALL 能够创建新的迁移脚本
|
||||
3. WHEN 部署到不同环境时 THEN Flyway SHALL 确保数据库结构的一致性
|
||||
4. IF 迁移失败 THEN 系统 SHALL 提供详细的错误信息并停止启动
|
||||
|
||||
### Requirement 2
|
||||
|
||||
**User Story:** 作为运维人员,我希望现有的SQL文件能够整理成Flyway标准格式,以便能够基于当前数据库状态进行版本化管理。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 整理现有SQL文件时 THEN 系统 SHALL 将所有建表语句合并为基线迁移脚本
|
||||
2. WHEN 创建基线版本时 THEN 脚本 SHALL 包含所有必要的表结构、索引和初始数据
|
||||
3. WHEN 处理重复或冲突的SQL时 THEN 系统 SHALL 去重并保持数据完整性
|
||||
4. WHEN 生成迁移文件时 THEN 文件命名 SHALL 遵循Flyway标准格式 (V{version}__{description}.sql)
|
||||
|
||||
### Requirement 3
|
||||
|
||||
**User Story:** 作为部署管理员,我希望部署脚本能够自动处理数据库迁移,以便简化部署流程并减少人工错误。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 执行部署脚本时 THEN 脚本 SHALL 在应用启动前执行数据库迁移
|
||||
2. WHEN 数据库迁移完成时 THEN 系统 SHALL 记录迁移历史和版本信息
|
||||
3. IF 迁移过程中出现错误 THEN 部署 SHALL 停止并提供回滚选项
|
||||
4. WHEN 在Docker环境中部署时 THEN 容器启动 SHALL 包含自动迁移流程
|
||||
|
||||
### Requirement 4
|
||||
|
||||
**User Story:** 作为开发团队成员,我希望有清晰的数据库迁移规范和流程,以便团队能够统一管理数据库变更。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 需要修改数据库结构时 THEN 开发人员 SHALL 创建新的迁移脚本而不是直接修改现有文件
|
||||
2. WHEN 迁移脚本创建后 THEN 脚本 SHALL 包含向前和向后兼容性考虑
|
||||
3. WHEN 多个开发人员同时进行数据库变更时 THEN 版本号管理 SHALL 避免冲突
|
||||
4. WHEN 迁移脚本提交时 THEN 代码审查 SHALL 包含数据库变更的验证
|
||||
|
||||
### Requirement 5
|
||||
|
||||
**User Story:** 作为系统管理员,我希望能够监控和管理数据库迁移状态,以便及时发现和解决迁移相关问题。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN 查询迁移状态时 THEN 系统 SHALL 提供当前数据库版本和迁移历史
|
||||
2. WHEN 迁移失败时 THEN 系统 SHALL 记录详细的错误日志
|
||||
3. WHEN 需要手动干预时 THEN 管理员 SHALL 能够查看和修复迁移状态
|
||||
4. WHEN 在生产环境中 THEN 迁移过程 SHALL 支持备份和回滚机制
|
||||
@ -1,73 +0,0 @@
|
||||
# Implementation Plan
|
||||
|
||||
- [x] 1. 添加Flyway依赖和基础配置
|
||||
- 在根pom.xml中添加Flyway相关依赖
|
||||
- 在qaup-admin模块的application.yml中配置Flyway参数
|
||||
- 创建db/migration目录结构
|
||||
- _Requirements: 1.1, 1.2_
|
||||
|
||||
- [x] 2. 从生产数据库导出基线结构
|
||||
- 使用pg_dump导出生产数据库的完整表结构
|
||||
- 导出基础配置数据和字典数据
|
||||
- 清理导出脚本中的环境特定信息
|
||||
- 验证导出脚本的完整性和可执行性
|
||||
- _Requirements: 2.1, 2.2, 2.3_
|
||||
|
||||
- [x] 3. 生成Flyway基线迁移脚本
|
||||
- 将导出的数据库结构整理为V1.0.0__Initial_baseline.sql
|
||||
- 添加必要的PostGIS扩展和空间索引
|
||||
- 包含系统必需的初始数据和配置
|
||||
- 验证基线脚本在全新数据库中的执行效果
|
||||
- _Requirements: 2.1, 2.2, 2.3, 2.4_
|
||||
|
||||
- [x] 4. 创建增量迁移脚本
|
||||
- 将现有的增量SQL文件转换为Flyway格式
|
||||
- 创建V1.0.1__Add_traffic_light_tables.sql等增量脚本
|
||||
- 确保所有脚本遵循Flyway命名规范
|
||||
- 添加必要的数据验证和错误处理
|
||||
- _Requirements: 2.4, 4.1, 4.2_
|
||||
|
||||
- [x] 5. 集成Flyway到Spring Boot应用
|
||||
- 配置Flyway在应用启动时自动执行
|
||||
- 实现FlywayMigrationHandler处理迁移事件
|
||||
- 添加迁移状态监控和日志记录
|
||||
- 创建迁移失败的告警机制
|
||||
- _Requirements: 1.1, 1.3, 5.1, 5.2_
|
||||
|
||||
- [x] 6. 修改Docker部署配置
|
||||
- 更新docker-compose.yml支持Flyway迁移
|
||||
- 修改应用启动脚本等待数据库就绪
|
||||
- 移除现有的init.sql初始化方式
|
||||
- 确保容器启动时自动执行数据库迁移
|
||||
- _Requirements: 3.1, 3.4_
|
||||
|
||||
- [x] 7. 更新部署脚本和流程
|
||||
- 修改deploy.sh脚本集成Flyway迁移检查
|
||||
- 更新BUILD-GUIDE.md文档说明新的部署流程
|
||||
- 创建数据库迁移状态检查工具
|
||||
- 实现迁移失败时的回滚机制
|
||||
- _Requirements: 3.1, 3.2, 3.3_
|
||||
|
||||
- [x] 8. 简单测试验证迁移功能
|
||||
- 在本地环境测试基线迁移脚本执行
|
||||
- 验证迁移后数据库结构的完整性
|
||||
- 测试应用启动时的自动迁移流程
|
||||
- _Requirements: 1.4, 2.3, 3.3_
|
||||
|
||||
- [x] 9. 创建开发规范和文档
|
||||
- 编写数据库迁移开发规范文档
|
||||
- 创建迁移脚本模板和示例
|
||||
- 制定版本号管理流程
|
||||
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||
|
||||
- [x] 10. 配置生产环境安全措施
|
||||
- 配置生产环境禁用Flyway clean操作
|
||||
- 添加迁移前的数据库备份机制
|
||||
- 设置迁移失败时的告警通知
|
||||
- _Requirements: 5.4, 3.3_
|
||||
|
||||
- [x] 11. 最终验证和部署
|
||||
- 在测试环境验证完整的迁移流程
|
||||
- 更新部署文档和操作手册
|
||||
- 进行生产环境迁移演练
|
||||
- _Requirements: 1.3, 1.4, 3.1, 3.2_
|
||||
@ -1,464 +0,0 @@
|
||||
# 设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
红绿灯信号集成功能为QAUP机场管理系统提供实时路口状态监控能力。该功能通过TCP服务器监听外部红绿灯硬件发送的状态信号,解析DI格式的原始数据,转换为系统内部的标准化消息格式,并通过WebSocket实时广播给前端客户端。
|
||||
|
||||
该设计遵循现有系统的架构模式,集成到现有的数据采集和WebSocket通信框架中,确保与其他系统组件的一致性和兼容性。
|
||||
|
||||
## 架构
|
||||
|
||||
### 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A[红绿灯硬件] -->|TCP连接<br/>端口8082| B[TrafficLightTcpServer]
|
||||
B --> C[TrafficLightDataCollector]
|
||||
C --> D[DataProcessingService]
|
||||
D --> E[TrafficLightSignalParser]
|
||||
E --> F[TrafficLightStatusEvent]
|
||||
F --> G[WebSocketMessageBroadcaster]
|
||||
G -->|WebSocket| H[前端客户端]
|
||||
|
||||
I[Spring配置] --> B
|
||||
J[应用配置文件] --> I
|
||||
|
||||
subgraph "datacollector模块"
|
||||
B
|
||||
C
|
||||
end
|
||||
|
||||
subgraph "dataprocessing模块"
|
||||
D
|
||||
E
|
||||
F
|
||||
end
|
||||
|
||||
subgraph "现有系统组件"
|
||||
G
|
||||
K[UniversalMessage]
|
||||
L[TrafficLightStatusPayload]
|
||||
end
|
||||
|
||||
F --> K
|
||||
F --> L
|
||||
```
|
||||
|
||||
### 数据流程
|
||||
|
||||
1. **信号接收**: TCP服务器(datacollector模块)监听8082端口,接收红绿灯硬件发送的JSON格式信号
|
||||
2. **数据采集**: TrafficLightDataCollector收集原始信号数据,传递给数据处理服务
|
||||
3. **数据处理**: DataProcessingService(dataprocessing模块)调用信号解析器处理数据
|
||||
4. **信号解析**: TrafficLightSignalParser将DI格式的原始信号转换为标准化的红绿灯状态
|
||||
5. **事件发布**: 数据处理服务通过Spring事件机制发布红绿灯状态变更事件
|
||||
6. **WebSocket广播**: 事件监听器将状态更新广播给所有连接的前端客户端
|
||||
|
||||
## 组件和接口
|
||||
|
||||
### 1. TrafficLightTcpServer (datacollector模块)
|
||||
|
||||
**职责**: TCP服务器,负责监听和接收红绿灯硬件信号
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Component
|
||||
public class TrafficLightTcpServer {
|
||||
// 启动TCP服务器
|
||||
public void startServer();
|
||||
|
||||
// 停止TCP服务器
|
||||
public void stopServer();
|
||||
|
||||
// 处理客户端连接
|
||||
private void handleClientConnection(Socket clientSocket);
|
||||
|
||||
// 获取服务器状态
|
||||
public ServerStatus getServerStatus();
|
||||
}
|
||||
```
|
||||
|
||||
**配置属性**:
|
||||
- `traffic.light.tcp.port`: TCP监听端口(默认8082)
|
||||
- `traffic.light.tcp.enabled`: 是否启用TCP服务器(默认true)
|
||||
- `traffic.light.tcp.max-connections`: 最大连接数(默认10)
|
||||
|
||||
### 2. TrafficLightDataCollector (datacollector模块)
|
||||
|
||||
**职责**: 集成到现有数据采集框架,收集红绿灯原始数据并传递给数据处理服务
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Service
|
||||
public class TrafficLightDataCollector {
|
||||
// 处理TCP服务器接收到的原始信号
|
||||
public void collectTrafficLightSignal(String rawJsonSignal);
|
||||
|
||||
// 获取采集统计信息
|
||||
public CollectionStatistics getStatistics();
|
||||
}
|
||||
```
|
||||
|
||||
### 3. TrafficLightSignalParser (dataprocessing模块)
|
||||
|
||||
**职责**: 解析DI格式的红绿灯信号,转换为内部状态枚举
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Component
|
||||
public class TrafficLightSignalParser {
|
||||
// 解析原始JSON信号
|
||||
public TrafficLightStatus parseSignal(String rawJsonSignal);
|
||||
|
||||
// 验证信号格式
|
||||
public boolean isValidSignal(String rawJsonSignal);
|
||||
|
||||
// 获取解析统计信息
|
||||
public ParseStatistics getStatistics();
|
||||
}
|
||||
```
|
||||
|
||||
**信号状态枚举**:
|
||||
```java
|
||||
public enum SignalState {
|
||||
RED("red"),
|
||||
YELLOW("yellow"),
|
||||
GREEN("green"),
|
||||
UNKNOWN("unknown");
|
||||
}
|
||||
|
||||
public class TrafficLightStatus {
|
||||
private String deviceId; // 红绿灯设备编号
|
||||
private String intersectionId; // 关联的路口编号
|
||||
private SignalState nsStatus; // 南北方向状态
|
||||
private SignalState ewStatus; // 东西方向状态
|
||||
private long timestamp; // 信号时间戳
|
||||
private String rawSignal; // 原始信号数据(用于调试)
|
||||
}
|
||||
```
|
||||
|
||||
### 6. IntersectionService (新增服务)
|
||||
|
||||
**职责**: 管理路口信息,提供路口数据的CRUD操作
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Service
|
||||
public class IntersectionService {
|
||||
// 根据路口编号获取路口信息
|
||||
public Intersection getIntersectionById(String intersectionId);
|
||||
|
||||
// 获取所有激活的路口
|
||||
public List<Intersection> getAllActiveIntersections();
|
||||
|
||||
// 添加新路口
|
||||
public void addIntersection(Intersection intersection);
|
||||
|
||||
// 更新路口信息
|
||||
public void updateIntersection(Intersection intersection);
|
||||
}
|
||||
```
|
||||
|
||||
### 7. TrafficLightService (新增服务)
|
||||
|
||||
**职责**: 管理红绿灯设备信息,提供设备数据的CRUD操作
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Service
|
||||
public class TrafficLightService {
|
||||
// 根据设备编号获取红绿灯信息
|
||||
public TrafficLight getTrafficLightByDeviceId(String deviceId);
|
||||
|
||||
// 根据路口编号获取红绿灯设备
|
||||
public List<TrafficLight> getTrafficLightsByIntersection(String intersectionId);
|
||||
|
||||
// 更新设备在线状态
|
||||
public void updateDeviceOnlineStatus(String deviceId, boolean isOnline);
|
||||
|
||||
// 更新设备心跳时间
|
||||
public void updateDeviceHeartbeat(String deviceId);
|
||||
}
|
||||
```
|
||||
|
||||
**实体类**:
|
||||
```java
|
||||
@Entity
|
||||
@Table(name = "intersections")
|
||||
public class Intersection {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "intersection_id", unique = true, nullable = false)
|
||||
private String intersectionId;
|
||||
|
||||
@Column(name = "intersection_name", nullable = false)
|
||||
private String intersectionName;
|
||||
|
||||
@Column(name = "latitude", nullable = false)
|
||||
private Double latitude;
|
||||
|
||||
@Column(name = "longitude", nullable = false)
|
||||
private Double longitude;
|
||||
|
||||
@Column(name = "area_code")
|
||||
private String areaCode;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "is_active")
|
||||
private Boolean isActive = true;
|
||||
|
||||
// getters and setters...
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "traffic_lights")
|
||||
public class TrafficLight {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "device_id", unique = true, nullable = false)
|
||||
private String deviceId;
|
||||
|
||||
@Column(name = "device_name", nullable = false)
|
||||
private String deviceName;
|
||||
|
||||
@Column(name = "intersection_id", nullable = false)
|
||||
private String intersectionId;
|
||||
|
||||
@Column(name = "device_type")
|
||||
private String deviceType = "STANDARD";
|
||||
|
||||
@Column(name = "manufacturer")
|
||||
private String manufacturer;
|
||||
|
||||
@Column(name = "model")
|
||||
private String model;
|
||||
|
||||
@Column(name = "install_date")
|
||||
private LocalDate installDate;
|
||||
|
||||
@Column(name = "is_online")
|
||||
private Boolean isOnline = false;
|
||||
|
||||
@Column(name = "last_heartbeat")
|
||||
private LocalDateTime lastHeartbeat;
|
||||
|
||||
@Column(name = "is_active")
|
||||
private Boolean isActive = true;
|
||||
|
||||
// getters and setters...
|
||||
}
|
||||
```
|
||||
|
||||
### 4. DataProcessingService扩展 (dataprocessing模块)
|
||||
|
||||
**职责**: 在现有数据处理服务中添加红绿灯数据处理逻辑
|
||||
|
||||
**接口扩展**:
|
||||
```java
|
||||
@Service
|
||||
public class DataProcessingService {
|
||||
// 现有方法...
|
||||
|
||||
// 新增:处理红绿灯信号数据
|
||||
public void processTrafficLightSignal(String rawJsonSignal);
|
||||
|
||||
// 创建WebSocket消息载荷(包含路口位置信息)
|
||||
private TrafficLightStatusPayload createTrafficLightPayload(
|
||||
TrafficLightStatus status,
|
||||
TrafficLight device,
|
||||
Intersection intersection
|
||||
);
|
||||
|
||||
// 发布状态变更事件
|
||||
private void publishTrafficLightStatusEvent(TrafficLightStatusPayload payload);
|
||||
|
||||
// 验证设备是否存在和在线
|
||||
private boolean isValidTrafficLightDevice(String deviceId);
|
||||
|
||||
// 更新设备心跳和在线状态
|
||||
private void updateDeviceStatus(String deviceId);
|
||||
}
|
||||
```
|
||||
|
||||
### 5. TrafficLightStatusEventListener (websocket模块)
|
||||
|
||||
**职责**: 监听红绿灯状态事件,通过WebSocket广播更新
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Component
|
||||
public class TrafficLightStatusEventListener {
|
||||
// 处理红绿灯状态事件
|
||||
@EventListener
|
||||
public void handleTrafficLightStatusEvent(TrafficLightStatusEvent event);
|
||||
|
||||
// 广播WebSocket消息
|
||||
private void broadcastStatusUpdate(TrafficLightStatusPayload payload);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 原始信号格式
|
||||
```json
|
||||
{
|
||||
"device_id": "TL_001", // 红绿灯设备编号(新增)
|
||||
"DI-01": 0,
|
||||
"DI-02": 0,
|
||||
"DI-11": 1, // 北红
|
||||
"DI-12": 0, // 北黄
|
||||
"DI-13": 0, // 北绿
|
||||
"DI-14": 0, // 东红
|
||||
"DI-15": 0, // 东黄
|
||||
"DI-16": 1, // 东绿
|
||||
"DI-17": 0,
|
||||
"DI-18": 0
|
||||
}
|
||||
```
|
||||
|
||||
### 内部状态模型
|
||||
```java
|
||||
public class TrafficLightStatus {
|
||||
private SignalState nsStatus; // 南北方向状态
|
||||
private SignalState ewStatus; // 东西方向状态
|
||||
private long timestamp; // 微秒级时间戳
|
||||
private String intersectionId; // 路口标识符
|
||||
}
|
||||
```
|
||||
|
||||
### WebSocket消息格式
|
||||
```json
|
||||
{
|
||||
"type": "intersection_traffic_light_status",
|
||||
"timestamp": 1704067200000000,
|
||||
"payload": {
|
||||
"intersection_id": "INTERSECTION_001",
|
||||
"intersection_name": "主要路口1号",
|
||||
"device_id": "TL_001",
|
||||
"device_name": "主路口红绿灯1号",
|
||||
"position": {
|
||||
"latitude": 39.9042,
|
||||
"longitude": 116.4074
|
||||
},
|
||||
"ns_status": "red",
|
||||
"ew_status": "green",
|
||||
"timestamp": 1704067200000000,
|
||||
"area_code": "AREA_A"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 1. 网络错误处理
|
||||
- **连接断开**: 记录日志,等待客户端重新连接
|
||||
- **端口占用**: 尝试备用端口,记录错误信息
|
||||
- **网络超时**: 设置合理的超时时间,自动重试机制
|
||||
|
||||
### 2. 数据解析错误处理
|
||||
- **JSON格式错误**: 记录原始数据,跳过当前消息
|
||||
- **DI字段缺失**: 使用默认安全状态(红灯)
|
||||
- **无效状态值**: 映射到UNKNOWN状态,记录警告
|
||||
|
||||
### 3. 系统错误处理
|
||||
- **内存不足**: 限制连接数,清理过期数据
|
||||
- **线程池满**: 使用队列缓冲,记录性能指标
|
||||
- **WebSocket断开**: 继续处理信号,不影响数据采集
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 1. 单元测试
|
||||
- **信号解析器测试**: 验证各种DI组合的解析结果
|
||||
- **状态转换测试**: 验证信号状态到枚举的映射
|
||||
- **错误处理测试**: 验证异常情况的处理逻辑
|
||||
|
||||
### 2. 集成测试
|
||||
- **TCP服务器测试**: 模拟红绿灯硬件连接和数据发送
|
||||
- **WebSocket广播测试**: 验证消息格式和广播功能
|
||||
- **端到端测试**: 从信号接收到前端显示的完整流程
|
||||
|
||||
### 3. 性能测试
|
||||
- **高频信号测试**: 验证每秒多次信号的处理能力
|
||||
- **并发连接测试**: 验证多个硬件设备同时连接
|
||||
- **长时间运行测试**: 验证系统稳定性和内存泄漏
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 应用配置文件 (application.yml)
|
||||
```yaml
|
||||
traffic:
|
||||
light:
|
||||
tcp:
|
||||
enabled: true
|
||||
port: 8082
|
||||
max-connections: 50 # 支持更多路口连接
|
||||
connection-timeout: 30000
|
||||
processing:
|
||||
enable-statistics: true
|
||||
statistics-interval: 60000
|
||||
default-intersection:
|
||||
latitude: 0.0 # 默认坐标,实际坐标从数据库获取
|
||||
longitude: 0.0
|
||||
```
|
||||
|
||||
### 数据库表设计
|
||||
|
||||
#### 路口信息表 (intersections)
|
||||
```sql
|
||||
CREATE TABLE intersections (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
intersection_id VARCHAR(50) UNIQUE NOT NULL, -- 路口编号
|
||||
intersection_name VARCHAR(100) NOT NULL, -- 路口名称
|
||||
latitude DECIMAL(10, 8) NOT NULL, -- 纬度
|
||||
longitude DECIMAL(11, 8) NOT NULL, -- 经度
|
||||
area_code VARCHAR(20), -- 区域编码
|
||||
description TEXT, -- 路口描述
|
||||
is_active BOOLEAN DEFAULT true, -- 是否激活
|
||||
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX idx_intersection_id ON intersections(intersection_id);
|
||||
CREATE INDEX idx_area_code ON intersections(area_code);
|
||||
```
|
||||
|
||||
#### 红绿灯设备表 (traffic_lights)
|
||||
```sql
|
||||
CREATE TABLE traffic_lights (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
device_id VARCHAR(50) UNIQUE NOT NULL, -- 红绿灯设备编号
|
||||
device_name VARCHAR(100) NOT NULL, -- 设备名称
|
||||
intersection_id VARCHAR(50) NOT NULL, -- 关联的路口编号
|
||||
device_type VARCHAR(20) DEFAULT 'STANDARD', -- 设备类型
|
||||
manufacturer VARCHAR(50), -- 制造商
|
||||
model VARCHAR(50), -- 型号
|
||||
install_date DATE, -- 安装日期
|
||||
is_online BOOLEAN DEFAULT false, -- 是否在线
|
||||
last_heartbeat TIMESTAMP, -- 最后心跳时间
|
||||
is_active BOOLEAN DEFAULT true, -- 是否激活
|
||||
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- 外键约束
|
||||
CONSTRAINT fk_traffic_light_intersection
|
||||
FOREIGN KEY (intersection_id)
|
||||
REFERENCES intersections(intersection_id)
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX idx_traffic_light_device_id ON traffic_lights(device_id);
|
||||
CREATE INDEX idx_traffic_light_intersection ON traffic_lights(intersection_id);
|
||||
CREATE INDEX idx_traffic_light_online ON traffic_lights(is_online);
|
||||
```
|
||||
|
||||
### 日志配置
|
||||
- **信号接收日志**: DEBUG级别,记录原始信号数据
|
||||
- **解析错误日志**: WARN级别,记录解析失败的信号
|
||||
- **系统状态日志**: INFO级别,定期记录处理统计信息
|
||||
- **网络错误日志**: ERROR级别,记录连接和网络问题
|
||||
@ -1,71 +0,0 @@
|
||||
# 需求文档
|
||||
|
||||
## 介绍
|
||||
|
||||
本功能为QAUP机场管理系统实现红绿灯信号接入。系统需要监听来自外部硬件的红绿灯状态信号,解析原始信号数据,转换为内部消息格式,并通过WebSocket向前端客户端广播状态更新。红绿灯信号提供实时路口状态信息,对机场交通管理和碰撞避免至关重要。
|
||||
|
||||
## 需求
|
||||
|
||||
### 需求 1
|
||||
|
||||
**用户故事:** 作为交通控制操作员,我希望系统能够自动接收来自外部硬件的红绿灯信号,以便我能够实时监控路口状态而无需手动干预。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当系统启动时,系统应在8082端口建立TCP服务器监听器
|
||||
2. 当红绿灯硬件发送状态信号时,系统应接收并捕获原始JSON数据
|
||||
3. 当TCP服务器接收到格式错误的数据时,系统应记录错误并继续监听
|
||||
4. 当TCP连接遇到网络错误时,系统应自动处理连接断开并等待重新连接
|
||||
5. 当系统关闭时,TCP服务器应优雅地关闭所有连接
|
||||
|
||||
### 需求 2
|
||||
|
||||
**用户故事:** 作为系统管理员,我希望红绿灯信号解析器能够将原始硬件信号转换为标准化的内部格式,以便数据能够被其他系统组件一致地处理。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当系统接收到原始红绿灯JSON数据时,系统应正确解析DI信号格式
|
||||
2. 当解析DI-11到DI-13信号时,系统应将它们映射到南北方向状态(红/黄/绿)
|
||||
3. 当解析DI-14到DI-16信号时,系统应将它们映射到东西方向状态(红/黄/绿)
|
||||
4. 当多个方向信号同时激活时,系统应确定正确的信号状态优先级
|
||||
5. 当原始数据包含无效DI值时,系统应使用默认安全状态(两个方向都为红灯)
|
||||
6. 当由于JSON格式错误导致解析失败时,系统应记录错误并跳过该消息
|
||||
|
||||
### 需求 3
|
||||
|
||||
**用户故事:** 作为前端开发人员,我希望红绿灯状态更新通过WebSocket以标准UniversalMessage格式广播,以便UI能够与其他系统消息一致地显示实时路口状态。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当红绿灯状态改变时,系统应创建包含路口详细信息的TrafficLightStatusPayload
|
||||
2. 当发布红绿灯更新时,系统应使用"intersection_traffic_light_status"消息类型
|
||||
3. 当通过WebSocket广播时,系统应包含微秒级时间戳
|
||||
4. 当未配置路口位置时,系统应使用默认坐标(0.0, 0.0)
|
||||
5. 当WebSocket客户端连接时,它们应立即接收红绿灯状态更新
|
||||
6. 当没有WebSocket客户端连接时,系统应继续处理信号而不出错
|
||||
|
||||
### 需求 4
|
||||
|
||||
**用户故事:** 作为系统操作员,我希望红绿灯集成是可配置和可监控的,以便我能够调整设置和排除故障而无需更改代码。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当系统启动时,系统应从应用程序属性中读取红绿灯配置
|
||||
2. 当配置中禁用红绿灯集成时,UDP监听器不应启动
|
||||
3. 当系统处理红绿灯信号时,系统应定期记录处理统计信息
|
||||
4. 当信号处理错误发生时,系统应增加错误计数器并记录详细信息
|
||||
5. 当未配置路口ID时,系统应使用默认路口标识符
|
||||
6. 当TCP端口配置不同时,系统应使用配置的端口而不是8082
|
||||
|
||||
### 需求 5
|
||||
|
||||
**用户故事:** 作为质量保证工程师,我希望红绿灯集成能够优雅地处理边缘情况和错误条件,以便系统在生产环境中保持稳定和可靠。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当TCP端口已被占用时,系统应记录错误并尝试替代端口
|
||||
2. 当红绿灯信号接收频率超过1秒间隔时,系统应处理所有信号而不丢失数据
|
||||
3. 当重复接收相同信号状态时,系统仍应广播更新以保持客户端同步
|
||||
4. 当系统内存不足时,红绿灯处理应以最小内存占用继续运行
|
||||
5. 当网络接口不可用时,系统应定期重试连接
|
||||
6. 当提供无效路口坐标时,系统应验证并使用安全默认值
|
||||
@ -1,87 +0,0 @@
|
||||
# 实现计划
|
||||
|
||||
- [x] 1. 创建数据库表和实体类
|
||||
- 创建路口信息表(intersections)和红绿灯设备表(traffic_lights)的SQL脚本
|
||||
- 实现Intersection和TrafficLight实体类,包含JPA注解
|
||||
- 创建对应的Repository接口,继承JpaRepository
|
||||
- _需求: 1.1, 4.5, 4.6_
|
||||
|
||||
- [x] 2. 实现红绿灯信号解析器
|
||||
- 创建SignalState枚举类,定义红绿灯状态(RED/YELLOW/GREEN/UNKNOWN)
|
||||
- 实现TrafficLightStatus数据模型类,包含设备ID、路口ID、状态等字段
|
||||
- 实现TrafficLightSignalParser类,解析DI格式JSON信号为内部状态
|
||||
- 编写信号解析的单元测试,覆盖正常和异常情况
|
||||
- _需求: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6_
|
||||
|
||||
- [x] 3. 实现路口和设备管理服务
|
||||
- 创建IntersectionService类,提供路口信息的CRUD操作
|
||||
- 创建TrafficLightService类,提供红绿灯设备的管理功能
|
||||
- 实现设备在线状态和心跳时间的更新方法
|
||||
- 编写服务层的单元测试
|
||||
- _需求: 4.1, 4.5, 5.5_
|
||||
|
||||
- [x] 4. 实现TCP服务器监听红绿灯信号
|
||||
- 创建TrafficLightTcpServer类,使用Java NIO实现TCP服务器
|
||||
- 实现多客户端连接处理,支持并发连接
|
||||
- 添加连接管理功能,包括连接建立、断开和重连处理
|
||||
- 集成Spring配置,支持端口、最大连接数等参数配置
|
||||
- 编写TCP服务器的集成测试
|
||||
- _需求: 1.1, 1.2, 1.4, 1.5, 4.2, 4.6, 5.1_
|
||||
|
||||
- [x] 5. 实现数据采集器集成TCP服务器
|
||||
- 创建TrafficLightDataCollector类,集成到现有数据采集框架
|
||||
- 实现TCP服务器接收到信号后的数据传递机制
|
||||
- 添加数据采集统计功能,记录接收信号数量和错误次数
|
||||
- 集成到DataCollectorService的定时任务中
|
||||
- _需求: 1.2, 1.3, 4.3, 4.4_
|
||||
|
||||
- [x] 6. 扩展数据处理服务处理红绿灯信号
|
||||
- 在DataProcessingService中添加processTrafficLightSignal方法
|
||||
- 实现设备验证逻辑,检查设备是否存在和激活
|
||||
- 实现路口信息查询,获取位置坐标等信息
|
||||
- 创建TrafficLightStatusPayload,包含完整的路口和设备信息
|
||||
- 更新设备心跳时间和在线状态
|
||||
- _需求: 2.1, 2.4, 2.5, 5.4, 5.6_
|
||||
|
||||
- [x] 7. 实现WebSocket事件发布和广播
|
||||
- 扩展现有TrafficLightStatusEvent,支持新的数据结构
|
||||
- 在数据处理服务中发布红绿灯状态变更事件
|
||||
- 创建或更新TrafficLightStatusEventListener,处理事件广播
|
||||
- 确保WebSocket消息格式符合前端要求
|
||||
- _需求: 3.1, 3.2, 3.3, 3.5, 3.6_
|
||||
|
||||
- [x] 8. 添加配置管理和错误处理
|
||||
- 在application.yml中添加红绿灯相关配置项
|
||||
- 实现配置类TrafficLightProperties,绑定配置属性
|
||||
- 添加全局异常处理,处理TCP连接、解析错误等异常
|
||||
- 实现优雅关闭机制,确保TCP服务器正确关闭
|
||||
- _需求: 4.1, 4.2, 4.3, 4.4, 5.1, 5.2, 5.3_
|
||||
|
||||
- [x] 9. 实现数据库初始化和管理接口
|
||||
- 创建数据库迁移脚本,初始化路口和设备表
|
||||
- 实现路口管理的REST API,支持路口信息的增删改查
|
||||
- 实现设备管理的REST API,支持设备信息的管理
|
||||
- 添加数据验证和约束检查
|
||||
- _需求: 4.5, 4.6, 5.6_
|
||||
|
||||
- [x] 10. 编写集成测试和端到端测试
|
||||
- 创建模拟红绿灯硬件的测试客户端
|
||||
- 编写TCP服务器到WebSocket广播的端到端测试
|
||||
- 测试多设备并发连接和信号处理
|
||||
- 测试异常情况处理,如网络断开、格式错误等
|
||||
- 验证性能指标,确保满足每秒信号处理要求
|
||||
- _需求: 1.3, 1.4, 2.6, 5.1, 5.2, 5.3, 5.4_
|
||||
|
||||
- [x] 11. 添加监控和日志记录
|
||||
- 实现处理统计功能,记录信号接收和处理数量
|
||||
- 添加性能监控,记录处理延迟和错误率
|
||||
- 配置日志级别,确保调试和生产环境的日志合理
|
||||
- 实现健康检查接口,监控TCP服务器和处理服务状态
|
||||
- _需求: 4.3, 4.4, 5.4_
|
||||
|
||||
- [x] 12. 系统集成和部署准备
|
||||
- 将所有组件集成到现有Spring Boot应用中
|
||||
- 更新Docker配置,确保TCP端口正确暴露
|
||||
- 编写部署文档,说明配置和启动步骤
|
||||
- 进行系统级测试,验证与现有功能的兼容性
|
||||
- _需求: 1.5, 4.1, 4.2_
|
||||
@ -1,382 +0,0 @@
|
||||
# 设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
红绿灯IP地址增强功能旨在改进现有的红绿灯信号处理系统,使其能够正确解析包含IP地址和端口信息的红绿灯消息格式,并相应地调整数据库结构以支持更灵活的设备管理。
|
||||
|
||||
根据实际的红绿灯消息格式:`('36.113.38.178', 56930) - {"DI-01":0,"DI-02":0,"DI-11":1,...}`,系统需要修改信号解析器以提取网络地址信息,并更新数据库表结构使设备ID字段变为可选。
|
||||
|
||||
## 架构
|
||||
|
||||
### 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A[红绿灯硬件] -->|TCP消息<br/>格式: ('IP', port) - {DI数据}| B[TrafficLightTcpServer]
|
||||
B --> C[TrafficLightDataCollector]
|
||||
C --> D[DataProcessingService]
|
||||
D --> E[TrafficLightSignalParser - 增强版]
|
||||
E --> F[TrafficLightStatus - 包含IP/端口]
|
||||
F --> G[TrafficLightService - 支持IP查找]
|
||||
G --> H[数据库 - 更新表结构]
|
||||
F --> I[WebSocketMessageBroadcaster]
|
||||
I -->|WebSocket| J[前端客户端]
|
||||
|
||||
subgraph "修改的组件"
|
||||
E
|
||||
F
|
||||
G
|
||||
H
|
||||
end
|
||||
|
||||
subgraph "现有组件(无需修改)"
|
||||
B
|
||||
C
|
||||
D
|
||||
I
|
||||
end
|
||||
```
|
||||
|
||||
### 数据流程
|
||||
|
||||
1. **消息接收**: TCP服务器接收格式为`('IP', port) - {DI数据}`的红绿灯消息
|
||||
2. **消息解析**: 增强的信号解析器提取IP地址、端口号和DI信号数据
|
||||
3. **设备识别**: 系统使用IP地址和端口信息识别或创建设备记录
|
||||
4. **数据处理**: 处理DI信号并更新设备状态
|
||||
5. **状态广播**: 通过WebSocket广播红绿灯状态更新
|
||||
|
||||
## 组件和接口
|
||||
|
||||
### 1. TrafficLightSignalParser (增强版)
|
||||
|
||||
**职责**: 解析包含IP地址和端口信息的红绿灯消息格式
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Component
|
||||
public class TrafficLightSignalParser {
|
||||
// 解析包含IP和端口信息的原始消息
|
||||
public TrafficLightStatus parseSignalWithAddress(String rawMessage);
|
||||
|
||||
// 提取IP地址信息
|
||||
private String extractIpAddress(String rawMessage);
|
||||
|
||||
// 提取端口信息
|
||||
private Integer extractPort(String rawMessage);
|
||||
|
||||
// 提取DI信号数据
|
||||
private String extractDiData(String rawMessage);
|
||||
|
||||
// 验证消息格式
|
||||
public boolean isValidMessageFormat(String rawMessage);
|
||||
}
|
||||
```
|
||||
|
||||
**消息格式解析逻辑**:
|
||||
```java
|
||||
// 输入格式: ('36.113.38.178', 56930) - {"DI-01":0,"DI-02":0,"DI-11":1,...}
|
||||
// 解析步骤:
|
||||
// 1. 使用正则表达式匹配 ('IP', port) 部分
|
||||
// 2. 提取IP地址字符串
|
||||
// 3. 提取端口号整数
|
||||
// 4. 提取 - 后面的JSON数据部分
|
||||
// 5. 解析DI信号数据
|
||||
```
|
||||
|
||||
### 2. TrafficLightStatus (增强版)
|
||||
|
||||
**职责**: 包含IP地址和端口信息的红绿灯状态数据模型
|
||||
|
||||
**数据模型**:
|
||||
```java
|
||||
public class TrafficLightStatus {
|
||||
private String ipAddress; // 设备IP地址
|
||||
private Integer port; // 设备端口号
|
||||
private String deviceId; // 设备ID(可选)
|
||||
private String intersectionId; // 路口ID
|
||||
private SignalState nsStatus; // 南北方向状态
|
||||
private SignalState ewStatus; // 东西方向状态
|
||||
private long timestamp; // 信号时间戳
|
||||
private String rawSignal; // 原始信号数据
|
||||
|
||||
// 生成设备唯一标识符(当deviceId为空时使用)
|
||||
public String generateDeviceIdentifier() {
|
||||
return ipAddress + ":" + port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. TrafficLight实体类 (修改版)
|
||||
|
||||
**职责**: 支持IP地址和端口信息存储的设备实体
|
||||
|
||||
**实体设计**:
|
||||
```java
|
||||
@Entity
|
||||
@Table(name = "traffic_lights")
|
||||
public class TrafficLight {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id; // 主键ID
|
||||
|
||||
@Column(name = "device_id") // 设备ID改为可选
|
||||
private String deviceId;
|
||||
|
||||
@Column(name = "ip_address", nullable = false) // 新增:IP地址字段
|
||||
private String ipAddress;
|
||||
|
||||
@Column(name = "port") // 新增:端口字段
|
||||
private Integer port;
|
||||
|
||||
@Column(name = "device_name", nullable = false)
|
||||
private String deviceName;
|
||||
|
||||
@Column(name = "intersection_id", nullable = false)
|
||||
private String intersectionId;
|
||||
|
||||
@Column(name = "device_type")
|
||||
private String deviceType = "STANDARD";
|
||||
|
||||
@Column(name = "is_online")
|
||||
private Boolean isOnline = false;
|
||||
|
||||
@Column(name = "last_heartbeat")
|
||||
private LocalDateTime lastHeartbeat;
|
||||
|
||||
@Column(name = "is_active")
|
||||
private Boolean isActive = true;
|
||||
|
||||
@Column(name = "created_time")
|
||||
private LocalDateTime createdTime;
|
||||
|
||||
@Column(name = "updated_time")
|
||||
private LocalDateTime updatedTime;
|
||||
|
||||
// 添加唯一约束:IP地址和端口组合必须唯一
|
||||
// 在数据库层面通过复合唯一索引实现
|
||||
}
|
||||
```
|
||||
|
||||
### 4. TrafficLightRepository (增强版)
|
||||
|
||||
**职责**: 支持基于IP地址和端口查询的数据访问层
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Repository
|
||||
public interface TrafficLightRepository extends JpaRepository<TrafficLight, Long> {
|
||||
// 现有方法...
|
||||
|
||||
// 根据IP地址和端口查找设备
|
||||
Optional<TrafficLight> findByIpAddressAndPort(String ipAddress, Integer port);
|
||||
|
||||
// 根据IP地址查找设备列表
|
||||
List<TrafficLight> findByIpAddress(String ipAddress);
|
||||
|
||||
// 根据设备ID查找(保持兼容性)
|
||||
Optional<TrafficLight> findByDeviceId(String deviceId);
|
||||
|
||||
// 检查IP地址和端口组合是否已存在
|
||||
boolean existsByIpAddressAndPort(String ipAddress, Integer port);
|
||||
}
|
||||
```
|
||||
|
||||
### 5. TrafficLightService (增强版)
|
||||
|
||||
**职责**: 支持基于IP地址的设备管理服务
|
||||
|
||||
**接口设计**:
|
||||
```java
|
||||
@Service
|
||||
public class TrafficLightService {
|
||||
// 现有方法...
|
||||
|
||||
// 根据IP地址和端口获取或创建设备
|
||||
public TrafficLight getOrCreateDeviceByAddress(String ipAddress, Integer port, String intersectionId);
|
||||
|
||||
// 根据IP地址和端口查找设备
|
||||
public Optional<TrafficLight> findDeviceByAddress(String ipAddress, Integer port);
|
||||
|
||||
// 更新设备心跳(基于IP地址和端口)
|
||||
public void updateDeviceHeartbeatByAddress(String ipAddress, Integer port);
|
||||
|
||||
// 生成默认设备名称
|
||||
private String generateDefaultDeviceName(String ipAddress, Integer port) {
|
||||
return "TrafficLight_" + ipAddress.replace(".", "_") + "_" + port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. DataProcessingService (修改版)
|
||||
|
||||
**职责**: 处理包含IP地址信息的红绿灯信号
|
||||
|
||||
**接口修改**:
|
||||
```java
|
||||
@Service
|
||||
public class DataProcessingService {
|
||||
// 现有方法...
|
||||
|
||||
// 修改:处理包含IP地址信息的红绿灯信号
|
||||
public void processTrafficLightSignal(String rawMessage) {
|
||||
try {
|
||||
// 使用增强的解析器解析消息
|
||||
TrafficLightStatus status = trafficLightSignalParser.parseSignalWithAddress(rawMessage);
|
||||
|
||||
// 根据IP地址和端口获取或创建设备
|
||||
TrafficLight device = trafficLightService.getOrCreateDeviceByAddress(
|
||||
status.getIpAddress(),
|
||||
status.getPort(),
|
||||
status.getIntersectionId()
|
||||
);
|
||||
|
||||
// 更新设备心跳
|
||||
trafficLightService.updateDeviceHeartbeatByAddress(
|
||||
status.getIpAddress(),
|
||||
status.getPort()
|
||||
);
|
||||
|
||||
// 创建WebSocket消息载荷
|
||||
TrafficLightStatusPayload payload = createTrafficLightPayload(status, device);
|
||||
|
||||
// 发布状态变更事件
|
||||
publishTrafficLightStatusEvent(payload);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理红绿灯信号失败: {}", rawMessage, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 原始消息格式
|
||||
```
|
||||
输入: ('36.113.38.178', 56930) - {"DI-01":0,"DI-02":0,"DI-11":1,"DI-12":0,"DI-13":0,"DI-14":0,"DI-15":0,"DI-16":1,"DI-17":0,"DI-18":0}
|
||||
|
||||
解析结果:
|
||||
- IP地址: "36.113.38.178"
|
||||
- 端口: 56930
|
||||
- DI数据: {"DI-01":0,"DI-02":0,"DI-11":1,"DI-12":0,"DI-13":0,"DI-14":0,"DI-15":0,"DI-16":1,"DI-17":0,"DI-18":0}
|
||||
```
|
||||
|
||||
### 数据库表结构变更
|
||||
|
||||
#### 修改traffic_lights表
|
||||
```sql
|
||||
-- 添加新字段
|
||||
ALTER TABLE traffic_lights
|
||||
ADD COLUMN ip_address VARCHAR(45) NOT NULL DEFAULT '0.0.0.0',
|
||||
ADD COLUMN port INTEGER;
|
||||
|
||||
-- 修改device_id字段为可选
|
||||
ALTER TABLE traffic_lights
|
||||
ALTER COLUMN device_id DROP NOT NULL;
|
||||
|
||||
-- 添加唯一约束:IP地址和端口组合必须唯一
|
||||
CREATE UNIQUE INDEX idx_traffic_light_ip_port
|
||||
ON traffic_lights(ip_address, port);
|
||||
|
||||
-- 添加IP地址索引
|
||||
CREATE INDEX idx_traffic_light_ip
|
||||
ON traffic_lights(ip_address);
|
||||
```
|
||||
|
||||
### WebSocket消息格式 (保持不变)
|
||||
```json
|
||||
{
|
||||
"type": "intersection_traffic_light_status",
|
||||
"timestamp": 1704067200000000,
|
||||
"payload": {
|
||||
"intersection_id": "INTERSECTION_001",
|
||||
"device_id": "36.113.38.178:56930", // 当设备ID为空时使用IP:端口
|
||||
"ip_address": "36.113.38.178", // 新增字段
|
||||
"port": 56930, // 新增字段
|
||||
"position": {
|
||||
"latitude": 39.9042,
|
||||
"longitude": 116.4074
|
||||
},
|
||||
"ns_status": "red",
|
||||
"ew_status": "green",
|
||||
"timestamp": 1704067200000000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 1. 消息格式解析错误
|
||||
- **格式不匹配**: 当消息不符合`('IP', port) - {JSON}`格式时,记录错误并跳过
|
||||
- **IP地址无效**: 验证IP地址格式,无效时使用默认值并记录警告
|
||||
- **端口号无效**: 验证端口号范围,无效时使用默认值
|
||||
- **JSON解析失败**: 记录原始数据,跳过当前消息
|
||||
|
||||
### 2. 数据库操作错误
|
||||
- **IP端口重复**: 当IP地址和端口组合已存在时,更新现有记录而不是创建新记录
|
||||
- **约束违反**: 处理数据库约束违反,提供清晰的错误信息
|
||||
- **连接失败**: 数据库连接失败时,缓存数据并重试
|
||||
|
||||
### 3. 设备管理错误
|
||||
- **设备创建失败**: 记录错误详情,使用临时标识符继续处理
|
||||
- **心跳更新失败**: 记录警告,不影响信号处理流程
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 1. 单元测试
|
||||
- **消息解析测试**: 测试各种消息格式的解析结果
|
||||
- **IP地址提取测试**: 验证IP地址和端口的正确提取
|
||||
- **设备查找测试**: 测试基于IP地址和端口的设备查找功能
|
||||
|
||||
### 2. 集成测试
|
||||
- **数据库迁移测试**: 验证表结构变更的正确性
|
||||
- **端到端测试**: 从消息接收到WebSocket广播的完整流程测试
|
||||
- **错误处理测试**: 测试各种异常情况的处理
|
||||
|
||||
### 3. 兼容性测试
|
||||
- **现有数据兼容性**: 确保现有设备记录在升级后仍能正常工作
|
||||
- **API兼容性**: 验证现有API调用不受影响
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 应用配置文件 (application.yml)
|
||||
```yaml
|
||||
traffic:
|
||||
light:
|
||||
parsing:
|
||||
# 消息格式配置
|
||||
message-format-regex: "\\('([^']+)',\\s*(\\d+)\\)\\s*-\\s*(\\{.*\\})"
|
||||
default-ip: "0.0.0.0"
|
||||
default-port: 8082
|
||||
|
||||
device:
|
||||
# 设备管理配置
|
||||
auto-create-device: true
|
||||
default-intersection-id: "DEFAULT_INTERSECTION"
|
||||
device-name-prefix: "TrafficLight_"
|
||||
```
|
||||
|
||||
### 数据库迁移脚本
|
||||
```sql
|
||||
-- V1.1__add_ip_port_to_traffic_lights.sql
|
||||
-- 添加IP地址和端口字段
|
||||
ALTER TABLE traffic_lights
|
||||
ADD COLUMN ip_address VARCHAR(45) NOT NULL DEFAULT '0.0.0.0',
|
||||
ADD COLUMN port INTEGER;
|
||||
|
||||
-- 修改device_id为可选
|
||||
ALTER TABLE traffic_lights
|
||||
ALTER COLUMN device_id DROP NOT NULL;
|
||||
|
||||
-- 为现有记录设置默认IP地址
|
||||
UPDATE traffic_lights
|
||||
SET ip_address = '0.0.0.0', port = 8082
|
||||
WHERE ip_address IS NULL;
|
||||
|
||||
-- 添加唯一约束和索引
|
||||
CREATE UNIQUE INDEX idx_traffic_light_ip_port
|
||||
ON traffic_lights(ip_address, port);
|
||||
|
||||
CREATE INDEX idx_traffic_light_ip
|
||||
ON traffic_lights(ip_address);
|
||||
```
|
||||
@ -1,33 +0,0 @@
|
||||
# 需求文档
|
||||
|
||||
## 介绍
|
||||
|
||||
本功能为现有的QAUP红绿灯集成系统修改消息解析逻辑,以正确处理包含IP地址和端口信息的红绿灯消息格式。根据实际的红绿灯消息格式,系统需要从TCP连接中识别设备的IP地址和端口信息,并修改设备表结构使设备ID字段变为可选,以便更灵活地管理红绿灯设备。
|
||||
|
||||
## 需求
|
||||
|
||||
### 需求 1
|
||||
|
||||
**用户故事:** 作为系统管理员,我希望红绿灯信号解析器能够从接收到的数据包中识别IP地址和端口信息,以便系统能够准确识别每个红绿灯设备的来源。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当系统接收到红绿灯数据包时,系统应从数据包格式中解析出IP地址信息
|
||||
2. 当系统接收到红绿灯数据包时,系统应从数据包格式中解析出端口号信息
|
||||
3. 当解析红绿灯信号时,系统应将解析出的IP地址和端口信息与DI信号数据一起处理
|
||||
4. 当数据包格式为`('IP地址', 端口号) - {DI数据}`时,系统应正确提取IP和端口信息
|
||||
5. 当记录信号处理日志时,系统应包含设备的IP地址和端口信息用于调试
|
||||
6. 当无法从数据包中解析出网络地址信息时,系统应记录警告但继续处理DI信号数据
|
||||
|
||||
### 需求 2
|
||||
|
||||
**用户故事:** 作为数据库管理员,我希望红绿灯设备表能够存储IP地址和端口信息,并且设备ID字段变为可选,以便系统能够基于网络地址管理设备。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. 当修改设备表结构时,系统应添加IP地址字段用于存储设备IP
|
||||
2. 当修改设备表结构时,系统应添加端口字段用于存储设备端口
|
||||
3. 当修改设备表结构时,系统应将设备ID字段改为可选(允许NULL)
|
||||
4. 当查询设备信息时,系统应支持通过IP地址和端口组合进行查找
|
||||
5. 当IP地址和端口组合重复时,系统应防止创建重复的设备记录
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
# 实现计划
|
||||
|
||||
- [x] 1. 修改数据库表结构
|
||||
- 创建数据库迁移脚本,为traffic_lights表添加ip_address和port字段
|
||||
- 修改device_id字段为可选(允许NULL)
|
||||
- 添加IP地址和端口组合的唯一约束索引
|
||||
- 为现有记录设置默认IP地址和端口值
|
||||
- _需求: 2.1, 2.2, 2.3, 2.5_
|
||||
|
||||
- [x] 2. 更新TrafficLight实体类
|
||||
- 在TrafficLight实体类中添加ipAddress和port字段
|
||||
- 修改deviceId字段的JPA注解,移除nullable=false约束
|
||||
- 添加IP地址和端口字段的验证注解
|
||||
- 更新构造函数和getter/setter方法
|
||||
- _需求: 2.1, 2.2, 2.3_
|
||||
|
||||
- [x] 3. 增强TrafficLightRepository接口
|
||||
- 添加findByIpAddressAndPort方法,支持基于IP和端口查询设备
|
||||
- 添加findByIpAddress方法,支持基于IP地址查询设备列表
|
||||
- 添加existsByIpAddressAndPort方法,检查IP端口组合是否存在
|
||||
- 保持现有的findByDeviceId方法以维持兼容性
|
||||
- _需求: 2.4, 2.5_
|
||||
|
||||
- [x] 4. 修改TrafficLightSignalParser解析器
|
||||
- 实现parseSignalWithAddress方法,解析包含IP和端口信息的消息格式
|
||||
- 添加extractIpAddress方法,使用正则表达式提取IP地址
|
||||
- 添加extractPort方法,提取端口号并转换为整数
|
||||
- 添加extractDiData方法,提取DI信号JSON数据部分
|
||||
- 更新isValidSignal方法,验证新的消息格式
|
||||
- _需求: 1.1, 1.2, 1.3, 1.4, 1.6_
|
||||
|
||||
- [x] 5. 更新TrafficLightStatus数据模型
|
||||
- 在TrafficLightStatus类中添加ipAddress和port字段
|
||||
- 添加generateDeviceIdentifier方法,当deviceId为空时生成IP:端口标识符
|
||||
- 更新构造函数和相关方法
|
||||
- 确保与现有代码的兼容性
|
||||
- _需求: 1.3, 1.5_
|
||||
|
||||
- [x] 6. 增强TrafficLightService服务类
|
||||
- 实现getOrCreateDeviceByAddress方法,根据IP和端口获取或创建设备
|
||||
- 实现findDeviceByAddress方法,根据IP和端口查找设备
|
||||
- 实现updateDeviceHeartbeatByAddress方法,基于IP和端口更新心跳
|
||||
- 添加generateDefaultDeviceName方法,生成默认设备名称
|
||||
- _需求: 2.4, 2.5_
|
||||
|
||||
- [x] 7. 修改DataProcessingService处理逻辑
|
||||
- 更新processTrafficLightSignal方法,使用增强的解析器处理消息
|
||||
- 修改设备查找逻辑,优先使用IP地址和端口进行设备匹配
|
||||
- 更新设备心跳更新逻辑,基于IP地址和端口进行更新
|
||||
- 添加异常处理,确保解析失败时不影响系统稳定性
|
||||
- _需求: 1.3, 1.5, 1.6_
|
||||
|
||||
- [x] 8. 编写单元测试
|
||||
- 为TrafficLightSignalParser编写消息解析测试,覆盖各种消息格式
|
||||
- 为TrafficLightService编写设备管理测试,测试基于IP地址的操作
|
||||
- 为TrafficLightRepository编写数据访问测试
|
||||
- 测试异常情况处理,如格式错误、IP地址无效等
|
||||
- _需求: 1.4, 1.6, 2.5_
|
||||
|
||||
- [x] 9. 执行数据库迁移和测试
|
||||
- 在开发环境执行数据库迁移脚本
|
||||
- 验证现有数据的兼容性和完整性
|
||||
- 测试新的唯一约束是否正确工作
|
||||
- 验证索引创建和查询性能
|
||||
- _需求: 2.1, 2.2, 2.3, 2.5_
|
||||
|
||||
- [x] 10. 集成测试和验证
|
||||
- 使用实际的红绿灯消息格式进行端到端测试
|
||||
- 验证IP地址和端口信息的正确提取和存储
|
||||
- 测试设备自动创建和更新功能
|
||||
- 验证WebSocket消息中包含正确的IP地址和端口信息
|
||||
- _需求: 1.1, 1.2, 1.3, 1.4, 1.5, 2.4_
|
||||
@ -1,142 +0,0 @@
|
||||
# 机场车辆位置过滤功能设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
本设计文档描述了如何在现有的机场车辆位置数据处理流程中添加过滤功能,通过系统配置控制是否转发未注册车辆的位置信息。
|
||||
|
||||
## 架构
|
||||
|
||||
### 整体架构
|
||||
```
|
||||
机场API -> DataCollectorService -> 车辆过滤器 -> 缓存/前端转发
|
||||
↓
|
||||
sys_vehicle_info表查询
|
||||
↓
|
||||
系统配置(ISysConfigService)
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
1. **VehicleLocationFilter**: 新增的车辆位置过滤器
|
||||
2. **DataCollectorService**: 修改现有的数据采集服务,集成过滤逻辑
|
||||
3. **ISysConfigService**: 利用现有的系统配置服务
|
||||
4. **ISysVehicleInfoService**: 利用现有的车辆信息服务
|
||||
|
||||
## 组件和接口
|
||||
|
||||
### 1. VehicleLocationFilter (新增)
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class VehicleLocationFilter {
|
||||
|
||||
private static final String CONFIG_KEY = "unmanaged.vehicle.filter.enabled";
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private ISysVehicleInfoService vehicleInfoService;
|
||||
|
||||
/**
|
||||
* 过滤机场车辆位置数据
|
||||
* @param vehicles 原始车辆列表
|
||||
* @return 过滤后的车辆列表
|
||||
*/
|
||||
public List<AirportVehicle> filterVehicles(List<AirportVehicle> vehicles);
|
||||
|
||||
/**
|
||||
* 检查过滤功能是否启用
|
||||
* @return true表示启用过滤
|
||||
*/
|
||||
private boolean isFilterEnabled();
|
||||
|
||||
/**
|
||||
* 批量检查车辆是否在数据库中存在
|
||||
* @param plateNumbers 车牌号列表
|
||||
* @return 存在的车牌号集合
|
||||
*/
|
||||
private Set<String> getExistingVehiclePlates(List<String> plateNumbers);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. DataCollectorService (修改)
|
||||
|
||||
在现有的 `collectVehicleData()` 方法中集成过滤逻辑:
|
||||
|
||||
```java
|
||||
@Scheduled(fixedRateString = "${data.collector.interval}")
|
||||
@Async
|
||||
public void collectVehicleData() {
|
||||
// ... 现有代码 ...
|
||||
|
||||
List<AirportVehicle> vehicles = dataCollectorDao.collectVehicleData(airportVehicleEndpoint, airportBaseUrl);
|
||||
|
||||
// 新增:应用过滤器
|
||||
List<AirportVehicle> filteredVehicles = vehicleLocationFilter.filterVehicles(vehicles);
|
||||
|
||||
// 继续处理过滤后的车辆数据
|
||||
for (AirportVehicle vehicle : filteredVehicles) {
|
||||
// ... 现有处理逻辑 ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 系统配置
|
||||
|
||||
在 `sys_config` 表中添加配置项:
|
||||
- config_key: `unmanaged.vehicle.filter.enabled`
|
||||
- config_value: `false` (默认值,不过滤)
|
||||
- config_name: `未管理车辆位置过滤开关`
|
||||
- config_type: `Y` (系统内置)
|
||||
|
||||
## 数据模型
|
||||
|
||||
### 配置项数据结构
|
||||
```sql
|
||||
INSERT INTO sys_config (config_name, config_key, config_value, config_type, remark)
|
||||
VALUES ('未管理车辆位置过滤开关', 'unmanaged.vehicle.filter.enabled', 'false', 'Y', '控制是否过滤未在sys_vehicle_info表中注册的车辆位置信息');
|
||||
```
|
||||
|
||||
### 车辆信息查询
|
||||
利用现有的 `sys_vehicle_info` 表结构,通过 `license_plate` 字段进行匹配。
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 异常处理策略
|
||||
1. **配置读取失败**: 默认不过滤,记录警告日志
|
||||
2. **数据库查询失败**: 默认不过滤,记录错误日志
|
||||
3. **车辆数据异常**: 跳过异常数据,继续处理其他车辆
|
||||
|
||||
### 日志记录
|
||||
- DEBUG级别: 记录过滤统计信息
|
||||
- WARN级别: 记录配置读取失败
|
||||
- ERROR级别: 记录数据库查询异常
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
1. **VehicleLocationFilter测试**
|
||||
- 测试过滤功能启用/禁用
|
||||
- 测试车辆存在性检查
|
||||
- 测试异常处理
|
||||
|
||||
2. **DataCollectorService集成测试**
|
||||
- 测试过滤器集成
|
||||
- 测试数据流完整性
|
||||
|
||||
### 集成测试
|
||||
1. 测试配置修改后的实时生效
|
||||
2. 测试大量车辆数据的过滤性能
|
||||
3. 测试数据库连接异常时的降级处理
|
||||
|
||||
## 性能考虑
|
||||
|
||||
### 优化策略
|
||||
1. **批量查询**: 一次查询所有车牌号,避免N+1问题
|
||||
2. **配置缓存**: 利用现有的系统配置缓存机制
|
||||
3. **快速失败**: 配置禁用时直接跳过所有过滤逻辑
|
||||
|
||||
### 性能指标
|
||||
- 单批次车辆过滤处理时间 < 50ms (100辆车以内)
|
||||
- 数据库查询次数: 每批次最多1次
|
||||
- 内存占用: 忽略不计 (仅临时存储车牌号列表)
|
||||
@ -1,35 +0,0 @@
|
||||
# 机场车辆位置过滤功能需求文档
|
||||
|
||||
## 介绍
|
||||
|
||||
为机场车辆位置 API 添加一个配置开关,控制是否将不在数据库车辆信息表(sys_vehicle_info)中的车辆位置信息转发给前端。
|
||||
|
||||
## 需求
|
||||
|
||||
### 需求 1
|
||||
|
||||
**用户故事:** 作为系统管理员,我希望能够配置是否过滤未注册车辆的位置信息,以便控制前端显示的车辆数据量。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. WHEN 系统配置中存在"unmanaged.vehicle.filter.enabled"配置项 THEN 系统 SHALL 根据该配置决定是否过滤车辆
|
||||
2. WHEN 配置为"true" THEN 系统 SHALL 只转发在 sys_vehicle_info 表中存在的车辆位置信息
|
||||
3. WHEN 配置为"false" THEN 系统 SHALL 转发所有接收到的机场车辆位置信息
|
||||
|
||||
### 需求 2
|
||||
|
||||
**用户故事:** 作为系统用户,我希望过滤功能不影响系统的实时性能。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. WHEN 过滤功能启用 THEN 系统 SHALL 使用车牌号批量查询车辆信息以提高效率
|
||||
2. WHEN 过滤功能禁用 THEN 系统 SHALL 跳过过滤逻辑,直接处理数据
|
||||
|
||||
### 需求 3
|
||||
|
||||
**用户故事:** 作为系统管理员,我希望能够通过现有的系统配置 API 查询和修改过滤配置。
|
||||
|
||||
#### 验收标准
|
||||
|
||||
1. WHEN 调用系统配置查询 API THEN 系统 SHALL 返回"unmanaged.vehicle.filter.enabled"配置项的值
|
||||
2. WHEN 调用系统配置修改 API THEN 系统 SHALL 允许修改该配置项的值
|
||||
@ -1,24 +0,0 @@
|
||||
# 实现计划
|
||||
|
||||
- [x] 1. 创建车辆位置过滤器组件
|
||||
- 创建 VehicleLocationFilter 类,实现车辆过滤逻辑
|
||||
- 添加配置读取和车辆存在性检查方法
|
||||
- 实现批量车牌号查询优化
|
||||
- _需求: 1.1, 1.2, 2.1_
|
||||
|
||||
- [x] 2. 修改数据采集服务集成过滤器
|
||||
- 在 DataCollectorService 中注入 VehicleLocationFilter
|
||||
- 修改 collectVehicleData 方法,在处理前应用过滤器
|
||||
- 添加过滤统计日志记录
|
||||
- _需求: 1.2, 1.3, 2.2_
|
||||
|
||||
- [x] 3. 添加系统配置项
|
||||
- 在数据库中插入未管理车辆位置过滤开关配置项
|
||||
- 验证配置项可以通过现有的系统配置 API 查询和修改
|
||||
- _需求: 3.1, 3.2_
|
||||
|
||||
- [x] 4. 编写单元测试
|
||||
- 为 VehicleLocationFilter 编写单元测试
|
||||
- 测试过滤功能启用/禁用场景
|
||||
- 测试异常处理和降级逻辑
|
||||
- _需求: 1.1, 1.2, 1.3_
|
||||
1
.serena/.gitignore
vendored
1
.serena/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/cache
|
||||
@ -1,35 +0,0 @@
|
||||
# QAUP-Management Architecture Patterns
|
||||
|
||||
## Critical Design Principle: Data Collection vs Processing Separation
|
||||
|
||||
### DataCollectorService (250ms interval)
|
||||
- **ONLY** collects raw position data from external APIs
|
||||
- Caches data in activeMovingObjectsCache with NULL speed/direction
|
||||
- **FORBIDDEN**: No calculations, no WebSocket events, no processing
|
||||
- Purpose: High-frequency data collection to ensure no data loss
|
||||
|
||||
### DataProcessingService (1000ms interval)
|
||||
- Reads cached position data from DataCollectorService
|
||||
- Calculates speed and direction using SpeedCalculationService
|
||||
- Sends WebSocket position updates
|
||||
- Performs violation detection and path conflict detection
|
||||
- Saves data to database
|
||||
|
||||
### Cache Sharing Pattern
|
||||
- DataCollectorService owns activeMovingObjectsCache
|
||||
- DataProcessingService receives cache reference via setActiveMovingObjectsCache()
|
||||
- Both services share the same cache instance but have different responsibilities
|
||||
|
||||
## Key Integration Pattern
|
||||
The collision avoidance system integrates with RuoYi through `QuapDataAdapter` (qaup-collision/src/main/java/com/qaup/collision/common/adapter/QuapDataAdapter.java:37), which bridges the collision detection system with RuoYi's service layer, avoiding direct DAO dependencies.
|
||||
|
||||
## Data Access Pattern
|
||||
Always use `QuapDataAdapter` for accessing vehicle and driver data in collision module instead of direct service calls. This maintains clean separation between collision detection and system management.
|
||||
|
||||
## WebSocket Communication
|
||||
Real-time data flows through WebSocket endpoints configured in collision module. Messages use `/topic` prefix for broadcasting to connected clients.
|
||||
|
||||
## Performance Optimization
|
||||
- Data collection interval: 250ms for high-frequency updates
|
||||
- WebSocket push throttling: 1000ms to prevent frontend overload
|
||||
- Redis caching with 60-second expiration for real-time data
|
||||
@ -1,34 +0,0 @@
|
||||
# QAUP-Management Project Overview
|
||||
|
||||
## Purpose
|
||||
QAUP-Management is an airport collision avoidance and management system built on the RuoYi framework. It integrates vehicle tracking, spatial analysis, and real-time monitoring for airport operations.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
### Backend
|
||||
- **Spring Boot 3.5.3** with Java 17
|
||||
- **PostgreSQL + PostGIS** for spatial data
|
||||
- **MyBatis** for database operations
|
||||
- **Redis** for caching and session management
|
||||
- **WebSocket** for real-time communication
|
||||
- **JTS + GeoTools** for spatial calculations
|
||||
- **RuoYi Framework** as base framework
|
||||
|
||||
### Frontend
|
||||
- **Vue 2.6.12** with Element UI
|
||||
- **Axios** for API communication
|
||||
- **ECharts** for data visualization
|
||||
|
||||
## Multi-Module Maven Architecture
|
||||
- **qaup-admin**: Main web application entry point containing controllers and startup configuration
|
||||
- **qaup-collision**: Core collision avoidance system with spatial analysis, WebSocket communication, and real-time monitoring
|
||||
- **qaup-framework**: Infrastructure layer with security, caching, and common configurations
|
||||
- **qaup-system**: User management, RBAC, and system administration
|
||||
- **qaup-common**: Shared utilities, constants, and base classes
|
||||
- **qaup-quartz**: Scheduled job management
|
||||
- **qaup-generator**: Code generation utilities
|
||||
|
||||
## Key URLs
|
||||
- **Admin Interface**: http://localhost:8080
|
||||
- **API Documentation**: http://localhost:8080/swagger-ui/index.html
|
||||
- **WebSocket Endpoint**: ws://localhost:8080/ws
|
||||
@ -1,63 +0,0 @@
|
||||
# Suggested Commands for QAUP-Management Development
|
||||
|
||||
## Build and Run Commands
|
||||
|
||||
### Maven Build
|
||||
```bash
|
||||
# Full clean build (skip tests for faster builds)
|
||||
mvn clean install -DskipTests
|
||||
|
||||
# Check dependencies
|
||||
mvn dependency:tree
|
||||
```
|
||||
|
||||
### Backend Development
|
||||
```bash
|
||||
# Start backend from qaup-admin module
|
||||
cd qaup-admin
|
||||
mvn spring-boot:run
|
||||
|
||||
# Production deployment using script
|
||||
./qaup.sh start
|
||||
```
|
||||
|
||||
### Frontend Development
|
||||
```bash
|
||||
# Start frontend (Vue.js)
|
||||
cd qaup-ui
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Debugging and Maintenance Commands
|
||||
|
||||
### Process Management
|
||||
```bash
|
||||
# Check port usage
|
||||
lsof -ti:8080
|
||||
|
||||
# Kill process if needed
|
||||
kill -9 <process-id>
|
||||
```
|
||||
|
||||
### Log Monitoring
|
||||
```bash
|
||||
# View logs
|
||||
tail -f qaup-admin/app.log
|
||||
```
|
||||
|
||||
## System Commands (Darwin/macOS)
|
||||
- `git` - Version control
|
||||
- `ls` - List directory contents
|
||||
- `cd` - Change directory
|
||||
- `grep` - Search text patterns
|
||||
- `find` - Find files and directories
|
||||
- `lsof` - List open files and processes
|
||||
- `kill` - Terminate processes
|
||||
- `tail` - Display file tail content
|
||||
|
||||
## Database Setup
|
||||
1. PostgreSQL with PostGIS extension enabled
|
||||
2. Run initialization scripts in order:
|
||||
- `sql/create_qaup_database.sql`
|
||||
- `sql/create_sys_vehicle_info_table.sql`
|
||||
- `sql/create_sys_driver_info_table.sql`
|
||||
@ -1,68 +0,0 @@
|
||||
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
|
||||
# * For C, use cpp
|
||||
# * For JavaScript, use typescript
|
||||
# Special requirements:
|
||||
# * csharp: Requires the presence of a .sln file in the project folder.
|
||||
language: java
|
||||
|
||||
# whether to use the project's gitignore file to ignore files
|
||||
# Added on 2025-04-07
|
||||
ignore_all_files_in_gitignore: true
|
||||
# list of additional paths to ignore
|
||||
# same syntax as gitignore, so you can use * and **
|
||||
# Was previously called `ignored_dirs`, please update your config if you are using that.
|
||||
# Added (renamed) on 2025-04-07
|
||||
ignored_paths: []
|
||||
|
||||
# whether the project is in read-only mode
|
||||
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||
# Added on 2025-04-18
|
||||
read_only: false
|
||||
|
||||
|
||||
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
|
||||
# Below is the complete list of tools for convenience.
|
||||
# To make sure you have the latest list of tools, and to view their descriptions,
|
||||
# execute `uv run scripts/print_tool_overview.py`.
|
||||
#
|
||||
# * `activate_project`: Activates a project by name.
|
||||
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
||||
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
||||
# * `delete_lines`: Deletes a range of lines within a file.
|
||||
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
|
||||
# * `execute_shell_command`: Executes a shell command.
|
||||
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
|
||||
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
|
||||
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
|
||||
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
||||
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
||||
# * `initial_instructions`: Gets the initial instructions for the current project.
|
||||
# Should only be used in settings where the system prompt cannot be set,
|
||||
# e.g. in clients you have no control over, like Claude Desktop.
|
||||
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
||||
# * `insert_at_line`: Inserts content at a given line in a file.
|
||||
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
||||
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
||||
# * `list_memories`: Lists memories in Serena's project-specific memory store.
|
||||
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
||||
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
|
||||
# * `read_file`: Reads a file within the project directory.
|
||||
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
|
||||
# * `remove_project`: Removes a project from the Serena configuration.
|
||||
# * `replace_lines`: Replaces a range of lines within a file with new content.
|
||||
# * `replace_symbol_body`: Replaces the full definition of a symbol.
|
||||
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
|
||||
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
||||
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
|
||||
# * `switch_modes`: Activates modes by providing a list of their names
|
||||
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
|
||||
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
|
||||
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
|
||||
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
|
||||
excluded_tools: []
|
||||
|
||||
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||
# (contrary to the memories, which are loaded on demand).
|
||||
initial_prompt: ""
|
||||
|
||||
project_name: "QAUP-Management"
|
||||
Loading…
Reference in New Issue
Block a user