首页 / 资讯中心 / 文章详情

智能雨伞共享系统:SpringBoot+小程序物联网实践

智能雨伞共享系统:SpringBoot+小程序物联网实践 ★ FEATURED ARTICLE
1. 项目概述当共享经济遇上雨季刚需去年梅雨季我在杭州出差刚出地铁站就遇上暴雨眼睁睁看着便利店20元一把的劣质雨伞被抢购一空。这种场景催生了智能雨伞借取系统的设计初衷——通过物联网小程序的组合拳解决城市短时用伞需求。我们团队用SpringBoot微信小程序打造的这套系统目前已在6个城市地铁站部署日均借还量超过3000次。这个系统的核心价值在于用户通过小程序扫码即可完成借伞无需人工值守智能锁控模块确保资产安全信用积分机制降低丢失率。相比传统共享雨伞方案我们的技术栈选择更注重快速迭代和稳定性后端采用SpringBoot 2.7 MyBatis-Plus小程序端使用TypeScript重构硬件端通过蓝牙5.0与云端通信。2. 系统架构设计解析2.1 技术栈选型背后的思考选择SpringBoot而非传统SSM框架主要基于三个实际考量内嵌Tomcat简化部署特别适合商场、地铁站等分散部署场景Starter生态对微信支付、Redis缓存等组件开箱即用Actuator端点监控对硬件离线预警至关重要数据库选用MySQL 8.0因其GIS空间函数能高效处理租赁点地理查询。这里有个坑要注意必须显式设置时区为Asia/Shanghai否则小程序端显示的时间会错乱8小时。2.2 微服务拆分策略虽然单体架构也能实现但我们仍按功能拆分为三个微服务用户服务处理注册/登录/信用分端口8081交易服务处理押金/租金计算端口8082设备服务与硬件通信端口8083这种拆分的优势在硬件故障时尤为明显——当某个租赁柜离线时其他服务仍可正常运作。通过Spring Cloud OpenFeign实现服务间通信关键配置如下# application-dev.yml feign: client: config: default: connectTimeout: 5000 readTimeout: 300003. 核心功能实现细节3.1 小程序端关键技术点地图选点功能采用腾讯地图插件需要特别注意坐标系转换问题。我们封装了以下工具类public class MapUtils { // GCJ02转WGS84微信小程序使用的是GCJ02坐标系 public static double[] gcj02ToWgs84(double lng, double lat) { double[] result new double[2]; // 转换算法实现... return result; } }蓝牙通信模块的稳定性是另一个挑战。实测发现在iOS设备上需要添加1秒的延时重试机制function connectLock(deviceId: string, retry 3): Promisevoid { return new Promise((resolve, reject) { const tryConnect (attempt: number) { wx.createBLEConnection({ deviceId, success: () resolve(), fail: () attempt retry ? setTimeout(() tryConnect(attempt 1), 1000) : reject() }) } tryConnect(0) }) }3.2 硬件通信协议设计雨伞锁控模块采用自定义二进制协议[头标识0xAA][命令字][数据长度][数据内容][CRC校验]SpringBoot端通过Netty处理TCP连接关键解码器实现public class UmbrellaDecoder extends ByteToMessageDecoder { Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, ListObject out) { if (in.readableBytes() 5) return; // 最小包长度 in.markReaderIndex(); byte header in.readByte(); if (header ! (byte) 0xAA) { in.resetReaderIndex(); return; } // 剩余解码逻辑... } }4. 安全与性能优化实战4.1 双重防刷机制设计为防止恶意刷单我们实现了双重校验前端通过wx.getNetworkType()获取网络环境禁止代理请求后端基于Redis的令牌桶限流Guava RateLimiter在集群环境下失效Aspect Component public class RateLimitAspect { Autowired private RedisTemplateString, Object redisTemplate; Around(annotation(rateLimit)) public Object checkRate(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable { String key rate: getRequestIP(); Long count redisTemplate.opsForValue().increment(key, 1); if (count ! null count 1) { redisTemplate.expire(key, rateLimit.time(), TimeUnit.SECONDS); } if (count rateLimit.count()) { throw new BusinessException(操作过于频繁); } return joinPoint.proceed(); } }4.2 高并发场景应对在早高峰时段单个租赁点可能面临每分钟上百次请求。我们通过三级缓存策略应对本地缓存Caffeine存储静态数据如租赁点信息Redis集群存储实时库存等高频变更数据MySQL最终数据持久化库存扣减的原子性操作使用Lua脚本实现local key KEYS[1] local change tonumber(ARGV[1]) local current tonumber(redis.call(GET, key) or 0) if current change 0 then redis.call(INCRBY, key, change) return 1 else return 0 end5. 运维监控体系建设5.1 全链路日志追踪通过MDC实现请求链路追踪关键配置public class LogInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { MDC.put(traceId, UUID.randomUUID().toString().substring(0,8)); return true; } } // logback-spring.xml appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder pattern%d{yyyy-MM-dd HH:mm:ss} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n/pattern /encoder /appender5.2 硬件健康度监测通过Spring Boot Actuator自定义EndpointComponent Endpoint(id umbrella-health) public class UmbrellaHealthEndpoint { ReadOperation public MapString, Object health() { return Map.of( offlineCount, deviceService.getOfflineCount(), batteryAlert, deviceService.getLowBatteryDevices() ); } }配合PrometheusGrafana搭建的监控看板可以实时发现电池电量低于20%的设备。6. 踩坑实录与性能对比6.1 微信支付异步通知之坑初期我们采用官方推荐的JSSDK方式但在Android机型上频繁出现签名错误。最终解决方案是统一使用v3版API在服务端做二次签名验证添加异步通知重试队列关键验证逻辑public boolean verifySignature(String serialNumber, String timestamp, String nonce, String body, String signature) { X509Certificate certificate getCertificate(serialNumber); String message timestamp \n nonce \n body \n; return verifySHA256withRSA(certificate, message, signature); }6.2 数据库优化前后对比优化前单表500万记录时查询平均耗时320ms高峰时段CPU占用85%优化措施按城市分表t_umbrella_上海为status字段添加位图索引热点数据垂直拆分优化后查询耗时50msCPU占用峰值45%7. 扩展思考如何设计信用体系我们参考芝麻信用设计了动态积分算法信用分 基础分(600) 准时归还次数×2 - 超时次数×5 - 丢失次数×20 社交助力×0.5好友助力加分实现时需要注意并发修改问题采用乐观锁控制UPDATE user_credit SET score score #{delta}, version version 1 WHERE user_id #{userId} AND version #{version}这套系统从技术角度看不算复杂但真正考验的是对线下场景的理解。比如我们发现在雨天早高峰时段把小程序首页的立即借伞按钮放大30%转化率能提升18%。这提醒我们技术方案永远要服务于真实的用户需求。
阅读完成 · 觉得有帮助?
咨询建站