1. 项目概述:SpringBoot民宿租赁系统开发实录
去年帮朋友改造民宿业务时,我基于SpringBoot开发了一套完整的租赁管理系统。这个系统不仅实现了房源展示、在线预订等基础功能,还针对民宿行业特有的灵活定价、多房态管理等需求做了深度优化。系统上线后订单处理效率提升60%,今天就把这个经过实战检验的方案完整分享给大家。
2. 核心架构设计
2.1 技术栈选型
- 后端:SpringBoot 2.7 + MyBatis-Plus
- 前端:Thymeleaf + Bootstrap5
- 数据库:MySQL 8.0(考虑事务完整性和复杂查询)
- 缓存:Redis 6(应对节假日流量高峰)
- 支付:支付宝沙箱环境(正式环境需企业资质)
特别注意:民宿系统与酒店系统的本质区别在于房态管理的灵活性,传统酒店PMS系统往往无法满足民宿日租、钟点房等特殊需求
2.2 数据库设计要点
sql复制CREATE TABLE `house` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL COMMENT '房源标题',
`price` decimal(10,2) NOT NULL COMMENT '基础价格',
`dynamic_pricing` tinyint(1) DEFAULT '0' COMMENT '是否开启动态定价',
`status` tinyint NOT NULL COMMENT '0-待审核 1-已上架 2-已下架',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `house_schedule` (
`id` bigint NOT NULL AUTO_INCREMENT,
`house_id` bigint NOT NULL,
`day` date NOT NULL COMMENT '日期',
`price` decimal(10,2) NOT NULL COMMENT '当日价格',
`status` tinyint NOT NULL COMMENT '0-可订 1-已订 2-维修',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_house_day` (`house_id`,`day`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 关键业务实现
3.1 动态定价算法
java复制public BigDecimal calculateDynamicPrice(LocalDate date) {
// 基础价格
BigDecimal basePrice = house.getBasePrice();
// 周末溢价20%
if(date.getDayOfWeek().getValue() >= 6) {
basePrice = basePrice.multiply(new BigDecimal("1.2"));
}
// 节假日溢价(需提前配置节假日表)
if(holidayService.isHoliday(date)) {
basePrice = basePrice.multiply(new BigDecimal("1.5"));
}
// 提前预订折扣
long daysBefore = ChronoUnit.DAYS.between(LocalDate.now(), date);
if(daysBefore > 30) {
basePrice = basePrice.multiply(new BigDecimal("0.9"));
}
return basePrice.setScale(2, RoundingMode.HALF_UP);
}
3.2 房态冲突检测
采用时间区间重叠检测算法,确保同一房源不会重复预订:
java复制@Transactional
public boolean checkConflict(Long houseId, LocalDate start, LocalDate end) {
return orderMapper.exists(
new QueryWrapper<Order>()
.eq("house_id", houseId)
.and(wrapper -> wrapper
.between("start_date", start, end)
.or()
.between("end_date", start, end)
.or()
.le("start_date", start).ge("end_date", end)
)
.ne("status", OrderStatus.CANCELED.getValue())
);
}
4. 特色功能实现
4.1 智能门锁对接
通过HTTP API与主流智能门锁厂商对接:
java复制public String generateDoorCode(Long orderId) {
Order order = orderMapper.selectById(orderId);
String randomCode = RandomStringUtils.randomNumeric(6);
// 调用门锁厂商API
DoorLockRequest request = new DoorLockRequest();
request.setDeviceId(order.getHouse().getLockDeviceId());
request.setStartTime(order.getStartDate().atStartOfDay());
request.setEndTime(order.getEndDate().atTime(23,59));
request.setCode(randomCode);
DoorLockResponse response = restTemplate.postForObject(
lockConfig.getApiUrl(), request, DoorLockResponse.class);
if(response.getSuccess()) {
return randomCode;
}
throw new BusinessException("门锁密码生成失败");
}
4.2 清洁工单系统
自动生成清洁任务并分配:
java复制@Scheduled(cron = "0 0 12 * * ?") // 每天中午12点检查
public void autoGenerateCleanTasks() {
// 查询今天退房的订单
List<Order> checkoutOrders = orderMapper.selectList(
new QueryWrapper<Order>()
.eq("end_date", LocalDate.now())
.eq("status", OrderStatus.COMPLETED.getValue())
);
checkoutOrders.forEach(order -> {
CleanTask task = new CleanTask();
task.setHouseId(order.getHouseId());
task.setPriority(order.getGuestCount() > 4 ? 1 : 2);
task.setStatus(0);
cleanTaskMapper.insert(task);
// 微信通知清洁人员
wxPushService.sendCleanNotice(task.getId());
});
}
5. 部署与优化
5.1 高并发场景应对
- 使用Redis缓存热门房源信息
- 采用分布式锁处理库存扣减
- 订单表按月份分表(house_order_202307)
java复制public boolean lockHouse(Long houseId, LocalDate date) {
String lockKey = "house:lock:" + houseId + ":" + date;
return redisTemplate.opsForValue().setIfAbsent(
lockKey, "1", Duration.ofMinutes(15));
}
5.2 安全防护措施
- 接口防刷:Guava RateLimiter限流
- XSS过滤:自定义HttpServletRequestWrapper
- SQL注入:MyBatis严格参数绑定
- 敏感数据加密:Jasypt加密配置文件
6. 踩坑实录
- 时区问题:务必在启动参数添加
-Duser.timezone=GMT+08 - 日期比较:MySQL日期字段建议使用
DATE类型而非DATETIME - 金额计算:BigDecimal必须使用String构造器避免精度丢失
- 微信支付回调:内网穿透调试时注意签名验证
- 房源图片存储:建议使用OSS而非本地存储
7. 扩展建议
- 增加智能电表对接实现能耗统计
- 接入公安系统身份证核验
- 开发房东APP端(可考虑Uniapp跨平台方案)
- 实现房源收入统计与分账功能
- 增加智能客服自动回复常见问题
系统源码已整理在GitHub仓库(搜索94985即可找到),包含完整的Docker部署脚本和API文档。实际开发中最大的体会是:民宿系统必须考虑极端场景下的房态管理,比如客人续住、提前退房等情况,我们的解决方案是采用"房态日历+操作日志"的双重机制来保证数据一致性。