一个专为EMQX设计的Topic管理增强服务,提供直观的Web界面来管理和监控MQTT Topic。
为了解决目前生产环境中MQTT Topic管理混乱、难以维护和缺乏业务视角的问题,我自主开发并上线了一套 “EMQX Topic管理增强系统”。
该系统作为EMQX企业版功能的补充与增强,旨在实现对海量Topic的规范化、可视化和精细化管理。其核心价值与功能包括:
- 全局视角,集中管理:系统可同步并展示现有EMQX集群的全量Topic信息,提供一个统一的控制面板,彻底改变了过去需要通过命令行或零散查询的被动状态。
- 业务赋能,精细治理:创新性地引入了“业务分组” 和 “标签管理” 功能。允许我们不再从技术前缀(如 /device/001/temp),而是从业务逻辑(如“黄酒-传感器数据”)的维度对Topic进行归类、授权和审计,极大提升了管理效率。
- 消息体规范与沉淀:支持为每个Topic配置和定义期望的消息体格式(Payload Schema)。这不仅为开发人员提供了明确的接口规范,减少了通信歧义,也为后续的数据质量稽核奠定了基础。
- 多系统支持: 管理多个EMQX系统实例,支持不同环境的EMQX集群
- 实时状态监控: 实时显示系统在线状态、连接数、Topic数量
- 连接测试: 支持EMQX系统连接状态测试和响应时间监控
- 系统健康检查: 自动检测EMQX系统健康状态,提供详细的错误信息
- 安全认证: 支持EMQX API用户名密码认证,密码加密存储
- Topic同步: 从EMQX系统自动同步Topic信息,支持增量更新
- Topic CRUD: 完整的Topic创建、读取、更新、删除功能
- 路径管理: 支持MQTT Topic路径的层级展示和管理
- 批量操作: 支持批量添加标签、分配业务组、设置Payload模板等操作
- 高级搜索: 支持关键词搜索、标签筛选、业务组筛选、系统筛选
- 数据导出: 支持Topic数据的导出功能
- 彩色标签: 为Topic添加彩色标签进行可视化分类
- 标签管理: 创建、编辑、删除标签,支持颜色自定义
- 使用统计: 显示标签使用次数和关联Topic数量
- 批量标签: 支持批量添加和移除标签操作
- 删除保护: 防止删除正在使用的标签
- 业务分组: 按业务逻辑对Topic进行分组管理
- 分组统计: 显示每个业务组的Topic数量和使用情况
- 批量分组: 支持批量分配Topic到业务组
- 分组搜索: 支持按业务组筛选和搜索Topic
- 模板库: 提供丰富的Payload模板库,支持JSON、XML等格式
- 模板分类: 按业务组对模板进行分类管理
- 模板收藏: 支持收藏常用模板,快速访问
- 使用统计: 记录模板使用次数和最后使用时间
- 模板复制: 支持基于现有模板创建新模板
- 批量操作: 支持批量删除和管理模板
- 实时仪表板: 显示Topic总数、系统状态、连接数等实时数据
- 系统概览: 提供多系统整体运行状况的可视化仪表板
- 业务统计: 显示业务组和标签的使用统计
- 状态刷新: 支持手动刷新系统状态和数据同步
- 用户认证: 基于Sa-Token的用户登录认证系统
- 用户管理: 支持用户的创建、编辑、删除和状态管理
- 权限控制: 基于角色的访问权限控制
- 会话管理: 安全的用户会话管理和自动登出
- Spring Boot 3.2.0: 现代化的Java Web框架,提供RESTful API服务
- MyBatis Plus 3.5.5: 高效的ORM框架,简化数据库操作
- Sa-Token 1.39.0: 轻量级权限认证框架,支持JWT和Redis会话
- MySQL 8.2.0: 关系型数据库,存储Topic、用户、标签等核心数据
- Redis: 缓存和会话存储,提升系统性能
- FastJSON 2.0.43: 高性能JSON处理库
- Spring Boot Actuator: 应用监控和健康检查
- Maven: 项目构建和依赖管理
- Vue 3: 渐进式JavaScript框架,采用Composition API
- TypeScript: 类型安全的JavaScript超集,提供更好的开发体验
- Element Plus 2.10.7: 基于Vue 3的企业级组件库
- Vite 5.0.12: 快速的前端构建工具,支持热更新
- Pinia 3.0.3: Vue 3官方推荐的状态管理库
- Tailwind CSS 3.4.1: 实用优先的CSS框架,快速构建现代UI
- Axios 1.11.0: HTTP客户端,处理API请求
- Vue Router 4.2.5: Vue.js官方路由管理器
- Docker: 容器化部署,支持单阶段构建
- OpenJDK 17: Java运行时环境
- G1GC: 垃圾收集器优化
- Health Check: 容器健康检查机制
- Docker: 20.10+ (推荐使用Docker部署)
- MySQL: 8.0+ (存储应用数据)
- Redis: 6.0+ (缓存和会话存储)
- EMQX: 5.0+ (被管理的MQTT Broker)
- Java: 17+ (本地开发需要)
- Node.js: 18+ (前端开发需要)
- Maven: 3.6+ (后端构建需要)
- 克隆项目
git clone <repository-url>
cd EmqxTopicHub- 构建Docker镜像
docker build -t emqx-topic-hub:latest .- 准备数据库创建MySQL数据库:
CREATE DATABASE emqx_topic_hub CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;- 运行容器
docker run -d \
--name emqx-topic-hub \
-p 8080:8080 \
-v /host/logs:/app/logs \
-e SPRING_DATASOURCE_URL=jdbc:mysql://your-mysql-host:3306/emqx_topic_hub \
-e SPRING_DATASOURCE_USERNAME=your-username \
-e SPRING_DATASOURCE_PASSWORD=your-password \
-e SPRING_DATA_REDIS_HOST=your-redis-host \
-e SPRING_DATA_REDIS_PASSWORD=your-redis-password \
emqx-topic-hub:latest说明:
- `-v /host/logs:/app/logs`:将宿主机的`/host/logs`目录挂载到容器的`/app/logs`目录,用于持久化日志文件
- 请将`/host/logs`替换为您希望存储日志的实际路径
- 访问应用打开浏览器访问:
http://localhost:8080默认登录账号:- 用户名:
admin - 密码:
admin123
- 用户名:
- 环境要求
- JDK 17+
- Maven 3.6+
- MySQL 8.0+
- Redis 6.0+
- 配置数据库修改
backend/src/main/resources/application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/emqx_topic_hub
username: your-username
password: your-password
data:
redis:
host: localhost
port: 6379
password: your-redis-password- 启动后端服务
cd backend
mvn spring-boot:run后端服务将在 http://localhost:8080 启动
- 环境要求
- Node.js 18+
- npm 或 yarn
- 安装依赖
cd frontend
npm install- 启动开发服务器
npm run dev前端服务将在 http://localhost:3000 启动
| 变量名 | 描述 | 默认值 |
|---|---|---|
SPRING_DATASOURCE_URL |
MySQL数据库连接URL | - |
SPRING_DATASOURCE_USERNAME |
数据库用户名 | - |
SPRING_DATASOURCE_PASSWORD |
数据库密码 | - |
SPRING_DATA_REDIS_HOST |
Redis主机地址 | localhost |
SPRING_DATA_REDIS_PORT |
Redis端口 | 6379 |
SPRING_DATA_REDIS_PASSWORD |
Redis密码 | - |
SERVER_PORT |
后端服务端口 | 8080 |
应用首次启动时会自动创建数据库表结构。如需手动初始化,可执行以下SQL脚本:
-- 创建用户表
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL UNIQUE,
`password` varchar(255) NOT NULL,
`email` varchar(100),
`status` tinyint DEFAULT 1,
`last_login_time` datetime,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted` tinyint DEFAULT 0,
PRIMARY KEY (`id`)
);
-- 插入默认管理员账号
INSERT INTO `user` (`username`, `password`, `email`)
VALUES ('admin', 'e10adc3949ba59abbe56e057f20f883e', 'admin@example.com');server:
port: 8080
spring:
application:
name: emqx-topic-hub
datasource:
url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:emqx_topic_hub}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:password}
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:}
database: ${REDIS_DB:0}
timeout: 5000
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
# MyBatis Plus配置
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
# Sa-Token认证配置
sa-token:
token-name: satoken
timeout: 2592000 # token有效期30天
activity-timeout: -1 # 无活动超时
is-concurrent: true # 允许并发登录
is-share: true # 共享token
token-style: uuid # token风格
is-log: false # 关闭日志
jwt-secret-key: ${JWT_SECRET:emqx-topic-hub-secret-key}
# 应用自定义配置
app:
emqx:
default-timeout: 10000 # EMQX API默认超时时间(ms)
max-retry: 3 # 最大重试次数
# 日志配置
logging:
level:
com.emqx.topic: INFO
org.springframework.web: INFO
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n".env (开发环境)
# API基础URL
VITE_API_BASE_URL=http://localhost:8080/api
# 应用信息
VITE_APP_TITLE=EMQX Topic Hub
VITE_APP_VERSION=1.0.0
# 开发模式配置
VITE_DEV_MODE=true
VITE_MOCK_API=false.env.production (生产环境)
# 生产环境API地址
VITE_API_BASE_URL=/api
# 应用信息
VITE_APP_TITLE=EMQX Topic Hub
VITE_APP_VERSION=1.0.0
# 生产模式配置
VITE_DEV_MODE=false
VITE_ENABLE_ANALYTICS=trueimport { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '/api')
}
}
},
build: {
outDir: 'dist',
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
element: ['element-plus']
}
}
}
}
})EMQX-TopicX/
├── backend/ # 后端Spring Boot服务
│ ├── src/main/java/com/emqx/topic/
│ │ ├── controller/ # REST API控制器
│ │ │ ├── AuthController.java # 用户认证
│ │ │ ├── DashboardController.java # 仪表板数据
│ │ │ ├── GroupController.java # 业务组管理
│ │ │ ├── PayloadTemplateController.java # Payload模板
│ │ │ ├── SystemController.java # EMQX系统管理
│ │ │ ├── TagController.java # 标签管理
│ │ │ ├── TopicController.java # Topic管理
│ │ │ └── UserController.java # 用户管理
│ │ ├── service/ # 业务逻辑层
│ │ │ ├── AuthService.java # 认证服务
│ │ │ ├── DashboardService.java # 仪表板服务
│ │ │ ├── EmqxService.java # EMQX API集成
│ │ │ └── TopicService.java # Topic业务逻辑
│ │ ├── mapper/ # MyBatis数据访问层
│ │ ├── entity/ # JPA实体类
│ │ ├── dto/ # 数据传输对象
│ │ │ └── SystemManagementDTO.java
│ │ ├── config/ # 配置类
│ │ │ ├── SaTokenConfig.java # 认证配置
│ │ │ └── WebConfig.java # Web配置
│ │ └── TopicApplication.java # 应用启动类
│ ├── src/main/resources/
│ │ ├── mapper/ # MyBatis XML映射文件
│ │ ├── schema.sql # 数据库初始化脚本
│ │ └── application.yml # 应用配置文件
│ └── pom.xml # Maven依赖管理
├── frontend/ # 前端Vue 3应用
│ ├── src/
│ │ ├── components/ # 可复用组件
│ │ ├── views/ # 页面组件
│ │ │ ├── DashboardPage.vue # 仪表板页面
│ │ │ ├── GroupManagement.vue # 业务组管理
│ │ │ ├── PayloadTemplate.vue # Payload模板管理
│ │ │ ├── TopicDetail.vue # Topic详情页
│ │ │ └── TopicOverview.vue # Topic总览页
│ │ ├── stores/ # Pinia状态管理
│ │ ├── api/ # API接口定义
│ │ │ ├── auth.ts # 认证API
│ │ │ ├── group.ts # 业务组API
│ │ │ ├── payloadTemplate.ts # 模板API
│ │ │ ├── system.ts # 系统管理API
│ │ │ └── topic.ts # Topic API
│ │ ├── types/ # TypeScript类型定义
│ │ ├── router/ # Vue Router路由配置
│ │ └── main.ts # 应用入口文件
│ ├── public/ # 静态资源
│ ├── package.json # 前端依赖配置
│ ├── vite.config.ts # Vite构建配置
│ ├── tailwind.config.js # Tailwind CSS配置
│ └── tsconfig.json # TypeScript配置
├── docker-compose.yml # Docker编排文件
├── Dockerfile # 多阶段Docker构建
├── .gitignore # Git忽略文件
└── README.md # 项目文档
- 添加EMQX系统
- 进入「系统管理」页面
- 点击「添加系统」按钮
- 填写EMQX系统信息:
- 系统名称:便于识别的名称
- API地址:EMQX REST API地址 (如: http://localhost:18083)
- 用户名/密码:EMQX Dashboard的认证信息
- 系统描述:可选的描述信息
- 点击「测试连接」验证配置
- 保存后系统会自动检测连接状态
- 监控系统状态
- 实时查看系统在线/离线状态
- 监控EMQX连接数和Topic数量
- 查看系统响应时间和最后检查时间
- 支持手动刷新系统状态
- 同步Topic
- 在「Topic总览」页面选择EMQX系统
- 点击「同步Topic」从EMQX系统获取最新Topic列表
- 系统会自动识别新增、删除的Topic
- 管理Topic
- 支持多条件搜索:关键词、业务组、标签、系统
- 批量操作:
- 批量分配业务组
- 批量添加/移除标签
- 批量设置Payload模板
- 单个Topic操作:查看详情、编辑、删除
- 数据导出:支持导出Topic列表为Excel或CSV
- Topic详情
- 查看Topic基本信息(名称、路径、所属业务、创建时间等)
- 管理Topic标签:添加、移除标签
- 查看关联的Payload模板
- 业务组管理
- 创建业务组:设置名称和描述
- 查看业务组统计:Topic数量、使用情况
- 编辑和删除业务组
- 搜索和筛选业务组
- 标签管理
- 创建彩色标签:自定义标签名称和颜色
- 查看标签使用统计:关联Topic数量
- 编辑标签信息和颜色
- 删除未使用的标签
- 模板库使用
- 浏览预置的Payload模板库
- 按业务组筛选模板
- 收藏常用模板
- 查看模板使用统计
- 自定义模板
- 创建新的Payload模板
- 支持JSON、XML等格式
- 设置模板变量和参数
- 复制现有模板进行修改
- 模板应用
- 为Topic批量设置Payload模板
- 在Topic详情中查看关联模板
- 记录模板使用历史
- 用户账号管理
- 管理员可创建、编辑、删除用户
- 设置用户状态(启用/禁用)
- 查看用户登录历史
- 权限控制
- 基于Sa-Token的认证机制
- 支持JWT令牌和Redis会话
- 自动登出和会话过期处理
# 用户登录
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "password"
}
# 用户登出
POST /api/auth/logout
Authorization: Bearer {token}
# 获取用户信息
GET /api/auth/userinfo
Authorization: Bearer {token}# 获取系统列表
GET /api/systems
# 创建系统
POST /api/systems
{
"name": "EMQX生产环境",
"apiUrl": "http://localhost:18083",
"username": "admin",
"password": "public",
"description": "生产环境EMQX集群"
}
# 测试系统连接
POST /api/systems/{id}/test
# 刷新系统状态
POST /api/systems/{id}/refresh# 获取Topic列表
GET /api/topics?page=1&size=20&keyword=sensor&groupId=1&tagId=2
# 同步Topic
POST /api/topics/sync/{systemId}
# 批量操作Topic
POST /api/topics/batch
{
"topicIds": [1, 2, 3],
"operation": "addTags",
"data": {
"tagIds": [1, 2]
}
}
# 导出Topic数据
GET /api/topics/export?format=excel&groupId=1# 获取模板列表
GET /api/payload-templates?page=1&size=20&groupId=1&favorite=true
# 创建模板
POST /api/payload-templates
{
"name": "传感器数据模板",
"content": "{\"temperature\": 25.5, \"humidity\": 60}",
"description": "温湿度传感器数据格式",
"groupId": 1
}
# 收藏/取消收藏模板
POST /api/payload-templates/{id}/favorite
# 复制模板
POST /api/payload-templates/{id}/copyA: 请按以下步骤排查:
- 检查EMQX服务状态:确保EMQX服务正常运行
- 验证API地址:确认API地址格式正确(如:
http://192.168.1.100:18083) - 检查认证信息:确认用户名密码正确,建议使用EMQX Dashboard的管理员账号
- 网络连通性:测试网络连接,确保防火墙未阻止18083端口
- EMQX版本兼容性:确保EMQX版本为5.0+,支持REST API v5
A: 可能的原因和解决方案:
- 权限不足:确保使用的账号具有Topic管理权限
- API超时:检查网络延迟,可在配置中增加超时时间
- EMQX系统负载过高:等待系统负载降低后重试
- 数据库连接问题:检查MySQL和Redis连接状态
A: 请检查以下项目:
- 后端服务状态:确认Spring Boot应用已启动(端口8080)
- API代理配置:检查Vite代理配置是否正确
- 浏览器控制台:查看是否有JavaScript错误或网络请求失败
- CORS配置:确认后端CORS配置允许前端域名访问
A: 常见解决方案:
- 端口冲突:确保8080端口未被占用
- 数据库连接:检查MySQL和Redis容器是否正常启动
- 环境变量:确认docker-compose.yml中的环境变量配置正确
- 镜像构建:清理Docker缓存后重新构建:
docker-compose build --no-cache
A: 排查步骤:
- 默认账号:使用默认管理员账号 admin/admin123
- 数据库初始化:确认用户表已正确初始化
- Sa-Token配置:检查Sa-Token配置和Redis连接
- 密码加密:确认密码加密方式与数据库中存储的一致
A: 检查要点:
- JSON格式:确保模板内容为有效的JSON格式
- 权限问题:确认用户有模板管理权限
- 业务组关联:检查模板是否正确关联到业务组
- 模板状态:确认模板未被删除或禁用
- ✨ 初始版本发布
- 🚀 支持多EMQX系统管理
- 📊 Topic同步和管理功能
- 🏷️ 标签和业务组管理
- 📄 Payload模板管理
- 👤 用户认证和权限控制
- 🐳 Docker容器化部署
- 📈 Topic使用统计和分析
- 🔔 系统告警和通知
- 📱 移动端适配
- 🌐 国际化支持
- 🔌 插件系统
- 📊 更丰富的数据可视化
我们欢迎所有形式的贡献!请遵循以下步骤:
- Fork项目到你的GitHub账号
- 克隆项目到本地:
git clone https://github.com/your-username/EMQX-TopicX.git
cd EMQX-TopicX- 后端开发环境:
cd backend
mvn clean install
mvn spring-boot:run- 前端开发环境:
cd frontend
npm install
npm run dev请使用以下格式提交代码:
<type>(<scope>): <description>
[optional body]
[optional footer]
Type类型:
feat: 新功能fix: 修复bugdocs: 文档更新style: 代码格式调整refactor: 代码重构test: 测试相关chore: 构建过程或辅助工具的变动
示例:
feat(topic): 添加Topic批量导出功能
- 支持Excel和CSV格式导出
- 添加导出进度提示
- 优化大数据量导出性能
Closes #123
- 创建功能分支:
git checkout -b feature/your-feature-name - 提交代码:
git commit -m "feat: your feature description" - 推送分支:
git push origin feature/your-feature-name - 创建Pull Request
- 等待代码审查和合并
- 🐛 Bug报告:GitHub Issues
- 💡 功能建议:GitHub Discussions
MIT License - 详见 LICENSE 文件
本项目采用MIT许可证,您可以自由使用、修改和分发本软件。







