背景痛点:选题“三宗罪”
大四开学,导师第一句话往往是“选题定了没?”——于是大家开始全网搜索“计算机毕业设计点子”,结果越看越懵:
- 题目过大:一开口就是“基于深度学习的智慧医疗云平台”,结果数据集、算力、标注全没有,最后只能硬塞几段公式,答辩现场被怼到怀疑人生。
- 技术堆砌:把微服务、区块链、大数据全写进标题,GitHub 拉一堆 star 高的项目拼拼凑凑,跑起来一次就截图,老师一问“熔断怎么做的”直接宕机。
- 无业务主线:纯 KPI 式堆功能,“登录、注册、上传、下载”四件套,做完连自己都不知道解决了谁的什么问题,论文写起来像说明书,查重率还爆表。
归根结底,是“想一口吃成胖子”,却忽略了本科阶段的根本目标——把一个完整技术栈跑通,把代码写干净,把业务讲圆。下面这套“轻量级 Web 应用”模板,是我带两届学弟妹踩坑后总结出的最小可落地闭环,新手也能在 6-8 周内交付可演示、可部署、可答辩的作品。
技术选型:为什么不是“全家桶”
先给结论:Vue 3 + Spring Boot 3 + MySQL 8,配一套 MyBatis-Plus、Redis(可选缓存)、Docker。理由一句话:社区成熟、文档成山、面试问题能 Google。
| 维度 | Vue 3 | React 18 | Angular 17 |
|---|---|---|---|
| 学习曲线 | 模板语法接近原生 HTML,心智负担低 | 函数式+Hooks,需熟悉 JSX | 一整套 RxJS、DI,概念多 |
| 中文资料 | 极多,B 站大学你懂的 | 多但杂,需筛选 | 少,且版本割裂 |
| 脚手架 | Vite 一键起 | CRA 已过时,需自己配 Vite | CLI 重,配置黑盒 |
后端同理,Spring Boot 相比 Django/Flask 的最大优势是**“一个注解跑起来”**,而且国内公司保有量高,答辩时老师有亲切感。数据库选 MySQL 不为别的,就因为学校机房装的是它,部署到云服务器也能找到现成镜像,省时间。
核心实现:以“课程管理系统”为例
1. 业务模块划分
- 用户中心:学生/教师/管理员三种角色,RBAC 到按钮级(答辩亮点)。
- 课程中心:CRUD 课程、选课退课、容量控制。
- 成绩中心:教师录入、学生查看、统计导出。
- 公告中心:管理员发通知,支持 Markdown 富文本。
- 系统日志:登录、敏感操作写表,AOP 一把梭。
2. 数据模型(精简 ER)
user(id, username, password, role, email, create_time) course(id, name, credit, max_capacity, teacher_id, semester) selection(id, student_id, course_id, score, gmt_create, gmt_modified) notice(id, title, content, publisher_id, publish_time) login_log(id, user_id, ip, ua, login_time)外键全部逻辑外键,避免级联删除把演示数据一锅端。
3. RESTful API 设计规范
| 方法 | 路径 | 描述 | 幂等 |
|---|---|---|---|
| GET | /api/courses?page=1&size=10 | 分页课程列表 | 是 |
| POST | /api/courses | 教师新建课程 | 否 |
| PUT | /api/courses/{id} | 更新课程信息 | 是 |
| DELETE | /api/courses/{id} | 删除课程 | 是 |
| POST | /api/courses/{id}/select | 学生选课 | 否(限库存) |
所有路径带/api前缀,方便 Nginx 做反向代理;返回统一包装:
{ "code": 200, "msg": "success", "data": { ... } }代码示例:用户登录接口(Spring Boot)
@RestController @RequestMapping("/api") @RequiredArgsConstructor public class UserController { private final UserService userService; private final JwtHelper jwtHelper; /** * 登录:POST /api/login * 1. 参数校验 * 2. 密码比对(BCrypt) * 3. 生成 JWT * 4. 返回用户基本信息 + token */ @PostMapping("/login") public ApiResult<LoginVO> login(@Valid @RequestBody LoginDTO dto) { User user = userService.lambdaQuery() .eq(User::getUsername, dto.getUsername()) .one(); if (user == null || !BCrypt.checkpw(dto.getPassword(), user.getPassword())) { return ApiResult.fail(401, "账号或密码错误"); } String token = jwtHelper.createToken(user.getId(), user.getRole()); LoginVO vo = LoginVO.builder() .id(user.getId()) .username(user.getUsername()) .role(user.getRole()) .token(token) .build(); return ApiResult.success(vo); } }Clean Code 三要素:
- 方法不超过一屏,逻辑分层一目了然。
- 命名自释,杜绝
a1,b2这类模糊词。 - 关键分支写注释,但不解释代码本身,而解释“为什么”。
前端 Vue 调用示例(Pinia + Axios):
export const useUserStore = defineStore('user', () => { const token = ref('') async function login(form: LoginForm) { const { data } = await axios.post('/api/login', form) token.value = data.data.token axios.defaults.headers.common['Authorization'] = `Bearer ${token.value}` } return { token, login } })性能 & 安全:别等老师提“SQL 注入”才 Google
- 注入防护:MyBatis-Plus 自带
#{}占位符,千万别用${}拼接。 - 密码哈希:BCrypt 强度 10 足够,明文=原罪。
- 接口幂等:选课、扣库存用数据库唯一索引
(student_id, course_id),重复点击直接抛DuplicateKeyException,前端捕获后提示“已选过”。 - XSS:富文本用 Markdown-it 渲染,关闭 HTML 标签;普通输入做转义。
- 限流:IP 级登录错误 5 次/分钟,Redis 计数器,低成本防暴力破解。
生产环境避坑:从“能跑”到“敢给人看”
- Git 提交:参考 Angular 规范,前缀
feat/fix/docs/,配合 issue 编号,方便回滚。
示例:feat: 选课接口增加库存校验 (#12) - 分支策略:master 保留稳定标签,dev 日常开发,feature 分支用完即删,合并用 PR,留下 code review 记录,答辩可加分。
- 配置分离:
application-dev.yml本地 H2,application-prod.yml云库 + 真实 Redis,防止本地调试把生产数据清空。 - 容器化:写个 20 行 Dockerfile,把 JAR 和 Vue 打包产物一起塞进去,docker-compose 一键
up,演示电脑无需装 JDK。 - 演示环境:云服务器 2C4G 足够,域名备案来不及就用 IP,Nginx 配 HTTPS 自签证书,浏览器点“高级”继续访问,老师不会较真。
可维护性思考:毕业不是终点
把基础功能跑完后,不妨再玩点“花活”:
- 日志接入 ELK,Kibana 大屏展示,答辩现场瞬间高大上。
- 用 Spring Batch 做成绩导入,演示 5 万条数据 30 秒跑完,老师点头“性能考虑得不错”。
- 前端加单元测试(Vitest),覆盖率 80% 以上,GitHub 徽章贴 README,评审专家一看就知道你懂工程化。
但谨记:先让主流程坚如磐石,再谈扩展。代码仓库结构清晰、README 步骤能复现、SQL 文件版本号对应 Git Tag,这些“枯燥”动作才是你未来三个月不失眠的底气。
结语:把“能跑”变成“能说”
本科毕设不是科研,是一次完整交付的演练:选题能自圆其说,技术栈能一行命令跑通,代码能当着老师的面单步调试。照着上面的最小闭环先落地,再按兴趣横向扩展,你会发现 8000 字论文只是“看图说话”,答辩成了“展示作品”,而不是“背诵概念”。祝你 6 周后把系统演示完,老师问“还有吗?”时,你能轻松回一句:“当然有,我给您开个新账号体验一下?”