1. 项目概述:智能家居系统的技术栈选型
去年接手一个智能家居平台重构项目时,我最终选择了SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0这套技术组合。这个全栈架构在开发效率、性能表现和可维护性上达到了很好的平衡,特别适合中小型物联网系统的快速迭代开发。
智能家居系统本质上是一个典型的物联网数据中台,需要处理设备状态同步、用户指令转发、定时任务调度等核心业务场景。SpringBoot2提供了完善的微服务支持,Vue3负责构建响应式管理界面,MyBatis-Plus简化了数据层开发,而MySQL8.0的JSON支持和窗口函数大大简化了设备日志处理。
提示:选择SpringBoot2而非SpringBoot3主要是考虑企业现有基础设施的兼容性,大多数生产环境仍运行在JDK8/11上
2. 后端架构设计与实现
2.1 SpringBoot2核心配置
在application.yml中需要特别注意以下关键配置:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/smart_home?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 加密密码建议使用Jasypt
mvc:
async:
request-timeout: 30000 # 设备状态上报接口超时时间
redis:
host: 127.0.0.1
port: 6379
timeout: 5000
设备通信模块采用Netty实现TCP长连接,这里分享一个心跳检测的实战代码:
java复制@ChannelHandler.Sharable
public class HeartbeatHandler extends IdleStateHandler {
private static final int READ_IDLE_TIME = 60;
public HeartbeatHandler() {
super(READ_IDLE_TIME, 0, 0, TimeUnit.SECONDS);
}
@Override
protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) {
ctx.close(); // 60秒未收到心跳则断开连接
}
}
2.2 MyBatis-Plus高级应用
对于设备状态表的分页查询,建议使用MyBatis-Plus的Lambda表达式写法:
java复制public Page<DeviceStatus> queryStatus(Long deviceId, Integer pageNum, Integer pageSize) {
return deviceStatusMapper.selectPage(
new Page<>(pageNum, pageSize),
Wrappers.<DeviceStatus>lambdaQuery()
.eq(DeviceStatus::getDeviceId, deviceId)
.orderByDesc(DeviceStatus::getReportTime)
);
}
踩坑记录:MySQL8.0在使用MyBatis-Plus批量插入时,需要在连接字符串添加rewriteBatchedStatements=true参数才能生效
3. 前端工程化实践
3.1 Vue3组合式API改造
设备控制面板采用Composition API重构后代码更清晰:
vue复制<script setup>
import { ref, onMounted } from 'vue'
import { getDeviceStatus, controlDevice } from '@/api/device'
const props = defineProps({
deviceId: String
})
const status = ref({})
const loading = ref(false)
onMounted(async () => {
loading.value = true
status.value = await getDeviceStatus(props.deviceId)
loading.value = false
})
const handleControl = async (command) => {
await controlDevice(props.deviceId, command)
status.value = await getDeviceStatus(props.deviceId)
}
</script>
3.2 状态管理方案选型
虽然Vuex4可以兼容Vue3,但我更推荐Pinia:
javascript复制// stores/device.js
import { defineStore } from 'pinia'
export const useDeviceStore = defineStore('device', {
state: () => ({
onlineCount: 0,
deviceMap: new Map()
}),
actions: {
async fetchOnlineCount() {
const res = await api.getOnlineDevices()
this.onlineCount = res.data.count
}
}
})
4. 数据库设计与优化
4.1 MySQL8.0特性应用
设备日志表利用JSON字段存储动态属性:
sql复制CREATE TABLE device_log (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
device_id VARCHAR(32) NOT NULL,
log_type ENUM('status','event','error') NOT NULL,
content JSON NOT NULL, -- 存储动态结构化的日志数据
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_device (device_id),
INDEX idx_time (create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 查询性能优化
对于设备历史状态查询,使用窗口函数大幅提升性能:
sql复制-- 获取每个设备最新状态
SELECT * FROM (
SELECT
device_id,
status_value,
ROW_NUMBER() OVER(PARTITION BY device_id ORDER BY report_time DESC) AS rn
FROM device_status
) t WHERE t.rn = 1;
5. 系统安全防护
5.1 接口鉴权方案
采用JWT+Redis实现无状态认证:
java复制public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization");
if (StringUtils.isEmpty(token)) {
throw new AuthException("未授权访问");
}
String userId = JwtUtil.verifyToken(token);
if (redisTemplate.opsForValue().get("user:"+userId) == null) {
throw new AuthException("令牌已失效");
}
return true;
}
}
5.2 设备通信安全
采用AES加密设备通信数据:
java复制public class DeviceCryptoUtils {
private static final String AES_KEY = "配置你的32位密钥";
public static String encrypt(String content) {
// 实现AES加密逻辑
}
public static String decrypt(String content) {
// 实现AES解密逻辑
}
}
6. 部署与监控
6.1 Docker化部署
后端服务的Dockerfile配置要点:
dockerfile复制FROM openjdk:11-jre
WORKDIR /app
COPY target/smart-home.jar .
EXPOSE 8080
ENTRYPOINT ["java","-jar","smart-home.jar",
"--spring.profiles.active=prod",
"--server.tomcat.max-threads=200"]
6.2 Prometheus监控
SpringBoot集成Prometheus的配置:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
tags:
application: smart-home
7. 开发中的典型问题
7.1 时区问题解决方案
MySQL8.0时区配置必须与应用一致:
sql复制-- 启动时执行
SET GLOBAL time_zone = '+8:00';
7.2 大事务处理
设备批量操作需要拆分事务:
java复制@Transactional(propagation = Propagation.REQUIRES_NEW)
public void batchUpdateDevices(List<Device> devices) {
for (Device device : devices) {
deviceMapper.updateById(device);
}
}
8. 项目文档规范
8.1 Swagger接口文档
SpringBoot集成Knife4j的配置:
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.smarthome.controller"))
.paths(PathSelectors.any())
.build();
}
}
8.2 数据库文档生成
使用SchemaCrawler生成数据库文档:
bash复制java -jar schemacrawler.jar \
--server=mysql --host=localhost --database=smart_home \
--user=root --password=yourpassword \
--info-level=standard --output-format=html \
--output-file=db-doc.html
这套技术栈在实际项目中展现了强大的生产力,特别是在处理高并发设备连接时(实测支持5000+设备同时在线),SpringBoot2的异步处理能力和Vue3的响应式更新配合得非常好。对于需要快速开发智能家居系统的团队,这个架构方案值得参考。
