1. 项目背景与核心需求
这个项目源于我在智能家居领域的实际开发需求。当时我们需要为鸿蒙智能硬件设备构建一个可靠的后端服务系统,用于处理设备上报的数据、用户指令转发以及业务逻辑处理。经过技术选型评估,最终决定采用SpringBoot+MyBatis这套经典组合来搭建Web服务端。
选择这个技术栈主要基于以下几个实际考量:
- SpringBoot的自动配置特性能够快速搭建可运行的Web服务
- MyBatis的灵活性适合处理智能硬件场景下的复杂数据关系
- 这套组合的成熟度高,社区资源丰富,遇到问题容易找到解决方案
- 与鸿蒙设备的HTTP/HTTPS通信接口对接方便
2. 技术架构设计
2.1 整体架构设计
我们的后端系统采用典型的三层架构:
- 表现层:Spring MVC处理HTTP请求
- 业务逻辑层:Spring管理的Service组件
- 数据访问层:MyBatis实现数据库操作
与鸿蒙硬件的交互流程如下:
鸿蒙设备 -> HTTP/HTTPS -> SpringBoot Controller -> Service -> MyBatis -> MySQL2.2 数据库设计要点
针对智能硬件场景,数据库设计特别注意了以下几点:
- 设备表包含固件版本、最后在线时间等关键字段
- 数据上报表做了分表设计,按设备ID哈希分表
- 建立设备-用户多对多关系表
- 所有表都添加了创建时间和更新时间字段
CREATE TABLE device_info ( id BIGINT PRIMARY KEY AUTO_INCREMENT, device_id VARCHAR(64) UNIQUE, device_name VARCHAR(128), firmware_version VARCHAR(32), last_online_time DATETIME, status TINYINT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );3. SpringBoot应用搭建
3.1 初始化项目
使用Spring Initializr创建项目时特别注意的依赖选择:
- Spring Web:提供MVC支持
- MyBatis Framework:ORM框架
- MySQL Driver:数据库连接
- Lombok:简化实体类编写
- Spring Boot Actuator:应用监控
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>3.2 关键配置实现
application.yml中的核心配置项:
server: port: 8080 servlet: context-path: /api spring: datasource: url: jdbc:mysql://localhost:3306/harmony_device?useSSL=false&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true特别注意:在生产环境中务必使用加密的方式处理数据库密码,可以使用Jasypt等库实现配置加密。
4. MyBatis集成与优化
4.1 动态SQL实践
在设备数据查询场景中,大量使用了MyBatis的动态SQL特性:
<select id="selectDevicesByCondition" resultType="Device"> SELECT * FROM device_info <where> <if test="status != null"> AND status = #{status} </if> <if test="deviceName != null and deviceName != ''"> AND device_name LIKE CONCAT('%', #{deviceName}, '%') </if> </where> ORDER BY created_at DESC </select>4.2 批量操作优化
针对设备数据批量上报的场景,特别优化了批量插入性能:
@Insert("<script>" + "INSERT INTO device_data (device_id, data_type, data_value, created_at) VALUES " + "<foreach collection='list' item='item' separator=','>" + "(#{item.deviceId}, #{item.dataType}, #{item.dataValue}, NOW())" + "</foreach>" + "</script>") void batchInsert(@Param("list") List<DeviceData> dataList);5. 接口设计与实现
5.1 设备认证接口
鸿蒙设备通过HTTPS调用此接口进行身份认证:
@RestController @RequestMapping("/device") public class DeviceController { @Autowired private DeviceService deviceService; @PostMapping("/auth") public ResponseResult<AuthVO> auth(@RequestBody AuthDTO authDTO) { // 参数校验 if (StringUtils.isEmpty(authDTO.getDeviceId()) || StringUtils.isEmpty(authDTO.getToken())) { return ResponseResult.fail("参数错误"); } // 业务处理 return deviceService.authDevice(authDTO); } }5.2 数据上报接口
处理设备定时上报的各种传感器数据:
@PostMapping("/data/report") public ResponseResult<Void> reportData( @RequestBody @Valid DeviceDataReportDTO reportDTO, @RequestHeader("X-Device-ID") String deviceId) { // 验证设备状态 Device device = deviceService.getById(deviceId); if (device == null || device.getStatus() != DeviceStatus.ONLINE.getCode()) { return ResponseResult.fail("设备不可用"); } // 处理上报数据 dataService.processReportData(deviceId, reportDTO); return ResponseResult.success(); }6. 性能优化实践
6.1 连接池配置
针对智能硬件可能产生的高并发连接,优化了HikariCP连接池配置:
spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 18000006.2 缓存策略
使用Redis缓存设备信息和常用数据:
@Service public class DeviceCacheServiceImpl implements DeviceCacheService { @Autowired private RedisTemplate<String, Object> redisTemplate; private static final String DEVICE_KEY_PREFIX = "device:"; @Override @Cacheable(value = "device", key = "#deviceId") public Device getDeviceById(String deviceId) { return deviceMapper.selectById(deviceId); } @Override @CacheEvict(value = "device", key = "#deviceId") public void evictDeviceCache(String deviceId) { // 缓存自动清除 } }7. 安全防护措施
7.1 接口安全设计
- 所有接口强制HTTPS
- 设备接口使用签名验证
- 用户接口采用JWT认证
- 敏感操作增加二次验证
- 接口限流防护
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/device/**").permitAll() .antMatchers("/api/**").authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); } }7.2 SQL注入防护
- 坚持使用MyBatis的参数绑定
- 禁止拼接SQL语句
- 对动态表名采用白名单校验
- 定期使用SQL注入检测工具扫描
8. 问题排查与解决
8.1 典型问题记录
MyBatis映射问题:
- 现象:查询返回的字段值为null
- 原因:数据库字段命名规范与Java属性不匹配
- 解决:配置
map-underscore-to-camel-case: true
连接泄漏问题:
- 现象:运行一段时间后连接池耗尽
- 原因:未正确关闭SqlSession
- 解决:使用try-with-resources或确保在finally块中关闭
批量插入性能问题:
- 现象:插入1000条数据耗时超过10秒
- 原因:未启用批处理模式
- 解决:在JDBC URL添加
rewriteBatchedStatements=true
8.2 监控与日志
配置完善的监控体系:
- Spring Boot Actuator暴露健康指标
- 自定义设备在线率统计
- 接口响应时间监控
- 异常告警通知
日志记录特别注意:
@Slf4j @RestController @RequestMapping("/api") public class ApiController { @PostMapping("/command") public ResponseResult sendCommand(@RequestBody CommandDTO dto) { log.info("收到控制命令:{}", dto); try { // 处理逻辑 return ResponseResult.success(); } catch (Exception e) { log.error("命令处理异常:", e); return ResponseResult.fail("处理失败"); } } }9. 部署与运维
9.1 打包与部署
使用SpringBoot的Maven插件打包:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> </configuration> </plugin> </plugins> </build>部署注意事项:
- 使用JDK11+运行环境
- 配置合适的JVM参数
- 使用Nginx做反向代理
- 配置日志轮转
9.2 数据库维护
定期维护任务:
- 设备数据归档(将历史数据移到归档表)
- 索引优化(定期分析慢查询)
- 备份策略(每日全备+binlog)
-- 创建数据归档存储过程 DELIMITER // CREATE PROCEDURE archive_device_data(IN keep_days INT) BEGIN DECLARE cutoff_date DATE; SET cutoff_date = DATE_SUB(CURRENT_DATE(), INTERVAL keep_days DAY); INSERT INTO device_data_archive SELECT * FROM device_data WHERE created_at < cutoff_date; DELETE FROM device_data WHERE created_at < cutoff_date; END // DELIMITER ;10. 项目演进方向
在实际运行过程中,我们持续对系统进行优化和扩展:
微服务化改造:
- 将设备管理、用户服务、数据服务拆分为独立服务
- 引入Spring Cloud Alibaba体系
- 使用Nacos作为服务发现中心
消息队列引入:
- 使用RocketMQ处理设备数据
- 实现削峰填谷
- 提高系统吞吐量
数据统计分析:
- 集成Elasticsearch实现设备数据搜索
- 使用Flink做实时计算
- 构建数据可视化大屏
这套基于SpringBoot+MyBatis的后端系统已经稳定运行了6个月,支撑了超过1万台鸿蒙智能设备的接入。在开发过程中积累的经验告诉我,良好的架构设计加上合适的优化手段,这套经典组合完全能够胜任物联网后端开发的各项需求。