news 2026/9/7 16:49:18

基于RuoYi和Spring Boot的在线智能IoT管理系统搭建指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于RuoYi和Spring Boot的在线智能IoT管理系统搭建指南

做在线智能 IoT 管理系统,最耗时间的往往不是设备接入协议,而是后台管理那套“通用功能”:用户登录、菜单权限、操作日志、数据字典、部门管理。这些功能每个项目都要重复写一遍,写起来又不能直接产生业务价值。如果你正在做物联网设备管理平台,或者准备用 Java 技术栈做毕业设计 / 课程设计 / 企业内部设备监控系统,本文会给你一条完整的实现路线:基于 RuoYi 框架 + Spring Boot + MySQL,配合 Idea 开发和 HTML/CSS 前端页面,快速搭出一个能用的在线智能 IoT 管理系统。

先说判断:RuoYi 这类快速开发平台,真正降低的是通用后台功能的开发成本,而不是 IoT 业务本身的复杂度。设备接入协议、数据上报链路、告警规则这些核心逻辑,依然需要你亲手设计。所以这篇文章会分成两条线推进:一条线讲怎么用 RuoYi 把用户、权限、菜单这些底座跑起来;另一条线讲怎么把 IoT 设备管理、数据上报、设备告警做成真正可落地的业务模块。两条线合在一起,才是一个完整的在线智能 IoT 管理系统。

1. 这篇文章真正要解决的问题

很多新手拿到 IoT 项目需求时,第一反应是:先研究 MQTT 协议,先写设备端代码,先做通信模块。这个顺序其实反了。

设备端只解决“数据怎么传上来”的问题,而一个完整的管理系统还要解决“数据传上来之后怎么办”。以我接触过的设备管理类项目为例,最常见的状态是:设备数据已经通过 MQTT 或 HTTP 上报到服务端,但后台没有用户体系,没有设备台账,没有历史数据查询页面,告警只能靠人工看日志。这就像家里装了一堆智能传感器,却没有一个统一控制面板,数据都在,但用不起来。

RuoYi 出现在这里,是为了解决“控制面板”的问题。它自带了一套成熟的后台管理基础功能:

  • 用户管理、角色管理、菜单管理、部门管理
  • 操作日志、登录日志、数据字典
  • 代码生成器,可以根据数据库表自动生成 CRUD 代码
  • 统一的前端页面框架和权限控制

而 IoT 业务本身,还需要你做四件事:

  1. 设计设备信息表、设备上报数据表、设备告警表
  2. 开放一个设备数据上报接口,接收设备端推上来的数据
  3. 提供设备管理页面,让运维人员看到所有设备的在线状态、基本信息、最新数据
  4. 设计告警规则,当温度、电压等指标超过阈值时,产生告警记录

这篇文章适合以下几类读者:准备用 Java 技术栈做 IoT 管理系统但不知道如何起步的人;想做毕设选题“在线智能物联网管理系统”的大学生;以及公司内部需要一个轻量级设备管理后台,但不想花三个月从零写权限系统的开发人员。

读完这篇文章,你会跑通这样一条完整链路:初始化 RuoYi 项目 → 设计设备相关数据表 → 用代码生成器生成业务 CRUD → 编写设备数据上报接口 → 开发设备管理前端页面 → 用模拟数据验证设备上报和在线状态更新。

2. 核心概念:RuoYi、Spring Boot、MySQL 在 IoT 系统中的分工

在动手之前,先把几个概念讲清楚,不然代码写完了可能还是不知道每一层在做什么。

2.1 RuoYi 到底是什么

RuoYi(若依)是一个基于 Spring Boot + Spring Security + MyBatis 的快速开发平台。你从官网下载项目后,默认就有用户管理、部门管理、菜单权限、登录认证这些功能。它的核心价值不是“多了一个框架要学”,而是帮你省掉了业务系统里最通用的那 30% 代码。

RuoYi 有两个常见版本:单体版本(后端 + Thymeleaf 模板页面)和前后端分离版本(RuoYi-Vue)。本文以单体版本为例来说明,因为项目标题里明确提到了 html/css,单体版本的页面能够直接用 Thymeleaf 模板和 HTML 渲染,理解起来更直观。前后端分离版本的思路完全一致,只是后端输出 JSON,前端用 Vue 做页面,业务表的 CRUD 设计没有本质区别。

有一个容易踩坑的理解误区:以为用了 RuoYi 就不用写代码了。实际上不是。RuoYi 提供的是基础底座和代码生成器,它可以生成实体类、Mapper、Service、Controller 的标准 CRUD 代码,但设备上报接口、告警判断逻辑、在线状态维护这些 IoT 业务逻辑,仍然需要自己写。

2.2 Spring Boot 在系统里的角色

Spring Boot 是这套系统的运行时骨架。它负责把数据库连接、Web 接口、事务管理、日志等组件组合起来,让开发人员少写大量 XML 配置。在 IoT 管理系统里,Spring Boot 的职责主要是:

  • 提供 HTTP 接口,接收前端页面的请求
  • 提供设备数据上报接口,接收设备端或模拟器推送的数据
  • 协调 Service 层和 Mapper 层,完成数据库读写
  • 集成 Spring Security,由 RuoYi 默认配置完成登录认证和权限控制

如果你之前只用 Spring Boot 写过传统 CRUD,那 IoT 系统在接口层并没有多出多少复杂性。真正的复杂性在数据模型设计:设备和数据是“一对多”的关系,每台设备会持续产生大量上报记录,这种数据形态和普通的订单表、用户表是不一样的。

2.3 MySQL 在 IoT 系统中的使用边界

MySQL 作为这套系统的核心存储,负责保存三类数据:RuoYi 框架自身的管理数据(用户、角色、菜单等)、业务基础数据(设备台账)、时序型数据(设备上报记录)。

这里有一个重要判断:如果设备数量少、上报频率低,比如家庭场景或小型工厂,MySQL 完全够用。但如果设备量达到几万台,每台设备每十秒上报一条数据,MySQL 很快会遇到写入压力和查询瓶颈。更合理的方案是引入时序数据库(如 TDengine、InfluxDB),或者对 MySQL 做分表归档。本文作为入门方案,先用 MySQL 把完整链路跑通,到了生产环境再根据数据量做演进。

2.4 一个典型 IoT 管理系统的分层架构

从整体架构看,这套在线智能 IoT 管理系统可以分成四层:

层级技术选型主要职责
设备接入层HTTP / MQTT接收设备上报的数据
应用服务层Spring Boot + RuoYi业务处理、权限控制、数据存储
数据存储层MySQL保存设备信息、上报数据、告警记录
Web 展示层HTML / CSS / Thymeleaf设备列表、状态监控、历史数据展示

这个架构对初学者最友好的地方在于:每一层都可以单独调试。设备接入层先用 Postman 或模拟器测,应用服务层直接用浏览器访问接口,数据存储层用 MySQL 客户端查询,Web 展示层最后对接接口。分层清晰,排错也会容易很多。

3. 环境准备与前置条件

在开始搭建之前,先把开发环境准备好。以下版本以常见的稳定组合为例,如果你是直接使用 RuoYi 官网最新代码,版本号请以你下载的版本为准。

3.1 开发工具与运行环境

组件建议版本说明
JDK1.8 或 17老版本 RuoYi 建议 1.8,新版本建议 17
IntelliJ IDEA2023 及以上导入 Maven 项目更方便
Maven3.6+管理项目依赖
MySQL5.7 或 8.0建议 8.0,性能更好
Redis5.0+RuoYi 部分配置可能需要,实际不强依赖

安装顺序建议:JDK → MySQL → Maven → IDEA。JDK 安装后,需要配置 JAVA_HOME 环境变量。MySQL 安装完成后,要记住 root 密码,并确保能通过命令行或客户端连接。

3.2 获取 RuoYi 项目

RuoYi 的下载和使用方式比较简单。你可以从项目官网获取源码,也可以通过 Maven 方式引入相关模块。项目是 Maven 多模块结构,典型的模块包括:

  • ruoyi-admin:启动模块,包含启动类和 controller
  • ruoyi-framework:框架核心,包括安全配置、拦截器
  • ruoyi-system:系统管理模块,用户、角色、菜单等
  • ruoyi-common:公共工具类

使用 IDEA 导入时,直接选择根目录的 pom.xml,让它以 Maven 项目方式加载。首次导入会下载大量依赖,国内网络环境下建议把 Maven 仓库地址配置为阿里云镜像,否则等待时间会很长。

3.3 数据库初始化

RuoYi 项目自带 SQL 脚本,包含了用户表、角色表、菜单表等基础数据。你需要先创建一个新的数据库,例如ry_iot,然后执行 RuoYi 项目的ry_xxx.sql脚本。执行完成后,表示 RuoYi 的基础表已经就绪。

有一点要特别提醒:RuoYi 的 SQL 脚本里默认带有字符集配置,建议统一使用utf8mb4,避免设备名称、位置描述等字段出现中文乱码。后面新增 IoT 业务表时,也保持这个习惯。

4. 核心数据表设计:设备、数据、告警

在线智能 IoT 管理系统的核心,不是页面,也不是接口,而是数据表设计。表设计一旦定下来,后端代码和前端页面基本就是围绕表结构展开的。

先明确实体关系:一台设备可以有多条上报数据、多条告警记录,所以设备表是主表,数据表和告警表是子表。

4.1 设备信息表 iot_device

设备表保存每台设备的静态信息。这里要注意区分“业务状态”和“在线状态”这两个字段:

  • status(业务状态):表示设备是否被停用,与是否在线无关。
  • online_status(在线状态):表示设备当前是否连接到服务器并保持上报。

这两个状态在实际项目里经常被混在一起,导致后续排错困难。设计时明确区分,后面写在线状态更新逻辑时会清晰很多。

CREATE TABLE iot_device ( device_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '设备ID', device_code varchar(64) NOT NULL COMMENT '设备唯一编码', device_name varchar(100) NOT NULL COMMENT '设备名称', device_type varchar(50) DEFAULT NULL COMMENT '设备类型,如温湿度传感器、电表', status char(1) DEFAULT '0' COMMENT '业务状态(0正常 1停用)', online_status char(1) DEFAULT '0' COMMENT '在线状态(0离线 1在线)', location varchar(200) DEFAULT NULL COMMENT '安装位置', last_report_time datetime DEFAULT NULL COMMENT '最后上报时间', create_by varchar(64) DEFAULT '' COMMENT '创建者', create_time datetime DEFAULT NULL COMMENT '创建时间', update_by varchar(64) DEFAULT '' COMMENT '更新者', update_time datetime DEFAULT NULL COMMENT '更新时间', remark varchar(500) DEFAULT NULL COMMENT '备注', PRIMARY KEY (device_id), UNIQUE KEY uk_device_code (device_code) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='IoT设备信息表';

device_code是设备唯一编码,在真实项目里一般是设备出厂时烧录的编号,或者是平台分配给设备的标识。这里设置了唯一索引,上报接口会根据这个编码定位设备。

4.2 设备上报数据表 iot_device_data

设备上报数据是 IoT 系统里增长最快的表。这类数据有几个特点:只插入、不修改、按时间查询。表设计上要特别关注索引,否则数据量一大,按设备和时间查历史数据会非常慢。

CREATE TABLE iot_device_data ( data_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '数据ID', device_id bigint(20) NOT NULL COMMENT '设备ID', temperature decimal(8,2) DEFAULT NULL COMMENT '温度值', humidity decimal(8,2) DEFAULT NULL COMMENT '湿度值', voltage decimal(8,2) DEFAULT NULL COMMENT '电压值', report_time datetime NOT NULL COMMENT '上报时间', PRIMARY KEY (data_id), KEY idx_device_time (device_id, report_time) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备上报数据表';

这里使用idx_device_time复合索引,是为了适配最常见的查询场景:查看某台设备在一段时间内的历史数据。如果业务需要按设备类型维度的汇总统计,可以考虑增加设备类型冗余字段,或者定期做聚合表,不要在原始数据表上做太复杂的统计查询。

4.3 设备告警表 iot_alarm

告警表用来记录设备指标超出阈值的情况。实际项目中,告警触发逻辑可以在设备端判断,也可以在服务端判断。对于智能 IoT 管理系统,推荐在服务端统一判断,因为这样规则可以动态调整,不用每次更新设备固件。

CREATE TABLE iot_alarm ( alarm_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '告警ID', device_id bigint(20) NOT NULL COMMENT '设备ID', alarm_type varchar(50) DEFAULT NULL COMMENT '告警类型,如超温、欠压', alarm_content varchar(500) DEFAULT NULL COMMENT '告警内容', status char(1) DEFAULT '0' COMMENT '处理状态(0未处理 1已处理)', alarm_time datetime DEFAULT NULL COMMENT '告警时间', PRIMARY KEY (alarm_id), KEY idx_alarm_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备告警表';

告警表和上报数据表本质上是两种类型的记录:数据表是设备“说了什么”,告警表是系统“发现了什么问题”。在实际开发中,上报数据每一条都会插入,但只有满足条件的上报才会插入告警记录,所以告警表的数据量会小很多。

5. 基于 RuoYi 的后端业务代码实现

数据表设计完成后,开始写后端代码。RuoYi 自带代码生成器,但对于 IoT 业务表,最稳妥的方式还是先手动写一遍核心链路,理解清楚以后再用生成器提高后续效率。

5.1 在 RuoYi 项目中添加设备模块的 Maven 依赖

如果你的 RuoYi 项目是多模块结构,可以在 ruoyi-admin 模块的 pom.xml 中添加快 JSON 解析库,用于处理上报接口的 JSON 数据。RuoYi 本身已经集成了 fastjson,通常不用额外添加,但如果版本较老,可以使用 fastjson2:

<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson2</artifactId> <version>2.0.36</version> </dependency>

实际开发中,这个依赖是否添加取决于项目里已有的依赖树。如果代码里用到了 fastjson 的 JSONObject,但没有相关依赖,就会出现编译报错。建议先检查依赖树,再决定是否添加。

5.2 配置数据库连接

在 ruoyi-admin 模块的 application.yml 中修改数据源配置,指向刚创建的ry_iot数据库:

server: port: 8080 spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/ry_iot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: 123456

这里最容易出的问题是serverTimezone配置错误。MySQL 8.0 连接时,如果 URL 不指定时区,JDBC 驱动会报时区错误。另外,characterEncoding=utf8是避免中文乱码的关键配置,不要漏掉。

5.3 编写设备实体类

在业务模块下新建com.iot.device.domain.IotDevice实体类。RuoYi 的实体类继承BaseEntity,可以复用创建时间、更新时间、备注等公共字段:

package com.iot.device.domain; import com.ruoyi.common.core.domain.BaseEntity; public class IotDevice extends BaseEntity { private Long deviceId; private String deviceCode; private String deviceName; private String deviceType; private String status; private String onlineStatus; private String location; private String lastReportTime; public Long getDeviceId() { return deviceId; } public void setDeviceId(Long deviceId) { this.deviceId = deviceId; } public String getDeviceCode() { return deviceCode; } public void setDeviceCode(String deviceCode) { this.deviceCode = deviceCode; } // 其他 getter / setter 省略,由 IDEA 快捷生成即可 }

这里的lastReportTime虽然是数据库的 datetime 类型,在实体类中既可以用Date也可以用String,RuoYi 的代码生成器默认会处理类型转换。为了减少前端格式转换的麻烦,这里示例使用 String,实际项目中建议统一用 Date,在返回 JSON 时配置格式化规则。

5.4 编写设备数据上报接口

设备数据上报是 IoT 系统的关键接口。它要做三件事:

  1. 根据 deviceCode 找到设备。
  2. 插入一条设备上报数据。
  3. 更新设备的最后上报时间和在线状态。

另外,还要判断温度、电压是否超过阈值,如果超过则写入告警表,方便运维人员处理。

package com.iot.device.controller; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.alibaba.fastjson2.JSONObject; import com.iot.device.domain.IotDevice; import com.iot.device.service.IotDeviceService; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; @RestController @RequestMapping("/iot/device") public class IotDeviceReportController extends BaseController { @Autowired private IotDeviceService iotDeviceService; @PostMapping("/report") public AjaxResult report(@RequestBody JSONObject body) { String deviceCode = body.getString("deviceCode"); // 1. 根据设备编码查找设备 IotDevice device = iotDeviceService.selectIotDeviceByCode(deviceCode); if (device == null) { return AjaxResult.error("设备不存在:" + deviceCode); } // 2. 记录上报数据 double temperature = body.getDoubleValue("temperature"); double humidity = body.getDoubleValue("humidity"); double voltage = body.getDoubleValue("voltage"); iotDeviceService.insertDeviceData(device.getDeviceId(), temperature, humidity, voltage); // 3. 更新设备在线状态和最后上报时间 iotDeviceService.updateOnlineStatus(device.getDeviceId(), new Date()); // 4. 判断阈值并写入告警 if (temperature > 60) { iotDeviceService.insertAlarm(device.getDeviceId(), "超温", "当前温度:" + temperature); } if (voltage < 180) { iotDeviceService.insertAlarm(device.getDeviceId(), "欠压", "当前电压:" + voltage); } return AjaxResult.success("上报成功"); } }

这里把阈值写死在代码里,只是为了演示完整链路。在实际工程项目中,阈值应该放到配置中心、数据库或 Redis 中,方便运行时动态修改。告警判断逻辑也应该独立成告警服务,避免上报接口过于臃肿。

5.5 编写 Service 和 Mapper 方法

Service 层需要实现几个核心方法:按编码查设备、插入数据、更新在线状态、插入告警。以插入上报数据为例,Mapper 层的 SQL 是这样写的:

<insert id="insertDeviceData"> INSERT INTO iot_device_data(device_id, temperature, humidity, voltage, report_time) VALUES(#{deviceId}, #{temperature}, #{humidity}, #{voltage}, #{reportTime}) </insert>

更新在线状态和最后上报时间:

<update id="updateOnlineStatus"> UPDATE iot_device SET online_status = '1', last_report_time = #{reportTime} WHERE device_id = #{deviceId} </update>

这里涉及一个很关键的业务判断:什么时候把设备状态置为离线?如果设备异常断电,它可能不会再上报数据,最后一次上报时间是 10 分钟前,如何判定它已经离线?

最常见的做法是增加一个定时任务,比如每分钟扫描一次设备表,把“最后上报时间早于当前时间 5 分钟”的设备置为离线。RuoYi 自带定时任务框架,可以在系统监控里配置一个定时任务,调用离线检测的 Service 方法,这是一个完整 IoT 系统必须考虑的问题。

5.6 设备管理列表接口

设备管理页面需要一个分页列表接口。RuoYi 的 BaseController 提供了startPage()方法,配合 MyBatis 的分页插件,可以很简洁地实现:

@GetMapping("/list") public TableDataInfo list(IotDevice device) { startPage(); List<IotDevice> list = iotDeviceService.selectIotDeviceList(device); return getDataTable(list); }

这个接口返回的是 RuoYi 约定的分页格式,前端表格组件可以直接拿到totalrows,不需要自己拼接 JSON。

6. 前端页面:设备管理列表与状态展示

RuoYi 单体版本的前端页面使用 Thymeleaf 模板引擎,HTML 文件放在resources/templates/iot/device.html目录下。页面本身使用 Layui 或简单 JavaScript 渲染都可以,这里给出一个简洁的例子,方便你理解页面如何与后端接口交互。

<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>IoT 设备管理</title> <link rel="stylesheet" href="/static/css/layui.css"> </head> <body> <div class="layui-container"> <h2>在线智能 IoT 设备列表</h2> <table class="layui-table" id="deviceTable"> <thead> <tr> <th>设备编码</th> <th>设备名称</th> <th>设备类型</th> <th>在线状态</th> <th>最后上报时间</th> <th>安装位置</th> </tr> </thead> <tbody id="deviceTbody"></tbody> </table> </div> <script src="/static/js/jquery.min.js"></script> <script> $(function() { $.get('/iot/device/list', function(res) { if (res.code === 0) { var rows = res.rows; var html = ''; for (var i = 0; i < rows.length; i++) { var row = rows[i]; var status = row.onlineStatus === '1' ? '在线' : '离线'; html += '<tr>'; html += '<td>' + row.deviceCode + '</td>'; html += '<td>' + row.deviceName + '</td>'; html += '<td>' + row.deviceType + '</td>'; html += '<td>' + status + '</td>'; html += '<td>' + row.lastReportTime + '</td>'; html += '<td>' + (row.location || '-') + '</td>'; html += '</tr>'; } $('#deviceTbody').html(html); } }); }); </script> </body> </html>

这里有一个新手经常踩的坑:RuoYi 默认情况下,所有接口都需要登录后才能访问。前端页面发起$.get('/iot/device/list')时,如果当前会话没有登录态,请求会被拦截并重定向到登录页,返回的数据就不是 JSON。

解决办法有两种:第一,在浏览器里先访问 RuoYi 的登录页,登录成功后再打开设备管理页面;第二,参考 RuoYi 的权限配置,给/iot/**的访问接口配置对应的权限标识,再在用户管理中为账号分配权限菜单。无论哪种方式,都要理解 RuoYi “先过后端权限认证,再访问业务接口”的基本逻辑。

7. 运行结果与效果验证

后端和前端代码完成后,进入验证阶段。验证的目标是:跑通“模拟设备上报 → 更新设备状态 → 页面看到结果”的完整链路。

7.1 启动项目

在 IDEA 中启动 ruoyi-admin 模块的启动类,控制台出现Started RuoYiApplication时,表示后端启动成功。启动过程中如果出现端口被占用,可以修改 application.yml 中的server.port

7.2 准备一条测试设备

在 iot_device 表中手动插入一台设备:

INSERT INTO iot_device(device_code, device_name, device_type, status, online_status, location) VALUES('DEV001', '车间温度传感器', '温湿度传感器', '0', '0', '一号车间');

这一步非常重要:设备表里如果没有这条记录,上报接口会直接返回“设备不存在”。

7.3 使用 curl 或工具模拟设备上报

先用最简单的 curl 命令模拟一次设备上报:

curl -X POST http://localhost:8080/iot/device/report \ -H "Content-Type: application/json" \ -d '{"deviceCode":"DEV001","temperature":25.6,"humidity":58.2,"voltage":220.3}'

如果返回结果包含"msg": "上报成功",说明接口逻辑已经走通。此时查询 iot_device 表,会看到online_status变为 1,last_report_time变成了当前时间。再查 iot_device_data 表,会多出一条上报记录。

7.4 验证告警触发

再执行一次模拟上报,把温度改成 80:

curl -X POST http://localhost:8080/iot/device/report \ -H "Content-Type: application/json" \ -d '{"deviceCode":"DEV001","temperature":80,"humidity":58.2,"voltage":220.3}'

查看 iot_alarm 表,应该能看到一条“超温”告警记录。

7.5 验证页面展示

打开设备管理页面,如果页面能正常显示设备列表,并且看到 DEV001 的在线状态是“在线”,说明后端接口、前端渲染、数据库更新这条链路全部跑通。

如果页面出现数据为空,优先打开浏览器开发者工具的 Network 面板,查看/iot/device/list这个请求返回了什么。如果返回的是 401 或跳转登录页,说明权限没有配置好,先走登录流程再测试。

8. 常见问题与排查思路

在基于 RuoYi 开发 IoT 管理系统的过程中,以下问题出现频率很高:

问题现象可能原因排查方式解决方案
页面调用接口返回 401未登录或接口没有配置权限打开浏览器 Network 查看请求状态先登录,或为接口配置权限标识
设备上报接口返回“设备不存在”device_code 不匹配查询 iot_device 表确认编码检查上报 JSON 中的 deviceCode
中文乱码数据库连接 URL 缺少 characterEncoding检查 application.yml添加characterEncoding=utf8
时间字段相差 8 小时JDBC 时区配置不对查询数据库时间与本地时间URL 添加serverTimezone=GMT%2B8
启动时报数据源错误MySQL 未启动或密码错误查看完整堆栈日志确认 MySQL 服务和账号密码
设备在线状态一直不变缺少离线扫描定时任务观察 last_report_time增加定时任务做超时离线判断

这里单独解释一下 401 的问题。RuoYi 自带 Spring Security,默认所有接口都受保护。很多人刚接触时,在浏览器地址栏输入接口地址,被重定向到登录页,就以为后端写错了。实际这是正常现象,只要登录后携带会话访问即可。

另一个容易忽略的问题是分页参数。RuoYi 的startPage()默认读取pageNumpageSize参数,如果你的前端请求没有传这两个参数,接口会返回全部数据。虽然功能没错,但设备数量多了以后会拖慢接口响应,建议在开发阶段就统一使用 RuoYi 的分页组件。

9. 最佳实践与工程建议

当整个 IoT 管理系统跑通以后,不要急着加新功能,先考虑下面这些工程层面的建议。它们决定了这个系统能不能从“demo”变成“能用的后台”。

9.1 设备编码规范

设备编码(device_code)是设备在系统中的唯一身份证,设计时要有全局视角。建议采用分段编码方式,例如:

  • 前 2 位代表设备类型:WD 表示温度、DL 表示电力
  • 中间 3 位代表区域编码
  • 最后几位代表设备序号

这样查日志、做报表、定位设备都能节省不少时间。

9.2 上报接口要做幂等和校验

设备端可能因为网络抖动而重复上报数据,上报接口如果每次都直接 insert,会导致数据量膨胀。可以设计一个去重字段,比如“设备编码 + 上报时间戳”,在插入前先查重。同时,接口参数要做合法性校验,防止设备异常时上报负数温度或空值,污染历史数据。

9.3 在线状态不要依赖设备主动断线

IoT 设备不具备稳定的“断线通知”能力,设备异常断电后,可能永远不会告知服务器。所以在线状态必须依靠超时判断维护。建议设计一个定时任务,周期扫描在线设备,将最后上报时间超过 5 分钟的设备置为离线。在 RuoYi 中,可以直接使用系统自带的定时任务功能,不需要额外引入 Quartz。

9.4 告警规则要可配置

不要在代码里写死阈值。阈值应该保存在配置表里,通过管理页面维护。比如温度超过多少触发“超温告警”,电压低于多少触发“欠压告警”。这样运维人员调整阈值时,不需要重新开发和发布服务。这就是在线智能 IoT 系统里“智能”二字的实际含义。

9.5 历史数据归档

设备上报数据会持续增长,建议从一开始就规划清理策略。最简单的方式是保留近三个月的明细数据,更早的数据定期迁移到归档表;如果业务允许,可以用定时任务删除。对于更复杂的统计需求,可以按天汇总设备数据的平均值、最大值、最小值,需要查询汇总趋势时直接读汇总表。

9.6 权限与安全边界

设备管理后台虽然内部使用,也要注意权限边界。RuoYi 默认提供了角色和菜单权限,建议按角色划分数据权限,比如普通运维人员只能查看设备列表和告警,管理员才能删除设备、调整告警阈值。涉及到生产环境的设备操作指令下发,不要直接暴露给前端,必须增加二次确认和操作日志记录。

9.7 代码生成器的使用时机

当你理解了实体、Mapper、Service、Controller 的写法之后,后续新加一张业务表,就可以使用 RuoYi 的代码生成器,从表结构直接生成标准 CRUD 代码。生成后再根据业务手动改造,效率会高很多。但第一张表,我仍然建议手写一遍,因为你只有理解了底层代码结构,才能在生成器生成的代码上做定制,否则出了问题都不知道从哪查起。

10. 总结与后续学习方向

到这里,一个基于 RuoYi + Spring Boot + MySQL 的在线智能 IoT 管理系统已经完整跑通了。你掌握了几个关键设计:设备和上报数据的一对多关系、在线状态的超时维护思路、上报接口的告警判断逻辑,以及 RuoYi 权限体系对业务接口的影响。

下一步,建议你从两个方向继续深入:一是把模拟上报替换成真实设备接入,可以了解 MQTT 协议与 EMQX 这类消息中间件,让设备通过 MQTT 上报数据,服务端订阅并写库;二是完善告警通知,当前告警只是写进了数据库,如果业务需要,可以扩展成短信、邮件或企业微信通知,这部分和 Spring Boot 的异步任务、消息队列结合得很紧密。

如果你是在做毕业设计或课程设计,基于这套系统,还可以继续扩展大屏数据可视化、设备地图定位、历史曲线报表等功能,技术栈不会变,核心还是在数据模型和接口设计上想清楚。建议先打开 IDEA,把这一套流程跑一遍,再回来看本文的设备表设计部分,会更有体会。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 16:49:01

Kali Linux BackTrack Mode 复古化改造完整指南

如果你是从 BackTrack 那个年代一路用过来的老用户&#xff0c;打开新版 Kali Linux 的第一反应大概率和我一样&#xff1a;这界面怎么完全变样了&#xff1f;终端不再是黑底绿字的 rootbt:~# &#xff0c;菜单也不是熟悉的 BackTrack 五个大分类&#xff0c;就连很多老命令都…

作者头像 李华
网站建设 2026/9/7 16:48:41

CS-Notes 剑指 Offer 动态规划:跳台阶问题的递推建模与 O(1) 空间解法

CS-Notes 剑指 Offer 动态规划:跳台阶问题的递推建模与 O(1) 空间解法 【免费下载链接】CS-Notes :books: 技术面试必备基础知识、Leetcode、计算机操作系统、计算机网络、系统设计 项目地址: https://gitcode.com/GitHub_Trending/cs/CS-Notes 本文基于 CS-Notes 仓库中…

作者头像 李华
网站建设 2026/9/7 16:47:39

Windows系统DLL修复工具:解决运行库与DirectX错误

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 16:45:53

git reset 超全解析:三种模式、底层原理与实战恢复技巧

我玩 Git 这么多年&#xff0c;git reset是我用得最多、也最容易被它坑过的命令之一。很多 Git 教程会把reset、checkout、revert放在一起讲&#xff0c;结果初学者越看越懵。这篇笔记我不打算面面俱到&#xff0c;就专注讲透git reset这一个命令&#xff1a;它到底移动了什么、…

作者头像 李华
网站建设 2026/9/7 16:44:46

零基础备考系统规划与管理师:别再盲目刷课,跑通闭环才是关键

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 16:43:34

注意力机制实战拆解:从原理到代码,搞懂Transformer的核心引擎

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华