做校园跑腿这个项目,是我这几年看下来最经典的 SpringBoot + Vue 全栈练手选题之一。它不是那种“为了技术而技术”的空壳项目,而是真真切切能跑通完整业务闭环的系统:用户下单、跑腿员接单、配送完成、费用结算,再加上管理员后台,麻雀虽小五脏俱全。对于想找毕设方向或者想系统梳理前后端知识的人来说,这个题目能覆盖到的知识点非常密集,而且业务场景贴近生活,容易讲清楚,也容易演示。
这篇文章我会完全站在实际开发的角度,把这个项目的核心设计思路、表结构、状态机、前端的交互细节、以及我实测下来的高频 Bug 全部拆开来讲。不谈虚的,只说怎么做、为什么这么做,以及有哪些坑我已经替你们踩过了。
1. 项目整体设计与业务拆解
1.1 核心角色与业务定位
校园跑腿网站的业务模型不复杂,但角色划分必须清晰。我梳理下来,这个系统至少需要三类角色:
- 普通学生用户(下单方):发布跑腿需求,填写取件地点、送达地点、期望完成时间、小费金额,然后等待跑腿员接单。完成后可以确认收货并评价。
- 跑腿员(接单方):在接单大厅浏览可接的订单,按距离、价格、方向筛选合适的任务,接单后完成配送流程。这里通常涉及身份认证(比如学号验证、上传学生证照片),因为跑腿员信任度直接关系到平台安全。
- 管理员:负责审核跑腿员资质、处理用户投诉、下架违规订单、管理公告和系统参数(比如平台抽成比例、单笔最大金额限制)。
这个三角色模型看起来简单,但放到具体业务里就有很多细节。比如“余额充值”和“提现”怎么做?用户下单时是直接扣款冻结,还是跑腿员完成后从平台账户划转?我在设计时采用了“用户充值余额→下单冻结金额→完成后解冻划转给跑腿员”的方式,这样平台作为中间担保方,能有效降低双方的信任成本。跑腿员侧的“钱包”记录提现明细,管理员审核后打款,这套逻辑闭环是证明你系统设计能力的地方,也是答辩时老师最常追问的部分。
1.2 主业务流程与异常分支
整个系统的核心事务是“订单的生命周期”。正常流程是:
code复制用户发布订单 → 订单进入待接单池 → 跑腿员接单 → 跑腿员开始配送 → 跑腿员标记送达 → 用户确认收货 → 订单完成 → 资金解冻并结算
这中间有非常多的异常分支要处理。订单超时没人接单怎么办?跑腿员接了单但长时间不取货怎么办?用户临时取消订单怎么退款?跑腿员送到了一半用户联系不上怎么办?送达后发生争议由谁判定?
我建议在项目设计阶段就把这些状态变化做成一张订单状态机图,不是在文档里画完就完事,而是要真正映射到代码里。每个状态定义成一个枚举,所有状态流转都通过统一的 OrderService.changeState() 方法触发,里面做前置校验、状态记录、消息推送。我第一次做的时候图省事,直接在各处调用 orderMapper.update 去改状态,结果业务越写越乱,最后重构才明白状态机的价值。
1.3 单体架构还是微服务
很多同学一上来就问要不要用微服务,把Spring Cloud全家桶搬进来,Nacos、Gateway、OpenFeign全都上。我的建议非常明确:这种规模的校园项目,SpringBoot单体应用 + 模块化分包就是最优解。微服务带来的分布式事务、链路追踪、服务治理成本,在这个业务体量下完全没必要。你真正要做的是把包结构划分清楚,让代码具备可扩展性。
推荐的分包方式是按业务模块划分顶层包:
controller:接收 HTTP 请求,只做参数校验和结果封装,不写业务逻辑。service:业务逻辑层,所有状态变更、金额计算、事务控制写在这里。mapper:MyBatis 接口层,只负责数据库交互。entity:与数据库表对应的实体类。dto/vo:入参出参对象,避免直接暴露实体给前端。config:各类配置类,比如拦截器、跨域、支付回调、WebSocket。common:统一返回结果、异常处理、工具类、常量。
这样分层的好处是职责清晰,改动一个模块不会牵连其他模块。如果你的项目里还有定时任务(比如超时订单自动取消),建议单独建一个 task 包来放调度任务,不打乱整体结构。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与关键依赖
2.1 后端基础框架与版本选择
SpringBoot 版本选择是一个看起来不起眼、实际影响巨大的问题。我推荐的组合是 SpringBoot 2.7.x + JDK 8 + MyBatis-Plus 3.5.x,这个组合我用到现在踩坑最少。原因很简单:很多高校的课程实验环境和旧项目代码都基于 JDK 8,如果你选 SpringBoot 3.x,不仅强制要求 JDK 17,很多老版本的依赖(比如一些生成验证码、连接池的第三方库)还需要额外适配,排查起来非常痛苦。
另外,spring-boot-starter-web 和 spring-boot-starter-validation 是必备的。数据库连接池建议用 Druid,因为它自带监控页面,开发阶段看 SQL 执行情况很方便。在 pom.xml 里这样配:
xml复制<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.20</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
JWT 我用的是 jjwt 0.11.5 这个版本,注意它分为 api、impl、jackson 三个包,需要一起引入,否则运行时报 ClassNotFoundException。很多人在这里卡半天,其实只是少引了一个依赖。
2.2 分页插件与代码生成器
MyBatis-Plus 用起来确实提升效率,但注意分页插件必须显式配置,否则你调 selectPage 方法会发现分页完全不生效,它会把全部数据查出来再内存分页,数据量一大后端就卡死。我在 MybatisPlusConfig 里这样配置:
java复制@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor pagination = new PaginationInnerInterceptor(DbType.MYSQL);
pagination.setMa
