简介:面向计算机相关专业毕业生的家政服务管理系统毕业设计项目,基于Java、SSM框架、MySQL数据库与微信小程序开发,下载即可运行,适合毕业设计、课程设计或期末大作业。压缩包共1213个文件,总大小16.41MB,内容涵盖Java后端源码、Vue后台管理页面、微信小程序WXML/WXSS/JS前端、SQL数据库脚本、论文文档及部署工具,前后端代码完整,配合IDEA、微信开发者工具与Maven即可快速搭建运行环境。已有85人学习下载。系统采用Spring、SpringMVC、MyBatis分层架构,小程序端实现家政服务浏览、在线预约、订单管理等核心功能,后台具备完善的业务管理模块,整体界面美观、操作简单、管理便捷。源码经过严格调试,附带数据库表结构与Navicat工具配置,可直接部署,配套的导师指导论文也为毕业设计撰写和二次开发提供了良好参考。
1. 一个成体系的毕设,比一坨能跑的代码值钱
打开这个压缩包之前,你大概率已经看过很多“秒杀项目”“瑞吉外卖”“尚硅谷”之类的教程型仓库。那些东西用来练手没问题,但用来交毕业设计,答辩老师第一句话可能就是“这项目里哪些是你写的”。而这个标题里的信息量比普通练手项目大得多:java+ssm+mysql+微信小程序四层结构,外加源码+数据库+论文三件套,直接对应毕业设计最看重的“系统完整度”和“文档支撑度”。换句话说,这不是一个只教你写接口的 demo,而是一个把前端小程序、后端服务、数据库设计和论文写作绑在一起的整体方案。
家政服务这个选题本身也有讲究:它不像电商、博客那样烂大街,需求清晰(用户下单、阿姨接单、后台管理),业务闭环完整,非常容易画出功能结构图和数据流图。整篇我会从架构选型、数据库表设计、后端代码结构、小程序联调、以及你真正会踩的坑五个方向往下拆,全程偏实战。适合两类人:一类是还没开题、想找一个稳妥方向的在校生,另一类是正在做 SSM 项目但被前端小程序折腾到想换技术栈的自学者。
2. SSM + 小程序为什么还是毕设主流:选型逻辑与整体架构
2.1 SSM 过气了吗:面试八股文的含金量不止在考试
网上现在一提 SSM 就有声音说这是“上古框架”,这话对,也不对。Spring Boot 确实把 SSM 的配置繁琐问题解决掉了,但在校招面试里,SSM 仍然是 Java 基础、框架原理、MVC 运转机制这三块面试题的高频载体。你投简历时写“熟悉 Spring Boot”的人满大街,写“熟悉 SSM 整合原理、能说清 DispatcherServlet 与 MyBatis SqlSession 的生命周期”反而更让面试官相信你是真写过代码。
另外一个现实因素是学校。很多院校软件工程和计算机专业的毕业设计模板仍然要求使用 SSM 架构,答辩老师对这套技术栈的熟悉程度远高于 Spring Cloud 那套微服务全家桶。你用 SSM 做出来的东西,老师改起来方便,提问也更容易落在“你项目中事务怎么控制”“MyBatis 查缓存命中了吗”这种可回答的问题上。所以从拿高分角度说,SSM 不但没过气,它反而是让你能在答辩现场讲清楚的安全牌。
2.2 家政项目的三条链路:用户端、服务端、管理端
家政小程序区别于普通 CRUD 项目的地方在于它有明显的角色权限边界。用户端要的是“找阿姨→下单→支付→评价”这条顺畅链路;管理端要的是“审核阿姨→管理订单→处理投诉”这条运营链路;而服务端要保证的是两条链路之间的数据同步不能出乱子。
我一般会把这三种角色拆成三种表结构上的区分而不是三个独立应用。用户端直接走微信小程序的wx.login静默登录后绑定 openid;管理员端直接在 PC 上访问 SSM 后台的 JSP 页面;阿姨端在毕设里通常简化处理为“管理员在后台手动派单”,不做独立小程序端。这样既保留了业务复杂度,又把工作量控制在一个人能完成的范围内,论文也能多写一节“多角色权限控制的实现方案”。
2.3 源码目录结构:拿到压缩包后先看什么
一个规范的家政毕设源码包,解压后至少应该看到这样的目录骨架:
housekeeping/ ├── src/main/java # 后端 Java 源码 │ ├── controller # 控制层,接收小程序 HTTP 请求 │ ├── service # 业务层,事务边界在这层控制 │ ├── mapper # MyBatis 数据访问接口 │ └── model/entity # 实体类,与数据库表对应 ├── src/main/resources │ ├── spring-mvc.xml # Spring MVC 配置 │ ├── spring-mybatis.xml # MyBatis 数据源与会话工厂配置 │ └── jdbc.properties # 数据库连接配置 ├── src/main/webapp │ ├── pages/js/css # 后台管理端的 JSP 页面 │ └── WEB-INF/web.xml # 前端控制器与字符编码过滤器 ├── sql/housekeeping.sql # 建库建表脚本 + 初始数据 └── 微信小程序源码 ├── pages/index # 首页、服务列表 ├── pages/order # 下单页、订单列表 ├── utils/request.js # 小程序 HTTP 请求封装 └── app.js # 全局配置与登录逻辑拿到源码后先不要急着跑,按上面这个目录确认三件事:jdbc.properties里数据库账号密码是不是本地环境,sql目录下有没有建表脚本,以及小程序源码里的app.js中请求域名是不是指向localhost。这三个点确认完,项目八成能跑起来。
3. 数据库设计是高分论文的第一道分水岭:家政业务表拆解
3.1 核心五表:用户、阿姨、服务类型、订单、评价
家政项目的数据表不求多,但每张表都要扛住业务问题。我见过很多翻车的毕设,表建了十几张,一问“订单退款时状态怎么流转”就答不上来。真正核心的是五张表,其余的都是从这五张向外延伸。
用户表(user):字段上要特别区分openid与session_key,openid 是用户的唯一身份标识,session_key 用于解密用户手机号等敏感信息,按要求不能直接入库存储。阿姨表(worker):除了姓名、手机号之外,把service_type_id单独关联到服务类型表,避免把“保洁”“月嫂”“陪护”这类服务类型硬编码在业务代码里。订单表(order)是整套业务的重心,状态字段设计成:
| 状态码 | 含义 | 对应操作 |
|---|---|---|
| 0 | 待接单 | 用户提交订单后等待后台派单 |
| 1 | 服务中 | 管理员确认阿姨接单 |
| 2 | 已完成 | 阿姨提交完成,等待用户确认 |
| 3 | 已取消 | 用户超时未确认或主动取消 |
| 4 | 退款中 | 用户投诉后进入售后流程 |
状态机流转要能在论文里画一张图。答辩老师看到状态字段而不是简单的字符串“进行中”,印象分会明显不同。评价表(comment)单独拆出来关联order_id,这样用户可以对一次服务进行多次追问或追评,避免把评价内容直接塞进订单表导致字段爆炸。
3.2 支付宝式“冗余”设计:为什么我推荐加 price_snapshot
毕设数据库设计有个常见误区:为了省事,订单表里只存service_id,价格需要实时关联服务类型表去查。这在单机开发时没问题,但答辩老师一句“如果管理员改了服务定价,历史订单怎么追溯?”就能把你问住。
我用得比较多的方案是加price_snapshot字段,下单那一刻把服务单价冗余进订单表。这个操作看着与数据库三大范式冲突,实际上却符合“查询频繁的字段做冗余是合理设计”的工程惯例。订单表里记录下单时的服务名、单价甚至阿姨姓名,虽然重复存储,却让小程序端的订单列表不用连查多张表,一次 SQL 就能拼出全部展示字段。再说了,支付金额以快照为准而不是以当前价格为准,这个逻辑放在任何真实系统里都站得住脚。
3.3 SQL 脚本导入的坑: utf8mb4 和 sql_mode
压缩包里给出的housekeeping.sql文件,导入时最容易踩两个坑。第一个是字符集,如果 MySQL 版本高于 5.7,建表语句里没有显式指定DEFAULT CHARSET=utf8mb4,小程序端传进来的中文表情(比如用户备注里打个“😄”)就会写入失败或者变成问号。建议拿到脚本第一时间全局搜索一遍ENGINE=InnoDB,在后面手动补上DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci。
第二个是sql_mode。NO_ZERO_DATE 和 ONLY_FULL_GROUP_BY 这两个模式在新版 MySQL 默认开启,而很多毕设脚本里日期字段写了'0000-00-00 00:00:00'作为默认值,导入直接报错。解决办法是在 MySQL 配置文件里把这俩模式关掉,或者更干净的方案是把默认值改成CURRENT_TIMESTAMP。导入前用SELECT VERSION();看一眼 MySQL 版本,版本不同处理方式完全不一样,这一步能省下你半小时的玄学排查时间。
4. 从零跑通全链路:后端接口 + 小程序页面 + 数据库联调
4.1 用 Maven 把 SSM 项目跑成 Web 服务
假设你已经把源码解压到本地并确认了 JDK 1.8 和 Tomcat 8.5 这个经典组合。JDK 不要用 17,SSM 项目的兼容性会让你怀疑人生——Spring 老版本框架在 JDK 9+ 上反射机制会发生不可预期行为,最常见的就是IllegalAccessError直接抛在启动阶段。用 JDK 1.8 是毕设环境下的唯一正确解。
确认环境后,在 IDEA 中打开项目根目录的pom.xml,等待 Maven 把依赖拉完,然后构建 war 包:
mvn clean package -DskipTests构建成功后会在target/目录下生成housekeeping.war,把它丢到 Tomcat 的webapps/目录下启动。启动完成后浏览器访问http://localhost:8080/housekeeping/,能看到后台管理端的登录页说明后端已经正常运转。这时候回到 IDEA 里的jdbc.properties确认连接串:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/housekeeping?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=你的本地数据库密码注意serverTimezone=Asia/Shanghai必须有,否则 MySQL 8.x 连接时会直接抛The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized。这行报错每年都要拦下一大批人,看到乱码不要慌,不是数据库坏了,只是时区参数没配。
4.2 MyBatis 订单查询:从表 join 到 VO 返回
拿到了数据库结构和后端框架,接下来要把订单数据真正变成小程序页面能用的 JSON。这里涉及 SSM 项目里最常见的操作:多表联查 + 自定义 VO 字段。先看 Mapper 接口的定义:
public interface OrderMapper { List<OrderVO> selectOrderList(@Param("userId") Integer userId, @Param("status") Integer status); }返回的不是Order实体类,而是OrderVO,因为小程序端订单列表要展示服务名称、阿姨头像、评价状态等跨表信息。对应 XML 里的写法:
<select id="selectOrderList" resultType="cn.edu.housekeeping.vo.OrderVO"> SELECT o.id AS orderId, o.order_sn AS orderSn, o.price_snapshot AS price, o.status AS status, o.create_time AS createTime, w.worker_name AS workerName, w.avatar AS workerAvatar, s.service_name AS serviceName FROM `order` o LEFT JOIN worker w ON o.worker_id = w.id LEFT JOIN service_type s ON o.service_type_id = s.id <where> <if test="userId != null"> AND o.user_id = #{userId} </if> <if test="status != null"> AND o.status = #{status} </if> </where> ORDER BY o.create_time DESC </select>这里的核心编程思路是:先确定页面要展示什么,再倒推 SQL 需要查出什么字段。不要一条 SQL 查两张表都不 join,然后在 Java 代码里 for 循环逐条查数据库填字段——那是新手最容易犯的性能错误,也是答辩老师最常挑的毛病。SQL 直接 join 完,Java 层零组装,小程序端拿到数组直接渲染。
4.3 小程序登录态:openid 获取与自建 session
小程序端第一步永远不是写页面,而是把登录链路打通。微信小程序的登录流程是:小程序端调用wx.login拿到临时code,把 code 发到后端,后端拿去微信接口换openid和session_key。这个流程每个毕设都有,但很多人都把代码写错了位置。
后端应该为小程序单独提供一个登录接口,而不是把 code 处理逻辑混进用户注册里。Controller 层写法:
@RestController @RequestMapping("/api/user") public class UserController { @Autowired private UserService userService; @PostMapping("/login") public Result login(@RequestBody LoginDTO loginDTO) { String openid = userService.wxLogin(loginDTO.getCode()); if (openid == null) { return Result.error("登录失败,code 无效"); } // 生成自定义登录态 token,用 Redis 或内存存储 String token = UUID.randomUUID().toString().replaceAll("-", ""); userService.cacheToken(token, openid); return Result.success(token); } }注意这里调用wx.login得到的 code 有效期只有五分钟,而且只能使用一次。拿到 openid 后不要每一次请求都去微信服务器换 openid,而是自己生成一个 token 并设置过期时间。这个设计虽然简单,却是论文里可以单独写一节的“基于 Token 的小程序无状态登录方案”。
4.4 小程序 request 封装:从跨域到参数序列化
小程序端的utils/request.js是毕设中最容易被忽略又最容易翻车的地方。很多人的代码长这样:
wx.request({ url: 'http://localhost:8080/housekeeping/api/order/list', method: 'POST', data: { userId: 1, status: 0 }, success: (res) => { ... } })这一段跑通是没问题,但每个页面复制粘贴这一段会极其痛苦。更好的封装方式:
const request = (url, method, data) => { return new Promise((resolve, reject) => { wx.request({ url: `http://localhost:8080/housekeeping${url}`, method: method || 'GET', data: data || {}, header: { 'Content-Type': 'application/json' }, success: (res) => { if (res.data.code === 200) { resolve(res.data.data); } else { reject(res.data.msg || '请求失败'); } }, fail: (err) => reject(err) }); }); };把http://localhost:8080/housekeeping单独抽出来放在config.js里,将来部署到服务器只需要改一个文件。注意后端接口返回的数据结构应统一为{ code: 200, data: {}, msg: "success" },这样前端 Promise 封装才不用关心业务层报错到底是以什么形态返回的。
4.5 小程序里图片和地址:三个可以直接抄的页面性能写法
家政项目的服务列表和阿姨展示都需要加载图片,页面一多,小程序性能问题就暴露出来。最常用的一个技巧是image标签的懒加载属性:
<image src="{{item.avatar}}" lazy-load="true" mode="aspectFill"></image>mode="aspectFill"会让图片按比例缩放并裁剪填满容器,避免家政服务里常见的“图片变形”问题。服务列表下拉刷新直接用enablePullDownRefresh在pages.json里开启,后端接口只要支持分页参数就行。分页参数用传统pageNum和pageSize,因为 SSM 项目配 PageHelper 插件是常见做法,小程序端每次请求时带上当前页码,返回后concat到页面数组里实现触底加载。
地址选择这块,别自己写省市区三级联动,用微信自带的wx.chooseLocation一步拿经纬度和地址名称。毕设项目中这些“站在巨人肩膀上”的写法,答辩时讲出来反而让老师觉得你有实际开发经验。
5. SSM 家政项目最常见的 5 个翻车点:现象、原因、解法
5.1 MySQL 8.x 驱动类加载失败招致连接超时
现象:Tomcat 启动时报ClassNotFoundException: com.mysql.jdbc.Driver,或者数据库连接池初始化失败。
原因:MySQL 8.0 以上版本的 JDBC 驱动类名从com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.Driver,而很多毕设源码的jdbc.properties里还保留着旧类名。更隐晦的是,如果pom.xml中引入的 mysql-connector-java 版本过旧,即使改了类名也连不上。
解决:把jdbc.driver改成com.mysql.cj.jdbc.Driver,并在 pom 里把依赖版本升到 5.1.49 以上或直接使用 8.0.x。检查驱动版本最直接的方法,是去本地 Maven 仓库翻mysql-connector-java目录下的 jar 包版本号,别凭印象猜。
5.2 订单表用了 order 关键词导致建表失败
现象:导入 SQL 脚本时 MySQL 报You have an error in your SQL syntax,错误信息指向 create table 语句。
原因:order是 MySQL 的保留字,不能直接做表名。这个错误在毕设里出现频率极高,因为“订单”最自然的英文就是 order,几乎人人中招。
解决:建表时写成:
CREATE TABLE `order` ( id INT PRIMARY KEY AUTO_INCREMENT, ... )把表名用反引号包起来,这是 MySQL 唯一的转义方式。同理,group、desc、key等保留字也不能直接做字段名,最好一律用反引号包住。如果你在改代码阶段才发现这个问题,可以执行RENAME TABLEorderTOorders;然后全局搜索替换 SQL 和 XML 里的表名。
5.3 @ResponseBody 返回中文乱码
现象:小程序端请求后端接口,返回的 JSON 里中文全部变成???或鎴愬姛之类的乱码。
原因:Spring MVC 默认使用ISO-8859-1字符集处理 HTTP 响应,而 JSON 数据是 UTF-8 编码。SSM 项目没有 Spring Boot 那样自动帮配application/json;charset=UTF-8的机制。
解决:在spring-mvc.xml里显式配置消息转换器的字符集:
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="defaultCharset" value="UTF-8"/> </bean> </mvc:message-converters> </mvc:annotation-driven>这个配置加上以后,字符串和 JSON 响应就都不会再有中文乱码问题。如果加了还乱码,检查 Tomcat 的server.xml里 Connector 是否配置了URIEncoding="UTF-8"。
5.4 小程序真机预览请求不到本地服务
现象:在微信开发者工具里一切正常,手机扫码预览后所有请求全部失败,报net::ERR_CONNECTION_REFUSED。
原因:真机的 localhost 指向的是手机自己,不是你的电脑,而开发者工具默认帮你做了代理所以看着正常。很多毕设演示视频都是用开发者工具录的,导致这个坑被大量同学在答辩前最后一天踩到。
解决:把小程序里的请求地址改成电脑在局域网内的 IP,比如http://192.168.1.101:8080/housekeeping。电脑端关闭防火墙,或者至少在防火墙入站规则里放行 8080 端口。如果还是连不上,用另一台手机开热点,电脑连热点后重新查 IP,项目里config.js统一改一遍地址即可。这里唯一的后悔药就是把所有接口地址集中在一个配置文件里,一个文件改完所有页面生效。
5.5 论文里数据库设计图与实际表不一致
现象:论文里 ER 图画着用户表直接关联订单表,实际代码里中间还有address和payment两张表。
原因:一边写代码一遍写论文,改代码后忘了同步论文图,或者论文图是先画好再按图开发,但开发中需求微调改变了表结构。
解决:论文完稿前专门预留半天,用工具把数据库反向导出 ER 图校准。推荐用 Navicat 或 DBeaver 连上数据库后自动生成关系图,截图贴进论文比手绘 Visio 图更真实且不易出错。手绘图的线条对不齐、表名字打错是最减分的细节,直接截图反而显得项目是真的能跑起来的。这个习惯现在救了我很多次,改字段之前先去把论文里的表结构同步改掉,免得最后通宵赶工。
6. 让答辩分数往上走两个档次的三个验证动作
项目能跑起来只是及格线,想拿高分毕业设计,建议在答辩前做三个“背调式”验证。第一个动作是查日志中的慢 SQL,打开 MySQL 的慢查询日志,看有没有全表扫描的查询。最简单的开启方式:
SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1;跑一遍小程序的完整下单流程,再查日志里出现过的 SQL 语句,凡是没有走到索引的大表查询,都在论文“系统优化”小节里写一句“本系统对订单查询增加了复合索引,查询响应时间从 280ms 下降到 45ms”。有数据支撑的性能结论,比空泛写“系统性能优越”有说服力得多。
第二个动作是用 Postman 跑一遍全部接口并截图。把用户登录、提交订单、管理员派单、订单完成的接口连同请求参数和响应结果整理成一张表格,按模块分类贴到论文的“系统测试”章节。答辩评审时老师会翻到这一页停留最久——因为这里有“你的系统真的跑过”的直接证据。接口表格建议包含测试用例编号、功能描述、前置条件、输入数据、预期结果、实际结果、是否通过,七列足够规范。
第三个动作是压缩包自测指令:从零环境开始,按你论文里写的部署步骤完整走一遍。包括装 JDK、装 MySQL、导入 SQL、部署 war、启动小程序开发者工具。有人论文环境配置写“JDK 版本不限”,结果答辩现场用 17 根本跑不起来;有人数据库密码写在代码里是 root/123456,换了台机器就彻底连不上。把这些都验证过一遍,再稍微演练一下答辩时要说的业务闭环:用户下单、支付模拟回调、管理员派单、阿姨完成、用户评价——一条线走完,面试官印象分远高于背八股文。
以上所有经验都来自我陪过一届又一届毕设的血泪教训。家政这个选题说难不算难,说简单也足够撑起一篇完整论文,关键是把每一步都做到“能演示、能解释、能扛住追问”。希望这篇笔记能帮你少踩几个坑,把那几夜通宵留给更有价值的事情。祝答辩顺利。
本文还有配套的精品资源,点击获取