
简介一套面向高校毕业设计的民宿短租微信小程序系统基于微信小程序与SSM框架MySQL数据库开发针对出差旅游人群的短租住宿需求实现了民宿信息线上展示、在线预订、订单管理等核心业务缓解传统中介费高、信息不透明等问题适合计算机相关专业学生作为课程设计或毕设参考。压缩包共有996个文件、整体约38.58MB主要包含Java后端源码、Vue管理页面、微信小程序前端、SQL数据库脚本、毕业论文文档以及mp4操作演示视频其中png、svg等素材用于界面图标与页面美化配置文件与批处理脚本可辅助快速部署运行。当前已有335人学习下载资料整理较完整可直接用于答辩准备或二次开发。整套资源同时提供源码、数据库、论文和视频演示能帮助理解SSM与小程序的前后端交互流程系统按用户、房主、管理员三类角色划分功能模块配合演示视频可快速掌握民宿预订业务逻辑降低毕设服务端开发门槛便于实现民宿短租场景下的完整业务流程。1. 民宿短租小程序毕业设计选它论文和演示都省心大学毕设选题最怕选一个“老师听过但你讲不深”的项目民宿短租小程序恰好是个例外微信小程序做用户端下单和房源浏览SSM提供后端接口MySQL存业务数据三条技术线正好覆盖前端、后端、数据库三个评审关注点。和传统图书管理系统、购物商城相比“短租”场景有按晚计价、日期重叠校验、订单状态流转这些足够展开的业务细节论文里能写的东西多代码量又控制在一个学期能完成的范围内。适合有Java基础但不想碰高并发和中间件的学生也适合在职想补一个可演示作品的人。这篇文章按我从零搭这套项目的顺序写环境、建表、接口、避坑都在里面想照着复现或改造成自己的毕设看这一篇足够。2. SSM 微信小程序 MySQL这套组合为什么是毕设的安全牌2.1 SpringSpringMVCMyBatis三个框架到底在干什么SSM不是单个框架而是三个框架的分工组合。Spring管对象创建、依赖注入和事务SpringMVC管HTTP请求的路由和响应MyBatis管SQL映射。以“用户点击登录”为例请求先进SpringMVC的DispatcherServlet由HandlerMapping找到对应的Controller方法Controller调用Service层做业务判断Service再通过Mapper接口找到XML里的SQL语句查询结果逐层返回。这个链路看起来长但每一层都职责单一答辩时老师问“你这个系统怎么分层的”你能从请求入口一路讲到SQL执行这种能讲清楚的状态在答辩现场很加分。毕设选SSM而不是Spring Boot核心原因是Spring Boot把大部分配置自动化了论文里能写的原理反而变少。SSM的applicationContext.xml、spring-mvc.xml、mybatis-config.xml都是自己一个个配置出来的每个bean、每个mapper扫描路径都亲手调过这意味着你在论文的“系统实现”章节里有真实素材可写而不是对着Spring Boot自动配置说“框架帮我们做好了”。版本选择上我建议JDK 1.8配合Spring 5.1.x、MyBatis 3.5.x、Tomcat 8.5这套组合踩坑率最低。Spring 6和JDK 17在Tomcat 9上也能跑但Servlet版本、Jackson兼容性、CGLIB代理这些细碎问题会在答辩前突然冒出来别给自己加难度。2.2 微信小程序前端原生框架足够不必再套一层民宿短租小程序要做的页面无非是首页房源列表、房源详情、订单列表、个人中心再加一个登录页。微信小程序原生提供的WXML、WXSS、JS、JSON四件套完全覆盖这些场景不需要为“代码更优雅”引入uni-app或第三方组件库。原生写法在微信开发者工具里调试最快报错时堆栈定位最直接导出源码给老师检查也最容易看懂。小程序的页面结构是每个页面由四个同名文件组成pages/index/index.wxml管模板index.wxss管样式index.js管逻辑index.json管页面级配置。页面跳转用wx.navigateTo数据请求用wx.request本地存储用wx.setStorageSync这算是小程序开发的“最小技能包”。把这三个API用熟民宿短租这种体量的项目能很快写完。登录方案我建议尽量简单账号密码登录后端校验通过后返回一个token小程序端存到storage里。不要为了显得高级引入微信授权登录的完整流程个人开发者的小程序里wx.login换openid需要再调后端接口学生没有AppSecret管理的经验反而容易把密钥泄露到前端静态代码里。账号密码登录在论文里也有得写可以加MD5加密存储和token过期机制足够凑一章“系统安全设计”。2.3 MySQL表设计短租业务最少需要哪几张表短租业务的核心对象有三个用户、民宿、订单。用户表要区分普通用户和房东因为房东要能管理自己发布的房源民宿表要有价格、地址、封面图、上下架状态订单表要记录入住日期、退房日期、晚数、总价和订单状态。评价表挂在订单下方便按房源查评价、按用户查评价。要不要收藏表看你的论文工作量如果觉得“核心功能太少”加一个收藏功能能补不少页面。字段类型有几个容易踩坑的地方价格用decimal(10,2)而不是float日期用date而不是varchar描述类文本用text。民宿图片不要往数据库里存二进制存相对路径字符串图片文件放到服务器磁盘目录里。这样表体量小迁移时也方便论文里还能写一段“为什么不在数据库存图片”的对比分析这属于送分内容。3. 从空环境到跑通登录民宿短租小程序的初始化全过程3.1 环境版本搭配JDK、Maven、Tomcat、MySQL怎么选我在复现这类项目时用的组合是JDK 1.8、Maven 3.6.3、Tomcat 8.5、MySQL 5.7。MySQL 5.7的安装配置教程比较多连接驱动用mysql-connector-java 5.1.49基本不会遇到SSL和认证问题。如果你装的是MySQL 8.0驱动版本至少8.0.20以上连接串里还要为useSSL、allowPublicKeyRetrieval、serverTimezone做额外配置这些参数缺一个就启动报错网上大量“mysql ssl连接错误”都是这个阶段出现的。Maven安装后先检查settings.xml里有没有配好镜像仓库。很多新人pom.xml写得没问题但依赖一直下载失败最后发现是Maven默认中央仓库访问缓慢换成镜像后几分钟全部解决。这个不起眼的步骤能省下大量焦虑时间属于“早做早享受”的典型操作。前端工具单独装微信开发者工具稳定版导入项目时目录指向小程序前端代码文件夹。建议仓库结构分成miniprogram和server两个平级目录前端目录给微信开发者工具打开后端Maven工程用IDEA打开两个IDE各管一端。后端代码里的上传图片目录、日志目录不要提交到Git仓库用.gitignore排除掉否则别人clone下来跑的时候会因为缺目录而翻车。3.2 建库建表SQL用户、房源、订单、评价表的结构数据库名建议直接叫homestay字符集用utf8mb4。房源标题、评价内容都可能出现表情符号utf8mb4才能完整存下来这也是比utf8更稳妥的选择。下面是核心表结构中我会反复确认的几个部分先建用户表和民宿表CREATE DATABASE IF NOT EXISTS homestay DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE homestay; CREATE TABLE user ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL COMMENT 登录名, password VARCHAR(100) NOT NULL COMMENT MD5后的密码, nickname VARCHAR(50) DEFAULT NULL, phone VARCHAR(20) DEFAULT NULL, avatar VARCHAR(255) DEFAULT NULL, role TINYINT NOT NULL DEFAULT 0 COMMENT 0普通用户 1房东 2管理员, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB COMMENT用户表; CREATE TABLE house ( id INT NOT NULL AUTO_INCREMENT, landlord_id INT NOT NULL COMMENT 房东用户ID, title VARCHAR(100) NOT NULL, description TEXT, price DECIMAL(10,2) NOT NULL COMMENT 每晚价格, address VARCHAR(255) NOT NULL, cover VARCHAR(255) DEFAULT NULL COMMENT 封面图相对路径, images VARCHAR(2000) DEFAULT NULL COMMENT 多图逗号分隔, status TINYINT NOT NULL DEFAULT 1 COMMENT 1上架 0下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_landlord (landlord_id) ) ENGINEInnoDB COMMENT民宿房源表;这段SQL里username加了唯一索引是为了防止重复注册landlord_id加普通索引是因为“查某房东名下所有房源”的频率很高不加索引在数据量上来后会变慢。create_time用DATETIME DEFAULT CURRENT_TIMESTAMP插入时不用手动赋值省掉一层逻辑。订单表要特别注意order是MySQL的保留字直接CREATE TABLE order会报错必须用反引号包起来。订单号要单独建唯一索引业务上用它做幂等校验避免用户重复点击下单时插入两条记录。CREATE TABLE order ( id INT NOT NULL AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL COMMENT 业务订单号, user_id INT NOT NULL, house_id INT NOT NULL, check_in_date DATE NOT NULL, check_out_date DATE NOT NULL, nights INT NOT NULL COMMENT 入住晚数, total_price DECIMAL(10,2) NOT NULL, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待支付 1已支付 2已入住 3已完成 -1已取消, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_user (user_id), KEY idx_house (house_id) ) ENGINEInnoDB COMMENT民宿订单表;订单状态我用数字而不是字符串理由是Java枚举和SQL都能直接比较查询效率高论文里用一张状态表说明0到3分别代表什么即可。总价由每晚价格乘以晚数得到不要在数据库里加触发器算业务层的BigDecimal更可控。3.3 跑通第一个登录接口Controller到Mapper的完整链路项目结构搭好后先跑通登录接口因为登录涉及前端传参、后端校验、数据库查询、结果返回一条链能覆盖80%的框架配置问题。后端先建UserMapper接口和UserMapper.xmlpublic interface UserMapper { User selectByUsernameAndPassword(Param(username) String username, Param(password) String password); }XML里对应SQLselect idselectByUsernameAndPassword resultTypecom.demo.entity.User SELECT id, username, nickname, phone, avatar, role FROM user WHERE username #{username} AND password #{password} /selectController层接收JSON参数调用Service结果封装成统一Result对象。密码存库前先MD5毕设用MD5加盐也能接受但论文里要写明为什么不存明文。统一Result对象里至少要有code、message、data三个字段小程序端判断code等于200再取数据这个约定后面所有接口都复用。RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; PostMapping(/login) public Result login(RequestBody User loginUser) { User user userService.login(loginUser.getUsername(), loginUser.getPassword()); if (user null) { return Result.error(用户名或密码错误); } return Result.success(user); } }小程序端登录按钮触发wx.request把表单数据POST到后端。url里如果写localhost开发者工具模拟器能通但真机预览时不行需要改成电脑的局域网IP。这一块的完整排查方法在第5章细讲这里先让模拟器跑通。wx.request({ url: http://127.0.0.1:8080/api/user/login, method: POST, data: { username: this.data.username, password: this.data.password }, header: { Content-Type: application/json }, success(res) { if (res.data.code 200) { wx.setStorageSync(token, res.data.data.token); wx.switchTab({ url: /pages/index/index }); } } });注意header里的Content-Type要与后端接收方式匹配。后端用RequestBody就必须是application/json用RequestParam就得换成application/x-www-form-urlencoded或直接拼在query里。前后端这个错位是登录接口最常见的对接失败原因。4. 民宿短租核心链路房源筛选、订单日期校验与状态流转4.1 房源列表和详情MyBatis动态SQL与图片相对路径房源列表要支持按城市、价格区间筛选。MyBatis的动态SQL是干这事最顺手的工具前端把筛选条件作为参数传过来XML里用if标签拼SQL条件为空就不加对应片段。select idsearchHouses resultTypecom.demo.entity.House SELECT id, title, price, address, cover, status FROM house where if testcity ! null and city ! AND address LIKE CONCAT(%, #{city}, %) /if if testminPrice ! null AND price gt; #{minPrice} /if if testmaxPrice ! null AND price lt; #{maxPrice} /if AND status 1 /where ORDER BY create_time DESC /selectXML里的小于号必须写成否则XML解析直接报错这是MyBatis新手最容易翻车的地方。where标签会自动去掉第一个多余的AND所有条件为空时会变成WHERE status 1正好符合“只查上架房源”的预期。cover字段存的是相对路径比如“/upload/house/1.jpg”。小程序端不能直接拿这个字符串当图片src需要在后端返回的VO里生成一个完整可访问的图片URL。我一般这样做后端配置一个属性记录访问前缀拼成“http://192.168.1.100:8080/upload/house/1.jpg”后放进VO里前端直接使用避免每个页面都去拼IP和端口。详情页除了显示房源基本信息还要给用户展示“哪些日期不可订”。最简单的方式是后端根据订单表中状态为已支付或已入住且日期区间重叠的记录返回一个不可预订日期数组。数据量小时把订单查出来后用Java算日期区间更直观答辩时也更容易讲清楚。4.2 订单链路创建、取消、支付、入住的状态机民宿短租订单比普通电商订单多一个“实际入住”环节状态流转是待支付(0) → 已支付(1) → 已入住(2) → 已完成(3)任何非终态都可以取消(-1)。真实项目里退款和支付回调很复杂但毕设可以简化成待支付状态的订单直接取消不涉及资金操作已支付订单取消时把状态改成已取消论文里注明“本系统未接入真实支付资金处理环节做了简化”。创建订单时要同时做两件事生成唯一订单号和校验日期是否可订。订单号用时间戳加用户ID加随机数拼成例如SELECT COUNT(*) FROM order WHERE house_id #{houseId} AND status IN (1, 2) AND #{checkIn} check_out_date AND #{checkOut} check_in_date;这段SQL是短租系统最容易写错的地方。日期重叠的判断逻辑是新订单的入住日期小于已有订单的退房日期且新订单的退房日期大于已有订单的入住日期两个条件同时成立表示区间重叠。很多人写成等值判断结果只挡住了完全相同的日期跨天重叠照样能下单。要意识到一个用户的订单可能是前一天入住后一天退房另一个用户想从中间插进来区间判断必须是不等式。创建订单的Service方法要加Transactional。插入订单、校验日期、更新房源状态三个操作必须同生同死否则会出现订单创建成功但日期被重复预订的脏数据。事务是SSM里最便宜的“后悔药”加一个注解就能避免大量数据不一致问题。Transactional public Order createOrder(OrderDTO dto) { // 1. 校验房源存在且上架 // 2. 校验所选日期无重叠订单 // 3. 计算总价 每晚价格 * 晚数 // 4. 生成订单号并插入 return orderMapper.insert(order) 0 ? order : null; }模拟支付在小程序端实现用户点“去支付”弹确认框确认后调用后端接口把状态置为已支付。这里的核心不是支付本身而是支付成功后订单列表要刷新房源的不可订日期要更新这两个前端表现才是答辩时让人觉得“系统完整”的关键。5. 民宿短租小程序常见问题与避坑5个现场排查记录5.1 request连不上本地后端不是代码错是域名校验现象微信开发者工具的模拟器里请求报“不在以下合法域名列表中”真机预览时直接request fail。代码检查过多遍没有语法问题后端接口用Postman能通但小程序就是连不上。原因微信小程序对request域名有校验规则。开发者工具默认开启“校验合法域名”像http://127.0.0.1:8080或局域网IP都不在合法域名列表里。真机预览时手机上的小程序也会执行同样的校验。解决开发者工具右上角“详情→本地设置”勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”。真机预览时把后端接口地址改成电脑的局域网IP手机和电脑连同一个Wi-Fi。要注意这个配置只影响开发调试上线时必须到微信公众平台配置HTTPS合法域名两者不是一回事。5.2 MySQL连接串没配好SSL、公钥检索、时区三类报错一起处理现象项目启动时日志报“Communications link failure”或报“Public Key Retrieval is not allowed”还有时区相关的乱码提示。配置检查了一下午驱动版本也对就是启动不通过。原因MySQL 8.0默认开启SSL驱动没配useSSLfalse会走SSL握手MySQL 8.0的caching_sha2_password插件要求客户端先获取公钥未开启allowPublicKeyRetrievaltrue就报错服务器时区没设成Asia/Shanghai时驱动拿到乱码形式的时区名也会拒绝启动。解决JDBC连接串统一写成下面这样三类问题一次解决jdbc.urljdbc:mysql://localhost:3306/homestay?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue这个配置对MySQL 5.7和8.0都适用。如果用的是5.1.x驱动连MySQL 8.0建议直接升级驱动到8.0.x否则这个报错会时好时坏排查起来很玄学。建议在项目一开始就把连接串按这个标准写好避免后续浪费几小时。5.3 日期时间差8小时数据库、Jackson、前端三处都要改现象订单创建时间在数据库里看是09:00小程序端显示成01:00。或者JSON返回的日期带“00:00”后缀前端new Date()解析后少8小时。原因默认时区是UTC。数据库连接串没指定时区时驱动按服务器时区处理Jackson默认序列化又按UTC输出前端new Date()再按浏览器本地时区转一遍三层叠加就偏移了。解决第一层连接串指定serverTimezoneAsia/Shanghai。第二层实体类日期字段加注解JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private Date createTime;第三层前端拿到格式化字符串后直接展示不要再用new Date()二次转换。三层都对齐了日期就不会漂移。我之前被这个问题折腾过很久后来发现连接串和JsonFormat各漏了一半两处一起改才彻底好。5.4 房源图片白屏404静态资源映射和路径拼接缺一不可现象小程序列表页能看到文字但图片全部裂开。后端日志没有任何异常浏览器直接访问图片URL也返回404。原因图片上传到了本地磁盘目录但SSM工程默认只处理动态请求。SpringMVC没有配置静态资源映射时/upload/xxx.jpg这个路径会被DispatcherServlet接走找不到对应处理器就返回404。解决在spring-mvc.xml里加静态资源映射把磁盘目录暴露成URL路径mvc:resources mapping/upload/** locationfile:D:/homestay/upload/ /同时确认上传代码保存的路径与映射一致。图片存到本地磁盘后数据库存“/upload/house/1.jpg”前端展示时拼上后端IP和端口。如果只是加了映射但数据库存的路径前面多了一层目录同样会404这两个配置是一对要一起检查。5.5 列表刷新闪烁和数据错位setData时机与请求竞态现象首页房源列表下拉刷新时页面先清空再加载明显白闪。快速切换筛选条件时列表数据偶尔和当前条件不匹配。原因下拉刷新回调里先setData把列表清空再等网络请求返回中间产生空白渲染。切换筛选条件时上一次请求还没回来下一次请求又发出去了响应到达顺序不确定最后一次返回的可能是老数据。解决刷新时不清空列表请求成功后整体替换每次请求带上递增的requestSeq响应回来时只处理最新一次refreshList() { const current this.requestSeq; wx.request({ url: http://127.0.0.1:8080/api/house/search, data: this.searchParams, success: (res) { if (current this.requestSeq) { this.setData({ houseList: res.data.data }); } } }); }requestSeq保证只有最后一次请求的响应才会更新页面老请求的响应被丢弃视觉上既不会白闪数据也不会错位。数据量不大时不用分页也能撑住但论文里要提一句“当前演示数据量较小生产环境需分页”给自己留余地。6. 答辩现场别翻车演示顺序、演示数据和验证技巧6.1 演示前先做一次冷启动预演答辩最怕现场卡在环境问题上。我建议演示前把Tomcat、MySQL、微信开发者工具全部从关闭状态启动一遍确认启动顺序和端口占用。Tomcat默认8080端口经常被杀毒软件或残留进程占用启动前用netstat -ano | findstr 8080看一眼。MySQL用命令行登录一次确认服务真的活着别等答辩时才发现图形工具连的是本地另一台机器的数据库。6.2 造一套有故事的演示数据演示数据不要用user1、123456这种一看就是测试的账号。在数据库里造一个带昵称、头像、手机号的房东账号再准备两三条地址真实感强的房源比如“近地铁站的Loft公寓”“带院子的乡村民宿”价格用168、268这种常见短租价位。演示时先在首页搜索“地铁”让筛选效果真实可见再选房下单把待支付改成已支付刷新订单列表看到状态变化。这条链路走通核心功能就齐了。6.3 把论文、源码和视频演示对齐有视频演示时建议分三段录用户端看房下单、房东端管理房源、管理员端查看订单每段两分钟内配一句旁白说明操作目的。论文里的系统测试章节按这三段对应的功能点写测试用例截图直接从演示视频里抽帧。我做这类项目习惯先把演示脚本用Word写好再录视频后面写论文“系统实现”章节时直接对照脚本里的截图和步骤不用返工。希望这个顺序能帮到你也祝答辩顺利。本文还有配套的精品资源点击获取