1. 项目背景与技术选型
在旅游行业数字化转型的浪潮中,景区民宿预约系统成为连接游客与住宿服务的重要纽带。去年我在为某5A级景区开发预约系统时,深刻体会到传统PHP架构在高并发预订场景下的力不从心。经过技术评估,最终选择了SpringBoot+Vue3的全栈方案,这套技术组合在性能、开发效率和可维护性方面展现出明显优势。
SpringBoot 2.7作为后端框架,其内嵌Tomcat容器和自动配置特性让我们在三天内就搭建好了基础REST API。配合MyBatis-Plus 3.5.1,单表CRUD操作代码量减少了60%。前端选用Vue3的组合式API开发模式,配合Element Plus组件库,实现了响应式表单和实时房态看板。数据库采用MySQL 8.0,利用窗口函数优化了热门民宿的排行统计。
关键决策点:放弃JPA选择MyBatis的主要考虑是复杂查询的灵活性。景区预约涉及多表关联(民宿-房型-订单-评价),需要手写优化SQL的场景较多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 前后端分离实践
采用严格的API契约开发模式,使用Swagger 3.0生成交互式文档。前端通过axios封装了带JWT校验的请求拦截器,典型接口响应时间控制在200ms内。为解决跨域问题,后端配置了基于CorsFilter的白名单机制:
java复制@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("https://client-domain.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
2.2 数据库设计要点
民宿系统的核心表包括:
homestay(民宿基础信息)room_type(房型库存)booking_order(订单流水)user(双角色用户体系)
特别注意了库存扣减的并发控制,最终采用MySQL乐观锁+Redis预扣减的方案:
sql复制UPDATE room_type
SET stock = stock - 1
WHERE id = #{roomTypeId} AND stock >= 1
3. 核心功能实现
3.1 预约业务流程
- 房态查询:使用Redis缓存民宿30天内的可预约状态,ZSET结构存储每天剩余房量
- 价格计算:策略模式实现周末/节假日动态定价
- 订单创建:分布式ID生成器保证订单号全局唯一
- 支付回调:支付宝沙箱环境集成,处理幂等回调
关键代码片段:
java复制@Transactional
public BookingResult createBooking(BookingDTO dto) {
// 1.校验库存
RoomType roomType = roomTypeMapper.selectForUpdate(dto.getRoomTypeId());
if (roomType.getStock() < 1) {
throw new BusinessException("房源已售罄");
}
// 2.创建订单
BookingOrder order = new BookingOrder();
order.setOrderNo(SnowFlake.nextId());
orderMapper.insert(order);
// 3.扣减库存
roomTypeMapper.deductStock(dto.getRoomTypeId());
// 4.发起支付
return new BookingResult(order.getOrderNo());
}
3.2 可视化房态管理
前端使用ECharts实现三维房态日历,通过WebSocket推送实时预订数据。核心难点在于处理时区转换,最终采用day.js库统一处理:
javascript复制const calendarData = computed(() => {
return props.rawData.map(item => ({
date: dayjs(item.date).format('YYYY-MM-DD'),
status: item.status
}))
})
4. 性能优化实践
4.1 缓存策略
采用多级缓存架构:
- 热点数据:Redis缓存民宿详情(TTL 5分钟)
- 静态资源:Nginx启用Brotli压缩
- CDN加速:图片等大文件走阿里云OSS
4.2 数据库优化
- 为
check_in_date和homestay_id创建复合索引 - 大文本字段(如民宿描述)拆分成单独表
- 配置连接池参数(最大连接数=CPU核心数*2 + 有效磁盘数)
5. 安全防护措施
- XSS防御:前端使用DOMPurify过滤富文本,后端配合@RequestBody注解
- CSRF防护:SameSite Cookie策略+关键操作二次验证
- SQL注入:MyBatis严格使用#{}占位符
- 敏感数据:手机号等字段AES加密存储
6. 部署与监控
采用Docker Compose编排服务:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- ./mysql-data:/var/lib/mysql
backend:
build: ./springboot
ports:
- "8080:8080"
depends_on:
- mysql
frontend:
build: ./vue3
ports:
- "80:80"
通过Prometheus+Grafana监控QPS和响应延迟,特别关注库存扣减接口的99线指标。
7. 踩坑与解决方案
- Vue3 Edge浏览器兼容性问题:禁用Edge的效率模式后解决
- MyBatis分页插件冲突:排除PageHelper自带count查询
- SpringBoot PDF导出XSS漏洞:强制设置Content-Disposition头
- MySQL连接池耗尽:调整wait_timeout与连接验证查询
项目上线后平稳支撑了黄金周单日10万+访问量,关键经验是:提前用JMeter做全链路压测,数据库预留30%性能余量。现在回看,如果采用ShardingSphere做水平分表会更利于长期扩展
