想在毕业设计这道坎上选一个“常见但又不太水”的题目,SpringBoot + Vue 的校园跑腿网站确实是个很稳的选项。它既不像纯管理系统那样只有增删改查,又不至于像分布式秒杀那样要压测、要消息队列、要 Redis 集群,难度刚好卡在一个本科生跳一跳够得着的位置。
这篇博文我按实际开发的顺序来讲,从需求拆解、数据库设计、后端接口、前端页面,到最后的部署和答辩准备,全部走一遍。适合正在做毕设、课设,或者想在小团队里快速搭出一套前后端分离项目的人参考。你要是只想要一个能过查重、能演示的完整系统,这篇内容可以直接照着落地。
先说结论:校园跑腿这个业务,核心就三句话——用户发单、骑手接单、跑完结算。把这三点做成闭环,系统就成立。剩下的全部是锦上添花。
1. 需求分析与技术选型:先想清楚再动手
很多人拿到题目就急着建工程,写了两天代码才发现订单状态不知道该设计成什么样,用户权限也乱成一团。这种问题根子不在编码,而在需求没有理清。
1.1 校园跑腿的“真需求”到底是什么
校园跑腿和美团、饿了么这类平台是有本质区别的。校内的配送半径小、用户群体固定、订单金额低,最典型的场景就是“宿舍楼下取快递”“食堂带饭”“超市代买”。因此系统设计不需要考虑复杂的运力调度,不需要算配送费,也不需要LBS实时派单,核心就是供需两侧的高效匹配。
我的用户角色拆分是三端:普通学生、跑腿骑手、系统管理员。普通学生要能发布订单、查看订单状态、取消订单、确认送达并评价;骑手要能浏览订单大厅、抢单、更新配送状态、查看自己的收入;管理员要能做用户审核、订单管理、公告管理、基础数据配置。
功能模块我最终收敛成这些:登录注册、个人中心、订单大厅、发布订单、接单/配送、评论、钱包充值、公告通知、后台管理。那些类似于“社交功能”“实时聊天”“路线规划”的,全部砍掉。不是不能做,而是做出来大概率会卡住进度,而且演示时根本不是评委关注的重点。
1.2 为什么选SpringBoot+Vue而不是其他组合
这个选型说实话有点“被生态推着走”的意思,但确实是目前国内Java后端项目里最稳的组合。
后端选SpringBoot,主要看中它的“约定大于配置”。以前用SSM框架写一个项目,XML配置文件能写到怀疑人生,SpringBoot通过自动配置把这些都简化了。再加上内置Tomcat,打一个Jar包就能跑,部署成本非常低。而且SpringBoot的生态太完整了,认证用JWT、持久层用MyBatis-Plus、文档用Swagger,几乎每踩一个坑都有现成方案。
前端选Vue,原因是它足够轻、文档亲民、社区资料多。Vue的响应式数据绑定和组件化开发让页面开发效率明显提升,Element UI / Element Plus一套组件库拿过来,后台界面的颜值立刻就有保障。相比React,Vue的上手曲线更平滑,遇到问题在中文搜索引擎里几乎都能找到答案。
这里要劝一句:除非你有特别强的理由,否则不建议在这个项目上引入微服务、分布式事务、消息队列这类重型组件。你是在做毕业设计,不是在做高并发的电商平台。技术栈应该为业务服务,而不是为了炫技把项目搞成四不像。
1.3 需要提前划清的边界
项目开始前,一定要把“能做”和“不做”写清楚,这是后期不烂尾的关键。
支付环节,我直接做成了“模拟支付”。也就是用户点击支付按钮后,系统默认支付成功并从余额中扣除,不接入真实微信/支付宝。原因很简单,个人开发者申请支付接口需要营业执照,而且真实支付涉及回调、证书、退款等一堆问题,不适合毕设场景。
定位环节,初期只用了校内热门地点的下拉选择,比如“1号宿舍楼”“图书馆”“东门菜鸟驿站”。如果要做地图选点,前端可以再集成腾讯地图或高德地图的JavaScript API,但这属于加分项而非必备项。
这些边界确定以后,项目一下子变得可落地了,至少不会在中期突然发现某个功能做不下去。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 架构设计与数据模型:先画图再写代码
我见过太多同学把数据库建得乱七八糟,用户表里放地址、订单表里放好评率,最后查询时全靠Java代码里各种循环赋值,效率极低。数据库设计是后端开发的骨架,这里省时间,后面一定加倍还回来。
2.1 前后端分离的工程结构与目录规划
我把项目分成了两个独立工程:
text复制school-runner-front
├── public
├── src
│ ├── api // 接口请求统一封装
│ ├── assets
│ ├── components // 公共组件
│ ├── router // 路由配置
│ ├── store // 状态管理(Vuex / Pinia)
│ ├── utils // 工具函数
│ ├── views // 页面组件
│ ├── App.vue
│ └── main.js
school-runner-server
├── src/main/java/com/example/runner
│ ├── config // 配置类(CORS、拦截器、MyBatisPlus)
│ ├── controller // 控制层
│ ├── service // 业务层
│ ├── mapper // 数据访问层
│ ├── entity // 实体类
│ ├── common // 统一返回体、异常处理、工具类
│ └── RunnerApplication.java
├── src/main/resources
│ ├── mapper // MyBatis XML文件
│ ├── application.yml
│ └── sql/init.sql
这个结构是当前Java后端项目最普遍的分层方式。控制层只接收参数和返回结果,业务逻辑全在Service层,数据操作在Mapper层。这样写的好处有两个:一是后期如果改了需求,只需要动对应层级的代码,不用满项目翻;二是答辩问“三层架构”的时候,你能讲得比书上的例子更实在。
2.2 核心数据表的设计与字段取舍
我的数据库一共有8张表,核心表如下:
| 表名 | 关键字段 | 说明 |
|---|---|---|
| user | id, openid, username, password, role, phone, avatar, balance, status | 其中role区分学生/骑手/管理员 |
| orders | id, order_no, user_id, rider_id, type_id, start_point, end_point, amount, commission, remark, status, create_time | 订单主表,状态字段最核心 |
| order_type | id, name, price, unit | 跑腿类型,如普通快递、代买急需品 |
| wallet_log | id, user_id, change_amount, balance, type, remark | 余额变动流水 |
| comments | id, order_id, user_id, rider_id, content, score | 订单评价 |
| notice | id, title, content, create_time | 系统公告 |
订单表里我单独把order_no提出来,不光是为了好看,而是考虑到用户可以按订单号查询,管理员也需要一个不暴露自增主键的单号来沟通。status字段我用tinyint存储,注释说明含义,因为订单状态在Java代码里会有对应的枚举类,数据库里存数字效率更高也更好维护。
有一张表我差点忘了写,后来才发现很关键:wallet_log。用户余额变动必须留下流水,不然用户说“我充过钱怎么没了”时,你连查证的方式都没有。流水表只做增加,不做更新和删除,这种表在业内叫“流水账”,设计原则就是只追加、不修改。
2.3 统一返回体与接口规范
接口返回格式如果不统一,前端处理起来就是一场灾难。一会儿{success:true, data:{}},一会儿{code:200, result:{}},前端每个请求都要单独判断。所以第一步就是定死返回体。
我的统一返回结构如下:
java复制@Data
public class Result<T> {
private Integer code;
private String msg;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMsg("操作成功");
result.setData(data);
return result;
}
public static <T> Result<T> error(St
