1. 项目概述:SpringBoot与微信小程序结合的自行车租赁系统
这个基于SpringBoot后端和微信小程序前端的天府自行车租赁系统,是我在2023年参与开发的一个实际项目。整套系统采用前后端分离架构,后端使用SpringBoot 2.7提供RESTful API服务,前端采用微信小程序原生开发框架,数据库选用MySQL 8.0配合Redis缓存。源码包(编号35789)包含了完整的可运行项目,从用户认证、车辆定位到订单支付的全套功能实现。
这个系统的核心价值在于:
- 完整实现了共享单车业务的核心流程:扫码开锁、计费结算、车辆定位等
- 采用微信小程序作为载体,无需安装独立APP,用户使用门槛低
- SpringBoot后端设计考虑了高并发场景下的稳定性问题
- 包含管理员后台用于车辆调度和运营数据分析
提示:虽然项目名称为"天府自行车",但架构设计适用于任何城市的共享单车系统,只需调整地图API和业务参数即可快速部署
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构详解
2.1 后端SpringBoot设计
后端采用经典的三层架构:
code复制controller(Web层)
├── service(业务逻辑层)
│ ├── mapper(数据持久层)
│ ├── util(工具类)
│ └── config(配置类)
└── exception(异常处理)
关键依赖配置(pom.xml节选):
xml复制<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
2.2 微信小程序前端架构
小程序采用模块化开发结构:
code复制pages/
├── index/ # 首页地图展示
├── scan/ # 扫码功能
├── wallet/ # 钱包支付
└── my/ # 个人中心
components/
├── bike-marker/ # 自定义地图标记
└── timer/ # 骑行计时器
特别处理了微信API的异步调用问题,采用Promise封装:
javascript复制// utils/wxPromise.js
const wxPromise = (api, options) => {
return new Promise((resolve, reject) => {
wx[api]({
...options,
success: resolve,
fail: reject
})
})
}
3. 核心功能实现
3.1 车辆定位与地图展示
使用腾讯地图微信小程序SDK实现:
- 获取用户当前位置权限
- 从后端API获取周边车辆数据
- 渲染自定义marker
javascript复制// pages/index/index.js
Page({
data: {
markers: [{
id: 1,
latitude: 30.674,
longitude: 104.067,
iconPath: '/images/bike.png',
width: 30,
height: 30
}]
},
onLoad() {
this.getLocation()
}
})
后端对应的GeoHash查询:
java复制// BikeServiceImpl.java
public List<Bike> findNearbyBikes(double lat, double lng, int radius) {
String geoHash = GeoHashUtils.encode(lat, lng);
return bikeMapper.selectByGeoHash(geoHash.substring(0, 6));
}
3.2 扫码开锁流程
- 小程序调用wx.scanCode获取车辆二维码信息
- 解析出车辆ID后调用开锁API
- 后端通过MQTT协议与智能锁通信
java复制// BikeUnlockController.java
@PostMapping("/unlock")
public Result unlock(@RequestParam String bikeId,
@RequestHeader("token") String token) {
// 1. 验证用户权限
// 2. 检查车辆状态
// 3. 发送开锁指令
mqttService.publish("/lock/" + bikeId, "unlock");
// 4. 创建骑行订单
return Result.success(orderService.createOrder(bikeId, token));
}
注意:实际生产环境需要考虑蓝牙直连方案作为备用通道,避免完全依赖网络通信
4. 支付与订单系统
4.1 微信支付集成
采用V3版微信支付接口,关键步骤:
- 后端生成预支付订单
- 小程序调起支付界面
- 异步通知处理
支付流程时序图:
code复制小程序 -> 后端: 创建支付订单
后端 -> 微信支付: 统一下单
微信支付 -> 后端: 返回prepay_id
后端 -> 小程序: 返回支付参数
小程序 -> 微信支付: 调起支付
微信支付 -> 小程序: 支付结果
微信支付 -> 后端: 异步通知
4.2 计费规则实现
采用策略模式设计计费规则:
java复制public interface BillingStrategy {
BigDecimal calculate(long duration);
}
// 分段计费实现
public class SectionBilling implements BillingStrategy {
@Override
public BigDecimal calculate(long seconds) {
if (seconds <= 1800) { // 30分钟内
return new BigDecimal("1.5");
} else {
return new BigDecimal("1.5")
.add(new BigDecimal(seconds - 1800)
.divide(new BigDecimal(3600), 2, RoundingMode.UP)
.multiply(new BigDecimal("1")));
}
}
}
5. 项目部署与运维
5.1 多环境配置
SpringBoot的application.yml配置示例:
yaml复制spring:
profiles:
active: @profileActive@
---
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/bike_dev
username: devuser
password: dev123
---
spring:
profiles: prod
datasource:
url: jdbc:mysql://prod-db:3306/bike_prod
username: ${DB_USER}
password: ${DB_PASS}
5.2 微信小程序发布流程
- 开发版本:开发者工具调试
- 体验版本:配置体验者白名单
- 提交审核:准备各项资质材料
- 线上发布:审核通过后发布
避坑指南:小程序类目必须选择"出行与交通-共享交通工具",否则会被驳回
6. 源码分析与扩展建议
6.1 关键代码解析
车辆状态同步的WebSocket实现:
java复制@ServerEndpoint("/ws/bike/{bikeId}")
@Component
public class BikeWebSocket {
@OnOpen
public void onOpen(@PathParam("bikeId") String bikeId,
Session session) {
// 将session与车辆ID关联
}
@OnMessage
public void onMessage(String message, Session session) {
// 处理锁状态变更消息
}
}
6.2 性能优化实践
- 车辆查询缓存:
java复制@Cacheable(value = "bike", key = "#geoHash")
public List<Bike> getBikesByGeoHash(String geoHash) {
return bikeMapper.selectByGeoHash(geoHash);
}
- 使用Redisson分布式锁处理并发开锁:
java复制RLock lock = redissonClient.getLock("bike:lock:" + bikeId);
try {
if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
// 处理开锁逻辑
}
} finally {
lock.unlock();
}
7. 常见问题解决方案
7.1 微信登录失败处理
典型错误代码及解决方案:
| 错误码 | 原因 | 解决方案 |
|---|---|---|
| 40029 | code无效 | 检查appsecret是否正确,code是否重复使用 |
| 45011 | API调用太频繁 | 增加请求间隔,客户端做请求合并 |
| 41008 | 缺少code参数 | 检查wx.login()调用是否成功 |
7.2 地图显示异常
可能原因及排查步骤:
- 检查小程序后台是否配置了合法域名
- 确认腾讯地图key是否正确
- 测试基础库版本是否兼容
- 检查用户是否授权地理位置权限
8. 项目扩展方向
基于现有架构可以进一步实现:
- 骑行轨迹记录:使用MySQL LineString类型存储
- 优惠券系统:结合Redis实现秒杀功能
- 车辆调度算法:基于k-means聚类分析
- 智能推荐停车点:使用协同过滤算法
我在实际部署中发现,车辆定位精度对用户体验影响很大。建议采用GPS+蓝牙信标+WiFi指纹的混合定位方案,可以将定位误差控制在3米以内。另外,高峰时段的订单并发处理需要特别注意,我们通过消息队列削峰和数据库读写分离,成功支撑了每秒300+的开锁请求。
