news 2026/10/7 18:51:03

家庭记账本系统毕设:SSM+微信小程序从拆包到答辩避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
家庭记账本系统毕设:SSM+微信小程序从拆包到答辩避坑指南

简介:基于Java SSM框架与微信小程序构建的家庭记账本系统,是一份适合毕业设计、课程设计及期末大作业的完整项目包。系统覆盖用户登录注册、账目录入、查询、数据统计与报表生成等核心功能,界面简洁、操作便捷,项目已在导师指导下完成并通过答辩。压缩包共775个文件,约68.44MB,包含Java后端源码、Vue前端页面、微信小程序WXML/WXSS页面、数据库SQL脚本及论文文档等,其中Java与Vue文件占比最高,用于实现后端业务逻辑与Web管理端,WXML/WXSS与JS组成小程序端,SQL脚本可直接导入MySQL;同时附有安装运行脚本、样式与配置文件,便于本地部署和二次开发。目前已有97人学习下载。这套资源提供可直接运行的前后端代码、数据库脚本、论文和配套工具,下载后无需修改即可启动。通过源码可学习SSM整合流程、小程序端与后端交互方式,以及家庭财务管理的分层设计与统计实现,作为高分毕设参考具有较高实用价值。

1. 家庭记账本系统在毕设里到底值不值得选:先看 SSM 与小程序的分工

如果你在毕业设计选题的海洋里刷到“基于 java+ssm+mysql+微信小程序的家庭记账本系统”,大概率是被“源码+数据库+论文”这种打包交付的形式吸引的。我的判断是先别急着下载,这套东西真正的价值不在“记账”这个业务,而在于它把 Java 后端最经典的 SSM 三件套和微信小程序前端完整串成了一条可演示的链路——登录、记一笔、查统计、看报表,刚好覆盖了毕业设计最看重的“业务闭环 + 技术栈完整度”。如果你的目标是快速拥有一套能跑起来的系统,再围绕它做二次开发和答辩准备,这个方向性价比很高;但如果你以为解压就能用、不改就能过,那后面踩坑的地方会比你想象的多得多。这篇文章就按我自己带毕设项目的习惯,把拆包、改配置、跑通、避坑的完整路径讲清楚。

2. 拆开源码包:SSM 后端、MySQL 表和微信小程序各自要改什么

2.1 先看懂这套系统的三层骨架

拿到这个压缩包,别急着启动,先花十分钟确认里面到底是什么结构。常见做法是,基于 SSM 的 Java 后端工程会是一个标准的 Maven 项目,目录里带着pom.xml、src/main/java、src/main/resources;数据库脚本一般是独立的.sql文件,可能放在db或sql目录下;小程序端则是另一个独立目录,里面是pages、utils、app.js这些微信开发者工具能直接导入的工程文件。

这套系统的分工很清晰:小程序端负责展示和收集用户操作,SSM 后端负责业务逻辑和读写 MySQL,数据库只存数据不跑业务。你在答辩时最常被问的一句话是“某个功能的数据是怎么从界面走到数据库的”,所以拆包阶段就要把这条链路在脑子里画出来——用户在小程序里点“记一笔”,前端把金额、分类、备注通过 HTTP 请求发给 SpringMVC 的 Controller,Controller 调 Service,Service 调 MyBatis 的 Mapper 接口,Mapper 再执行 SQL 把数据写进 MySQL。反过来的读操作也一样,只是方向相反。

这个三层架构是 SSM 项目的标准范式,也是它成为毕设常青树的原因。Spring 管对象和事务,SpringMVC 管请求路由,MyBatis 管数据库访问,每一层都能在答辩时单独拿出来讲。但要注意,很多打包版本里三层分的并没有那么干净,Controller 里直接写业务、Mapper 里写复杂 SQL 的情况很常见,这部分后面要改。

2.2 记账业务最核心的几张表

不管压缩包里的数据库脚本长什么样,一个家庭记账本的核心表基本逃不出这几张,我一般会对照着检查脚本是否完整:

表名作用关键字段
user用户(家庭成员)id、openid、nickname、avatar
account账本id、user_id、name、type(家庭/个人)、created_time
category收支分类id、name、type(income/expense)、icon
record收支明细id、account_id、category_id、amount、type、note、record_date
budget预算(可选)id、account_id、category_id、month、amount

record表是整个系统的核心,字段设计上有一个经常翻车的点:金额字段建议用DECIMAL(10,2)而不是FLOAT或DOUBLE。因为浮点数在 MySQL 里存储会有精度误差,比如 0.1 加 0.2 不等于 0.3,记账这种对数字敏感的场景一旦出现分角误差,后期对账非常痛苦。MyBatis 映射时对应的 Java 类型用BigDecimal,不要用double。

user表的openid字段是微信生态的关键,小程序端通过wx.login拿到临时 code,后端再用 code 去微信接口换 openid。这个字段要加唯一索引,因为一个微信号对应一个 openid,用户重复注册时要用 openid 而不是自增 id 来判断身份。

2.3 后端工程里那几个必须改的配置文件

SSM 项目最让人头疼的就是配置文件多。不同于 Spring Boot 的约定优于配置,SSM 需要你手动维护web.xml、spring-mvc.xml、spring-mybatis.xml、jdbc.properties这一组文件。拆包后第一件事就是打开jdbc.properties或者db.properties,确认里面的数据库连接信息:

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/family_account?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=123456

参数说明:family_account是数据库名,得跟你导入的 .sql 文件里的建库语句保持一致;useSSL=false是必须加的,MySQL 8.0 里不关 SSL 会出现一大堆握手警告;characterEncoding=utf8是中文不乱码的前提,尤其记账备注里大量中文。如果你的 MySQL 是 8.0 以上版本,driver这一行要换成com.mysql.cj.jdbc.Driver,后面避坑章节会专门展开。

spring-mybatis.xml里一般配了 Mapper 扫描路径和 SQL 映射文件位置,比如classpath:mapper/*.xml。如果启动时提示找不到某个 mapper 方法,八成是这里的前缀路径和实际目录对不上。这一类问题在第五章统一排查。

2.4 小程序端的目录与配置

小程序工程打开后,先看app.js或utils/request.js,里面通常会有一个baseUrl常量,指向后端接口地址。这是个毕设项目能否实机演示的关键:

// utils/request.js 片段 const baseUrl = 'http://localhost:8080/ssm-account/api'

这个地址在后端启动之前不用改,但启动之后大概率要改成你电脑的局域网 IP,否则手机端预览时根本连不上后端,只有开发者工具模拟器能通。另外project.config.json里的appid是你自己的,需要用微信开发者工具扫码替换,不然真机预览会报注册信息不匹配。

3. 本地跑通记账系统:MySQL 导入、后端启动、小程序连上电脑的三个步骤

3.1 环境清单与版本匹配,先把地基打对

跑这套系统之前,先把环境捋清楚。SSM 项目对 Java 版本的容忍度有限,最常见的坑是拿 JDK 17 跑老项目,结果 Tomcat 直接罢工。我一般推荐的组合是 JDK 1.8(181 以上版本)+ Maven 3.6.x + Tomcat 8.5 + MySQL 5.7 或 8.0。MySQL 8.0 能用,但要注意驱动类名和时区问题,后面单独讲。

微信开发者工具也需要留意版本,稳定版即可,不用追最新版,因为有些 API 在小程序基础库里的兼容性会因版本变化而出现不一致。导入项目时选择“导入项目”,目录指向小程序端的文件夹,AppID 选“测试号”也能跑通大部分功能,但涉及wx.login换取 openid 时,测试号的逻辑和正式号有差异,建议用自己的小程序 AppID。

还有一点容易忽略:Maven 仓库的镜像配置。国内网络环境下maven-central默认源下载依赖极慢,建议在settings.xml里配置阿里云镜像,否则第一次构建可能会等十几分钟,这期间你什么都做不了。有同学说构建失败就怀疑代码有问题,其实大概率是依赖没拉下来。

3.2 导入数据库脚本,别让 SQL 文件吃灰

数据库脚本通常是一个.sql文件,里面包含建库、建表、插入初始分类数据的语句。导入步骤用命令行或者 Navicat 都行,我习惯用命令行演示,因为答辩时在终端敲命令比打开 GUI 工具更有说服力:

mysql -u root -p123456 -e "source /path/to/family_account.sql"

参数说明:-p123456是密码直连,如果你的密码有特殊字符,建议改成mysql -u root -p后回车交互式输入;source是 MySQL 客户端的导入命令,路径要写绝对路径,否则会报找不到文件。导入完成后执行下面的命令验证一下:

mysql -u root -p123456 -e "use family_account; show tables;"

看到user、category、record等表名就说明导入成功了。如果报错说数据库已存在,说明脚本里带了CREATE DATABASE IF NOT EXISTS而库里已经有同名库,这时候要么先DROP DATABASE,要么手动改脚本里的库名。

一个常见问题是脚本缺少初始数据。有的精简版只建表不插数据,导致小程序端首页看不到默认分类。如果遇到这种情况,需要手动补几条分类数据,比如“餐饮”“交通”“购物”“工资”“奖金”之类的:

INSERT INTO category (name, type, icon) VALUES ('餐饮', 'expense', 'food'); INSERT INTO category (name, type, icon) VALUES ('交通', 'expense', 'traffic'); INSERT INTO category (name, type, icon) VALUES ('工资', 'income', 'salary');

3.3 后端 SSM 启动:从 Maven 打包到 Tomcat 部署

环境就绪后,进入后端工程的根目录,确认pom.xml存在,然后执行编译打包。这里有一个决策点:SSM 项目老派的发布方式是把war包丢进 Tomcat 的webapps目录,但如果你用的是 IntelliJ IDEA,可以在 IDEA 里配置 Tomcat 直接启动,省去手动拷贝的环节。两种方式我都用过,推荐在本地开发阶段用 IDEA 内嵌 Tomcat,答辩前再打一次 war 包做最终验证。

命令行打包方式如下:

mvn clean package -DskipTests

参数说明:clean会先删除target目录避免旧产物干扰;package生成 war 包;-DskipTests跳过单元测试,避免测试类报错导致打包中断。打包完成后,在target目录下能看到类似ssm-account.war的文件。如果你要在本地命令行启动 Tomcat,把这个 war 包复制到 Tomcat 的webapps目录,然后执行:

cd /path/to/tomcat/bin ./startup.sh

然后打开浏览器访问http://localhost:8080/ssm-account/,看到登录页或者接口返回的 JSON 就说明后端起来了。注意ssm-account是 war 包的名称,对应 Tomcat 的虚拟目录名,改 war 包名就等于改访问路径。

后端启动失败的排查顺序我一般固定为:先看catalina.out日志,再看localhost.log,最后看具体异常栈。常见的启动失败原因是 MySQL 连不上——URL 写错、密码不对、驱动缺失,这三种占了七成。

3.4 小程序端连接本地接口,三处必须改的配置

后端跑起来后,小程序端有三处配置不改成自己的就无法正常演示。

第一处是utils/request.js里的baseUrl。开发者工具模拟器里可以用http://localhost:8080,但真机预览时手机和电脑不在同一个网络环境,localhost指向的是手机自己,必须改成电脑的局域网 IP,比如http://192.168.1.100:8080。获取方式是在终端执行ipconfig(Windows)或ifconfig(macOS/Linux),找到192.168.x.x那一段。

第二处是app.js里可能存在的全局配置,比如一些项目会把账本 id 或用户 id 写死在globalData里,这个不一定是 bug,而是为了演示方便。但你要知道它在哪儿,因为答辩时要能解释“当前用户是怎么确定的”。

第三处是project.config.json里的appid。使用自己的 AppID 后,登录态相关的功能才能走完整的微信链路。如果只为了快速看界面,用测试号也行,但wx.login返回的 code 在测试号下后端换取 openid 的流程可能不同。

代码里还有一处隐蔽的配置——如果小程序端有上传图片或头像的功能,uploadFile的 URL 也要跟着baseUrl一起改,不少项目只改了普通请求的地址,漏掉了上传的,结果“记账成功但头像传不上去”。

4. 记账主链路:收支录入、分类汇总与月度统计的接口实现

4.1 登录与 openid 绑定:微信小程序登录的毕设级方案

记账本需要一个用户身份来隔离数据,微信小程序最省事的方案就是wx.login换取 openid,把它当成用户的天然唯一 ID。流程是这样的:小程序端调用wx.login拿到临时 code,通过后端接口传给服务器;后端拿这个 code 去调用微信的jscode2session接口,换取 openid 和 session_key;然后后端查数据库,openid 不存在就自动注册,存在就直接返回用户数据。

后端 Controller 的核心逻辑类似这样:

@Controller @RequestMapping("/api/user") public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public Result login(@RequestBody Map<String, String> params) { String code = params.get("code"); String openid = userService.getOpenidByCode(code); User user = userService.findOrCreate(openid); return Result.success(user); } }

逻辑说明:code是一次性的,有效期五分钟,用后作废,不能缓存或重复使用;getOpenidByCode内部是 HTTP 调用微信接口,这个调用放在 Service 层做,不要在 Controller 里拼 URL。findOrCreate是先按 openid 查库,查到就返回,查不到就插入一条新用户记录。返回的Result是统一的 JSON 包装类,建议包含code、message、data三个字段,小程序端通过code判断成功与否,不要让它裸返回一个 Map。

4.2 记一笔:从页面表单到数据库的完整数据流

记一笔是记账本的核心操作,前端页面收集金额、分类、日期、备注,然后 POST 到后端。我在看这类项目的源码时,最关注的是金额和分类这两个字段有没有做后端校验——很多毕设版本只在前端做了required校验,后端接口裸奔,这是答辩时容易露怯的点。

后端保存记录的代码大概长这样:

@RequestMapping(value = "/add", method = RequestMethod.POST) @ResponseBody public Result addRecord(@RequestBody Record record) { // 必填校验 if (record.getAmount() == null || record.getCategoryId() == null) { return Result.error("金额和分类不能为空"); } // 金额不能为负数 if (record.getAmount().compareTo(BigDecimal.ZERO) < 0) { return Result.error("金额不能为负数"); } // 默认值补全 if (StringUtils.isEmpty(record.getNote())) { record.setNote("无备注"); } record.setCreateTime(new Date()); recordService.add(record); return Result.success(null); }

逻辑说明:compareTo(BigDecimal.ZERO)是 BigDecimal 的标准比较方式,不能用>或<直接比较;StringUtils.isEmpty注意引的是 Spring 的还是 Apache Commons 的,两者对 null 和空串的处理略有差异。补全createTime是后端职责,不能依赖前端传时间戳,否则用户改手机时间会影响数据正确性。

这里有个隐蔽的问题:前端传来的amount在 JSON 里可能是数字也可能是字符串,SpringMVC 默认用 Jackson 反序列化,BigDecimal对数字和字符串都能处理,但如果是空字符串就会报错。所以前端提交前一定要把金额字段转换成数字类型,别用Number('')这种会得到 0 的写法。

4.3 月度统计与分类汇总:几条能当答辩亮点的 SQL

记账本里最有含金量的功能不是记一笔,而是统计。常见的统计包括:本月总支出、本月总收入、按分类汇总的支出占比、近六个月的收支趋势。后端如果用 Java 做内存统计,数据量小时没问题,但答辩时会被问“数据量大了怎么办”,所以统计逻辑应该尽量下沉到 SQL 里。

月度支出按分类汇总的 SQL:

SELECT c.name AS category_name, SUM(r.amount) AS total_amount FROM record r INNER JOIN category c ON r.category_id = c.id WHERE r.type = 'expense' AND DATE_FORMAT(r.record_date, '%Y-%m') = '2025-06' GROUP BY r.category_id ORDER BY total_amount DESC;

参数说明:DATE_FORMAT(r.record_date, '%Y-%m')是把日期格式化成YYYY-MM的字符串,与'2025-06'比对;这里要注意record_date字段如果是datetime类型且有索引,使用DATE_FORMAT会导致索引失效,数据量大时查询变慢。更好的写法是用范围查询:r.record_date >= '2025-06-01' AND r.record_date < '2025-07-01',但毕设答辩时先把功能跑通更重要,索引优化可以作为加分项提一句。

近六个月趋势图的数据来源:

SELECT DATE_FORMAT(record_date, '%Y-%m') AS month, SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) AS expense_total, SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) AS income_total FROM record WHERE account_id = #{accountId} AND record_date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) GROUP BY DATE_FORMAT(record_date, '%Y-%m') ORDER BY month ASC;

逻辑说明:CASE WHEN在聚合函数里做条件求和,是避免两次查询的标准写法;DATE_SUB(CURDATE(), INTERVAL 6 MONTH)动态计算半年前的日期,不需要在 Java 里拼参数。这个接口返回的数据直接喂给小程序端的图表组件就行,比如 echarts-for-weixin 或者原生 canvas。

4.4 会话保持:token 的简单实现与安全边界

SSM 项目里要处理的一个问题是:用户登录后,后续每次请求怎么识别身份。常见做法是登录成功后后端生成一个 UUID 作为 token,存到 Redis 或内存 Map,下发到小程序端,小程序端存到wx.setStorageSync,之后每次请求在 header 里带上。毕设项目如果没有引入 Redis,用 ConcurrentHashMap 顶住即可,但前提是后端不能重启——一重启 token 全失效,用户要重新登录。

后端拦截器的写法:

public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); if (token == null || !TokenManager.isValid(token)) { response.setStatus(401); return false; } return true; } }

逻辑说明:TokenManager是持有 token 存储的静态类或 Spring Bean;preHandle返回 false 时请求会直接中断,不会进入 Controller。注册拦截器时注意要排除登录接口本身和静态资源,否则会出现“登录接口也被拦截”的死循环。这个机制在答辩时讲出来比“没做登录”高一个档次,代码量也不大。

安全边界要讲清楚:这套方案只能保证“基本识别”,token 是明文放在 header 里的,抓包就能看到。真正的生产环境应该用 HTTPS + 短期 token + 刷新机制,但毕设答辩时你主动说出这个局限,比被老师问出来要好得多。

5. 从能跑到跑稳:SSM+小程序联调的 6 个高频坑与排查清单

5.1 MySQL 8.0 驱动类名报错:ClassNotFoundException 的真相

现象:后端启动时报ClassNotFoundException: com.mysql.jdbc.Driver。

原因:MySQL 8.0 的驱动包把类名改成了com.mysql.cj.jdbc.Driver,旧名字在 8.0 驱动里虽然还保留兼容,但在某些版本和 Spring 版本的组合下会直接找不到。与此同时,jdbc:mysql://的 URL 在新驱动下强制要求时区参数,不写serverTimezone=Asia/Shanghai就报The server time zone value的异常。

解决:改jdbc.properties两处,驱动类名换成com.mysql.cj.jdbc.Driver,URL 末尾加上&serverTimezone=Asia/Shanghai。同时确认pom.xml里的 MySQL Connector 版本是 8.x:

<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>

如果不想换 URL,也可以在 MySQL 服务端执行SET GLOBAL time_zone = '+8:00',但不如改 URL 干净,后者跟着工程走,换台电脑部署不受影响。

5.2 小程序 request 报 “不在以下 request 合法域名列表中”

现象:微信开发者工具控制台报url not in domain list,请求发出去了但返回 fail,或者提示“不在以下 request 合法域名列表中”。

原因:微信小程序对普通 HTTP 请求做了域名白名单校验,线上环境要求域名必须备案且在公众平台配置。但本地开发调试时没必要配域名,工具里有一个开关可以关掉校验。

解决:开发者工具的“详情 → 本地设置”里勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”。勾上之后本地请求就能通了。但要注意两个边界:一是这个开关只对开发者工具生效,真机预览默认还是不校验的(预览时用的是工具环境),但正式发布的小程序必须配合法域名;二是如果你用手机扫描预览二维码,手机和电脑要在同一个局域网,且后端监听的地址不能是127.0.0.1,要监听0.0.0.0或具体的局域网 IP。

这个现象在毕设答辩前最容易翻车——前一天在工作室跑得好好的,换了个场地网络,手机连不上后端,演示直接变黑匣子。预防办法是用手机流量开热点让电脑连上,这样手机和电脑必然在同一网段。

5.3 本地调试用 http://localhost 后端,真机一预览就失败

现象:开发者工具模拟器里一切正常,扫码真机预览时页面能打开但所有数据加载不出来。

原因:模拟器里localhost指向的是你开发电脑,真机里的localhost指向手机自己。后端接口地址写死成localhost时,真机找不到后端。

解决:把baseUrl改成电脑的局域网 IP。获取 IP 的几种方式:macOS 在系统设置 → 网络里看,或者在终端执行ipconfig getifaddr en0;Windows 在命令行执行ipconfig,找IPv4 地址段。然后改成http://192.168.x.x:8080/工程名。改完后先在模拟器里试一次,再真机试一次,两次都通再继续别的功能。同时确认电脑防火墙放行了 8080 端口,否则手机请求会被防火墙拦掉——这是最玄学的一个环节,经常查了半天代码发现是防火墙问题。

5.4 MyBatis 日期比较翻车:DATE_FORMAT 导致整表扫描

现象:数据量只有几千条时统计接口很快,但随着测试数据越加越多,月度统计接口从几十毫秒涨到几百毫秒,再过一阵直接卡到秒级。

原因:统计 SQL 里用了DATE_FORMAT(record_date, '%Y-%m') = '2025-06'这种写法,MySQL 无法对record_date使用索引,只能全表扫描。几千条数据无所谓,几十万条就明显了。

解决:改成范围查询,让索引生效:

<select id="sumByMonth" resultType="map"> SELECT c.name AS category_name, SUM(r.amount) AS total_amount FROM record r INNER JOIN category c ON r.category_id = c.id WHERE r.type = 'expense' AND r.record_date &gt;= #{startDate} AND r.record_date &lt; #{endDate} GROUP BY r.category_id </select>

参数说明:startDate和endDate在 Java 里算好传入,比如 6 月的区间就是2025-06-01 00:00:00到2025-07-01 00:00:00,endDate用开区间,避免把 7 月 1 日的记录算进来。注意 XML 里>和<必须转义成&gt;和&lt;,这是 MyBatis XML 文件的老坑,不转义会直接报 XML 解析错误。这一条讲出去,答辩老师会觉得你懂 MySQL 的索引原理。

5.5 JSON 序列化:日期变成时间戳,BigDecimal 变成科学计数法

现象:小程序端拿到后端返回的日期字段是1719302400000这种一串数字,金额字段变成了1.0E+2。

原因:SpringMVC 默认使用 Jackson 做 JSON 序列化,Java 的Date默认输出为毫秒时间戳;BigDecimal在某些版本下会被序列化成科学计数法。前端没做二次处理,直接绑定到界面就显示成乱七八糟的字符。

解决:在后端全局配置 Jackson 的消息转换器,把日期格式固定成字符串,并关闭科学计数法。常规做法是在 SpringMVC 配置文件里加:

<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.fasterxml.jackson.databind.ObjectMapper"> <property name="dateFormat"> <bean class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd HH:mm:ss"/> </bean> </property> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>

这个配置比较啰嗦,如果项目里已经用了 Spring Boot 风格可以简化为配置类。另一个更省事的方法是在实体类的日期字段上标注@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8"),金额字段上标注@JsonSerialize(using = ToStringSerializer.class)。两种方式选一种,不要在同一个项目里混用,否则接口返回格式会不统一。

5.6 Tomcat 端口冲突与 war 包路径不一致

现象:启动 Tomcat 时控制台报Port 8080 required by Tomcat v8.5 Server at localhost is already in use,或者启动成功但访问http://localhost:8080/ssm-account/返回 404。

原因:第一个是 8080 端口被别的进程占了,可能是之前启动的 Tomcat 没关干净,也可能是其他 Web 服务在监听。第二个大概率是 war 包名和访问路径不一致,比如你手动改过 war 包名,但 IDEA 部署配置里用的还是旧名字。

解决:端口占用用lsof -i:8080(macOS/Linux)或netstat -ano | findstr 8080(Windows)查进程 id,然后kill。之后可以改 Tomcat 的server.xml里<Connector port="8080">换成其他端口,比如 8081,但要同步改小程序的baseUrl。war 包路径问题,进入 Tomcat 的webapps目录看看实际解压出来的文件夹名,再用那个名字拼 URL——这个文件夹就是 Tomcat 给你生成的上下文路径,大小写都别搞错,Windows 下不区分大小写,Linux 下区分。

6. 答辩与二次开发:把记账模板从“能跑”变成“你的项目”

到这里,这套家庭记账本系统已经能跑通主链路了。但如果你打算直接拿它去答辩,我给一句忠告:模板项目只能作为起点,答辩老师最反感的就是照着项目读 PPT,你得能找到几个点证明你“动过手”。

第一个建议是在项目里加一个功能模块,优先级最高的是“预算管理”。多数记账本模板只有记账和统计,没有预算超支提醒。你可以在现有表结构上加一张budget表,在记录新增时检查当月该分类的预算剩余,返回给前端一个“已超支 XX 元”的提示。这个改动涉及建表、Service 逻辑、Controller 接口和小程序端提示,是一个完整的闭环功能,工作量适中,但答辩时能讲的故事多了很多。

第二个建议是把统计接口的 SQL 换成前面 4.3 节里的范围查询版本,并主动讲出“不用 DATE_FORMAT 是为了走索引”。这一句话就能证明你不是只会复制粘贴的,而是理解 SQL 执行效率的基本原理。很多毕设项目的数据量很小,老师不太关注性能,但你主动提出来,观感完全不一样。

第三个建议是梳理清楚登录态方案。把 4.4 节的 token 思想完整实现一遍,哪怕只是用内存 Map 存 token,也让整个系统有了身份认证的骨架。答辩时被问到“用户数据怎么隔离的”这个问题时,你的回答会从“没做登录”变成“用 openid 关联用户 + token 标识会话”,两个回答的档次差距,经历过答辩的人都懂。

最后说一个我自己的教训:以前带过一个同学,他拿了一个类似的小程序记账项目,全程没改代码,直接拿去开题。开题那天老师问“你负责哪部分”,他答不上来,场面一度非常尴尬。后来我帮他理清思路,把登录流程、记账链路和统计 SQL 各选一个点深入讲透,再补了一个预算功能,答辩才顺利过了。所以别急着拿包就跑,先花一个下午把代码读一遍,找到你自己能讲清楚的那条线,然后在这条线上做出一个属于自己的改进点,这套流程走到位,高分毕业设计是真的拿得到的。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 18:50:09

手机PDF转换成Word免费版!零套路无水印,新手直接用

日常办公、学生整理资料&#xff0c;经常会遇到需要把PDF转换成Word的情况。但大部分转换工具要么需要付费开会员、要么转换后自带水印、要么排版错乱&#xff0c;十分影响使用。很多人找了半天&#xff0c;都没找到真正免费、操作简单、适配手机的PDF转Word方法。今天给大家整…

作者头像 李华
网站建设 2026/10/7 18:49:28

Java炸弹人课设源码拆解:Swing游戏开发与碰撞检测

简介&#xff1a;一款基于Java开发的炸弹人小游戏源码包&#xff0c;是面向计算机相关专业学生的课程设计和毕业设计参考作品。项目采用图形界面与事件驱动架构&#xff0c;完整实现了经典炸弹人的玩法流程&#xff0c;包括地图生成、玩家移动、怪物追踪、爆炸范围判定以及胜负…

作者头像 李华
网站建设 2026/10/7 18:48:01

国产AI突围:MoE架构如何省算力降能耗,落地全工业场景

1. 国产AI突围的底层逻辑&#xff1a;为什么能源和架构成了胜负手过去两年&#xff0c;我一直在跟踪国内大模型从实验室走向产线的全过程。说实话&#xff0c;最初大家比拼的是参数规模&#xff0c;谁的模型大谁就有话语权。但到了2024年下半年&#xff0c;风向明显变了——能源…

作者头像 李华
网站建设 2026/10/7 18:48:01

工程科研AI协作实战:命令行代理与项目说明文件配置指南

1. 工程科研场景下AI工具选型的底层逻辑 1.1 为什么通用聊天窗口撑不起真正的科研工作流 我最早接触AI辅助科研&#xff0c;和大多数人一样&#xff0c;是从网页版对话窗口开始的。查文献、润色摘要、解释一段公式&#xff0c;确实方便。但用了不到两周就发现一个致命问题&…

作者头像 李华
网站建设 2026/10/7 18:47:22

I2C通信时序详解:从物理层到调试实战的完整指南

我第一次调 I2C 的时候&#xff0c;心里想的是&#xff1a;这协议也太简单了吧&#xff0c;SCL 传时钟&#xff0c;SDA 传数据&#xff0c;两根线搞定一切。结果板子上新贴的温湿度传感器&#xff0c;怎么读都是 0xFF。后来才反应过来&#xff0c;0xFF 意味着 SDA 根本没被拉低…

作者头像 李华
网站建设 2026/10/7 18:45:28

从IDE到ADE:智能体开发环境的技术基建与实操指南

1. 从IDE到ADE&#xff1a;开发环境正在经历一次范式迁移如果你最近在开发者社区里闲逛&#xff0c;大概率会频繁撞见一个词——ADE&#xff0c;也就是Agentic Development Environment&#xff0c;智能体开发环境。两三年前我们还在讨论"哪个IDE的补全更准""谁…

作者头像 李华