资讯动态

前后端分离校园外卖系统实战:SpringBoot+Vue+MyBatis全栈开发

发布时间:2026/10/20 8:06:59 来源:尧图企业网站定制
前后端分离的校园外卖服务系统技术栈锁定SpringBootVueMyBatisMySQL很多人第一眼看到这种项目会觉得是“老套路”但真正自己从零搭一遍才发现里面能踩的坑一点都不少。这个项目覆盖了用户端点餐、商家端接单、订单流转、地址管理、购物车合并、JWT登录鉴权这些完整闭环再加上前后端分离架构下的跨域处理、接口联调、打包部署非常适合用来练手或者作为毕业设计的核心框架。这篇博文我打算把整套系统从设计思路开始讲到数据库表结构、后端接口实现、前端Vue页面、最后到服务器部署全程带上源码级别的细节和排错经验希望对正在做类似校园系统或外卖服务的同学有点实际帮助。1. 为什么要做校园外卖系统场景痛点决定功能划分1.1 校园场景的特殊性校园和外部的商业外卖场景差别其实很大。首先用户高度集中宿舍区、教学区、食堂这几个地点覆盖了绝大多数订单配送范围短配送时间也相对集中基本就是你上午课程结束时和晚饭前这两个窗口期单量爆发。其次商家多样既有食堂窗口也有校内小餐馆和周边商户它们的菜品种类、出餐速度、价格区间差异很大这就对系统的商品分类和商家信息展示提出了要求而不是简简单单一个商品列表就能糊弄过去的。还有一个很实际的问题校园用户的作息规律非常强下单高峰几乎可以预测到分钟级这就意味着订单状态流转的效率很重要学生用户等不了太久商家端也必须能够快速看到新订单并及时处理。传统的电话点餐和微信群接龙在这个场景下效率极低商家经常漏单错单所以才需要一个前后端分离的Web系统来支撑整个点餐和接单流程。在做需求拆分的时候我建议按照角色来划分而不是按照功能模块来划分。这个系统的核心角色是三个普通学生用户、商家、系统管理员。学生用户关心的是能不能快速找到商家和菜品、加购物车、下单、看订单状态商家关心的是新订单提醒、更新菜品、修改价格、上架下架商品管理员关心的则更偏向于用户状态管控、商家入驻审核和数据统计。把角色理清楚之后再去设计接口和页面就会顺手很多。1.2 核心功能范围界定对于一个前后端分离的外卖系统功能范围不要一上来就铺得很大。大多数校园外卖项目的失败不是功能少而是功能太多导致后期根本做不完。我当时定的核心功能范围是用户端登录注册、浏览商家列表、按分类查看菜品、加购物车、查看购物车、提交订单、查看订单列表和详情、订单状态更新、收货地址管理商家端菜品管理增删改查、菜品上下架、订单管理查看新订单、接单、标记完成管理端用户禁用/启用、商家入驻审核、基础数据统计用户数、订单数支付功能我是建议先不做的直接用“模拟支付货到付款”的方式代替。原因很简单接入真实支付渠道需要商户号、证书、回调域名等等一套流程下来会把项目周期拖长很多而且对于学习性质的系统来说支付环节并没有带来多少架构上的价值。把支付状态设计成一个可以扩展的字段后续要接支付渠道时改起来也不费劲。1.3 哪些功能被刻意省略我特意省略了这几块内容优惠券系统、订单超时自动取消的定时任务、多商家购物车拆分、管理员后台的图表报表。这些功能不是不需要而是它们和核心流程的耦合度不高完全可以在主流程跑通之后再迭代。尤其是订单超时取消项目后期如果想要优化可以用SpringBoot的定时任务加上状态判断来处理核心逻辑就是查询超过一定时间仍未支付的订单把状态改成已取消并把库存释放这个不难但初期实现反而会分散精力。2. 技术选型SpringBootVueMyBatisMySQL的取舍理由2.1 后端为什么选SpringBoot如果从学习成本、生态成熟度、招聘市场需求三个维度去衡量SpringBoot在Java后端项目里还是最稳妥的选择。版本选择上我建议直接用SpringBoot 2.7.x系列不要一上来就上SpringBoot 3。原因很现实3.x版本要求JDK17起步一些旧版依赖和新版不兼容网上能搜到的解决方案大部分都是针对2.x的排错成本明显更高。2.7.x直接配JDK8或者JDK11在中国绝大多数教学环境和企业老项目里都是通行配置。SpringBoot带来的最大便利就是自动配置和Starter机制你只要在pom里引入spring-boot-starter-web、mybatis-spring-boot-starter、mysql-connector-java这些依赖再配好application.yml里的数据源信息一个能跑起来的服务基本上就有了。对于校园外卖这样的中小型系统来说SpringBoot默认内置的Tomcat完全够用不需要额外部署外置Tomcat打包成jar直接跑就行。2.2 前端为什么锁定VueVue的优势在校园项目场景里非常突出上手快、中文文档齐全、社区解决方案丰富。Vue2和Vue3之间的选择也是很多新手纠结的问题。我的建议是如果你从零开始写直接上Vue3加Composition API如果你是参考别人项目改造那大概率会遇到Vue2的老代码也不用急着升级稳定性优先。定位是学习练手选择哪种技术版本都行重点是搞懂数据流和组件通信。Vue前端通常配合Element UI系列组件库表格、表单、对话框、分页这些高频组件都有现成的不需要自己手写样式。整个前端项目通过Vite或者Vue CLI构建开发环境下用proxy代理解决跨域生产环境下编译成静态文件交给Nginx托管这也是前后端分离项目最标准的部署形态。2.3 MyBatis和MySQL的搭配理由MyBatis和MySQL的组合在校园类项目里占有率极高。MyBatis相对于Spring Data JPA来说SQL掌控力更强复杂多表查询时你可以在XML里直接写联表SQL即使不会写动态查询和复杂条件至少排查数据问题时更直观。MySQL作为数据库选型没什么好争论的免费、轻量、安装简单主流的云服务器都能轻松跑起来单表几百万数据量对这个项目来说完全不是瓶颈。我强烈建议用代码生成器来生成基础的实体类、Mapper接口和XML文件比如MyBatis Generator或者直接用IDEA插件。手动去写几十个表的实体和CRUD不仅效率低而且容易出错。项目重点应该放在业务逻辑的编排和接口的设计上而不是重复的增删改查代码。3. 项目结构与数据库设计地基决定上层建筑3.1 前后端分离的项目目录结构前后端分离项目在物理上就是两个完全独立的目录不要混在一起提交到同一个代码仓库的同一层级。我常用的目录结构是这样的campus-delivery/ ├── backend/ # SpringBoot后端 │ ├── src/main/java │ │ └── com/example/delivery │ │ ├── common/ # 通用类Result、异常处理 │ │ ├── config/ # 配置类跨域、拦截器 │ │ ├── controller/ # 控制层 │ │ ├── entity/ # 实体类 │ │ ├── mapper/ # MyBatis Mapper接口 │ │ ├── service/ # 业务层接口与实现 │ │ └── util/ # 工具类JWT、密码加密 │ └── resources │ ├── mapper/ # MyBatis XML映射文件 │ └── application.yml └── frontend/ # Vue前端 ├── src │ ├── api/ # 接口请求封装 │ ├── router/ # 路由配置 │ ├── store/ # 状态管理 │ ├── views/ # 页面组件 │ └── main.js └── vite.config.js后端采用传统的三层结构controller-service-mapper这个分层在中小型项目中已经非常成熟。前端按模块拆api层单独抽出所有请求方法view层只关注渲染和用户交互这样团队成员分工时可以各自开发互不阻塞。3.2 数据库表结构设计概览数据库设计是这个项目最值得花时间琢磨的地方。我先把核心表列举出来然后逐个说明设计原因和关键字段。user用户表CREATE TABLE user ( id bigint(20) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 登录名, password varchar(100) NOT NULL COMMENT BCrypt加密后的密码, phone varchar(20) DEFAULT NULL, avatar varchar(255) DEFAULT NULL, role tinyint(4) NOT NULL DEFAULT 1 COMMENT 1-用户 2-商家 3-管理员, status tinyint(4) NOT NULL DEFAULT 1 COMMENT 1-正常 0-禁用, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;用户表里用role字段区分三种角色比单独建管理员表和商家表要简洁很多。因为用户和商家很多基础字段是共通的比如登录名、手机号、状态合并在一张表里维护起来更方便。至于商家独有的信息比如店铺名、营业时间可以单独建business_info表通过user_id关联。business商家信息表CREATE TABLE business ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, name varchar(100) NOT NULL, image varchar(255) DEFAULT NULL, address varchar(255) DEFAULT NULL, notice varchar(255) DEFAULT NULL COMMENT 商家公告, status tinyint(4) NOT NULL DEFAULT 1 COMMENT 1-营业 0-打烊, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;菜品表dish和商家关联这里要注意价格字段不要用double精确到分的场景用decimal更可靠尤其后续如果涉及优惠计算浮点数误差会让人非常头疼。非法请求或者脏数据可能导致订单总额计算错误这一类线上问题通常很难发现。购物车表cart的设计很多新手会忽略用户和菜品的唯一约束。同一个用户把同一个菜品加入购物车应该执行的是更新数量而不是插入新记录。订单表orders和订单明细表order_detail是核心。订单表存总金额、订单状态、收货地址快照明细表存下单时的菜品快照。这里有一个非常重要的设计原则明细表里一定要冗余下单时的菜品名称和价格不能通过外键去关联菜品表实时查询。因为菜品价格以后可能调整如果用户下单后商家改了价格你再去菜品表查历史订单就会得到错误的数据。快照是把当时的交易现场固定下来这在订单类系统中是通用做法。3.3 关联查询与索引设计订单查询场景里最常见的SQL是根据用户id查订单列表再查这个订单下面的明细。这个场景需要给orders表的user_id加上索引order_detail表的order_id也加索引。商家端需要查自己名下的菜品、订单所以dish表的business_id和orders表的business_id也要建索引。别小看这几条索引校园外卖系统虽然数据量不大但高峰期并发查询时会明显感受到区别。索引缺失时MySQL会走全表扫描数据量一旦上万查询耗时就会从几毫秒飙到几百毫秒。另外我建议订单号不用自增id单独生成一个业务订单号。自增id暴露在接口里其实是一种安全隐患别人通过修改id就能遍历你的订单数据。业务订单号可以用当前时间加用户id和随机数的组合生成比如yyyyMMddHHmmss userId 四位随机数。我在实际项目中见过更优雅的做法是引入分布式ID组件但对这个小系统来说时间戳加随机数的组合已经足够。4. 后端核心实现接口设计与业务编排4.1 统一返回结果与业务异常体系前后端分离项目中后端返回给前端的数据一定要有统一的格式。我用的返回结构非常简单就是一个Result泛型类public class ResultT { private Integer code; // 200-成功 500-失败 401-未登录 private String message; private T data; // 静态方法 success/error }所有的Controller接口统一返回Result对象前端axios拦截器里拿到的也是这个结构判断code是否等于200来决定下一步操作。这样做的好处是错误处理逻辑可以完全收口前端不需要为每个接口单独写错误分支后端出现业务异常时也只需要抛出统一的异常对象。配合这个Result结构我还写了一个全局异常处理器用RestControllerAdvice注解标记分别拦截自定义业务异常、参数校验异常、其他兜底异常。尤其是运行时异常如果没有统一处理默认会返回SpringBoot的Whitelabel Error Page前端拿不到任何有效信息排错就变得非常困难。4.2 JWT登录鉴权与拦截器配置登录这块我没有用传统的Session方案而是用JWT生成令牌返回给前端前端每次请求在请求头里带上Token后端通过拦截器校验。选择JWT的理由是它天然适合前后端分离架构服务端不需要存储会话状态接口天然支持跨域而且后面的移动端扩展也能直接复用同一套鉴权逻辑。JWT工具类主要提供三个方法根据用户id生成Token、解析Token获取用户id、校验Token是否有效。生成时设置一个合理的过期时间我的建议是2小时到12小时之间。校园项目里学生使用场景往往集中在白天课间过期时间太短会导致用户频繁重新登录太长又会增加安全风险。拦截器的核心逻辑Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (request.getMethod().equals(OPTIONS)) { return true; // 放行预检请求 } String token request.getHeader(token); // 校验token解析失败则返回401提示登录过期 }拦截器里放行OPTIONS请求这个细节特别重要。跨域请求时浏览器会先发送一个预检请求如果拦截器把这个请求拦下来前端就会报跨域错误而且排查时容易误判为后端没做跨域处理。这种问题有个很明显的特征开发环境下接口偶尔能通偶尔报错刷新页面后第一次请求大概率失败实际上就是预检请求被拦截了。密码存储必须加密我建议用BCrypt。MD5和SHA这类散列算法已经很不安全了撞库和彩虹表攻击很容易破解。Spring Security的BCryptPasswordEncoder可以单独引入即使不用Security框架也可以只用它的加密工具类。4.3 核心业务流程购物车到生成订单从购物车提交生成订单是这个项目最核心的业务流程涉及到事务处理和多个表的联动。我在service层实现这个逻辑时事务注解Transactional是必须加上的否则中间任何一步失败都可能导致数据不一致。下单流程拆解如下第一步根据购物车id列表查询当前用户的购物车明细这里必须校验购物车里的菜品归属当前用户防止越权下单第二步遍历购物车明细联表查询对应菜品信息判断菜品是否在售如果某个菜品已经下架直接中断下单流程并提示用户第三步计算订单总金额这里踩了一个很常见的坑金额计算全部用BigDecimal乘以数量后累加最后作为订单总金额第四步插入订单主表订单状态设为待支付收货地址从用户默认地址快照进去第五步循环插入订单明细表记录菜品名称、单价、数量快照第六步删除用户对应的购物车记录订单完成这个流程里最容易出错的就是事务边界。很多人会把查询购物车和最后删购物车放在同一个方法里中间业务逻辑穿插网络调用或者耗时操作导致事务时间过长。MyBatis的默认配置一般不会主动开启Spring事务如果不加Transactional第一步插入了订单但第五步失败了就会出现只有订单没有明细的脏数据。4.4 MyBatis与XML映射的实际写法虽然现在有很多代码生成工具但核心SQL我还是建议手写。比如订单列表联查商家信息一句简单的LEFT JOIN就能避免前端再发一个查询商家信息的请求。我在OrderMapper.xml里这样写select idfindOrderWithBusiness resultTypecom.example.delivery.entity.OrderVO SELECT o.*, b.name as businessName FROM orders o LEFT JOIN business b ON o.business_id b.id WHERE o.user_id #{userId} ORDER BY o.create_time DESC /select动态SQL也是MyBatis的强项商家端订单列表需要按状态筛选我通常用if teststatus ! null标签来拼接条件。这些写在XML里比用注解嵌入SQL要清晰很多尤其条件多的时候后期维护难度完全不同。还有一个细节是resultType和resultMap的选择字段名和列名不一致时我会习惯用resultMap明确映射避免因为数据库列名下划线转驼峰没开配置导致字段全是null。4.5 跨域配置的正确姿势前后端分离开发时跨域是绕不开的问题。开发环境下Vite或Webpack的devServer里配置proxy代理最简单实际请求还是同源的。但生产环境下如果后端接口和前端静态页面不在同一个端口就需要后端主动支持跨域。SpringBoot里我写了一个WebMvcConfigurer配置类重写addCorsMappings方法允许的源和请求头全部显式配置。有一点要提的是允许的源不要直接用*。如果后端同时支持Token认证使用*和allowCredentialstrue会产生冲突浏览器会直接拒绝请求。我把origins配置成前端实际部署的域名或者开发环境的localhost端口这样既安全又能避免这类隐性问题。5. 前端Vue实现页面组织与工程化细节5.1 页面拆分与路由规划前端页面我按照角色区分为三个独立区域用户端、商家端、管理端。路由采用嵌套路由的方式共用布局组件侧边栏和导航栏根据当前登录用户的角色显示不同菜单。用户端的核心页面有商家列表、菜品浏览、购物车抽屉、订单确认页、订单列表、地址管理。商家端核心页面有菜品管理、订单管理。管理端的页面相对简单一个用户列表加一个商家审核页就够用。页面数量控制在十个以内时Vue Router的配置和维护还是很轻松的但要提前规划好懒加载不要所有页面一次性打包进主包否则首屏加载会很慢。5.2 Axios封装与Token管理Axios封装是前端工程化的第一步。我先新建了一个request.js文件创建axios实例设置baseURL、超时时间。请求拦截器里从localStorage取Token加到请求头。响应拦截器里统一判断后端的Result结构如果code是401就跳转登录页并清除本地Token。这样做的效果是所有页面代码里只要关心业务数据不用重复处理登录过期这类横切逻辑。Token存储位置我建议用localStorage而不是sessionStorage。虽然两者在安全等级上差不多但localStorage的持久性对用户体验更友好用户关闭浏览器再打开时不需要重新登录。当然这只是一个相对合理的选择如果要做得更安全可以配合登录后的滑动过期机制但对学习项目来说已经足够。5.3 组件通信与状态管理购物车是前端状态管理最典型的需求。加入购物车这个行为可能发生在商家列表页、菜品详情页购物车数据又需要在下单确认页、底部的购物车栏等多个组件里共享。我最初用组件的props和emit逐层传递页面一多就非常痛苦后来改成Pinia统一管理购物车状态从接口拉取的购物车数据存放在store里任何组件需要时直接引用修改时统一调用store的action。这才算真正把前端状态理清楚。需要提醒的是购物车数据的同步时机要明确。我的方案是登录后拉取一次每次加购成功后更新本地store同时调用后端接口同步。这样页面上即时反馈后端数据也不会丢失。5.4 前端路由守卫实现权限控制Vue Router的beforeEach路由守卫是控制页面访问权限的关键点。未登录用户访问需要登录的页面时直接重定向到登录页并带上redirect参数登录成功再跳回原页面。已登录用户但角色不匹配时跳转到自己的首页。这个逻辑不复杂但很实用而且必须在每个需要鉴权的页面的路由meta里标记需要的角色否则任何人都能通过URL直接访问商家管理界面。6. 完整部署教程从源码到线上可访问6.1 环境准备清单部署一套前后端分离项目需要准备好这些环境Linux服务器推荐CentOS 7以上或Ubuntu 20.04、JDK8或JDK11、Maven 3.6以上、MySQL 5.7或8.0、Node.js 16以上、Nginx。这里有一个实际建议JDK和Maven用yum或者apt安装有时版本不理想更推荐用tar包解压配置环境变量主动权完全在自己手里。部署前先做好两件事第一修改MySQL的root密码并创建项目的专用数据库账号不要把root密码直接写在项目配置文件里第二把前端的接口地址baseURL从开发环境的localhost改成生产环境的后端域名或IP。这一步经常被忽略导致前端打包后页面能打开但接口全部请求到本地看起来就是页面空白和数据加载失败。6.2 数据库初始化与配置数据库表结构准备好之后还有一个非常容易踩坑的地方时区配置。MySQL连接串里的serverTimezone参数本地开发可能用的是Asia/Shanghai服务器上如果配错或者不配数据库连接会直接报错即使连上也可能出现插入时间少了8小时的情况。我的建议是统一在JDBC连接串里加上serverTimezoneAsia/ShanghaiuseSSLfalsecharacterEncodingutf8省掉很多莫名其妙的时间问题。初始化表结构时如果用的MySQL8注意utf8mb4字符集要全链路保持一致。数据库、表、连接串三个地方都要配合否则中文极有可能出现乱码。排查乱码问题时先看表字符集再看连接串是否带了characterEncoding最后看前端页面有没有声明charset按照这个顺序查大概率能定位。6.3 后端打包部署后端打包前确认application.yml里MySQL地址、用户名密码与实际环境一致。密钥之类的敏感配置生产环境建议通过环境变量覆盖而不是直接写在配置文件里。打包命令很简单cd backend mvn clean package -DskipTests java -jar target/campus-delivery.jar --spring.profiles.activeprodjar包启动后先看启动日志有没有报错。SpringBoot启动成功会打印Tomcat started on port的日志。此时可以先在本机用curl测试接口是否通比如curl http://localhost:8080/api/user/info带上Token测试鉴权再通过Nginx反向代理对外提供服务。端口选择上后端服务不建议直接用80或者443端口保留给Nginx更合理。后端端口可以随意选一个比如8080Nginx监听80端口把请求转发到8080这样对外访问不暴露后端实际端口也方便后续多项目并存。6.4 前端构建与Nginx配置前端构建是部署里最容易出问题的一步。执行npm install时经常依赖安装失败建议用淘宝镜像源。Vue3项目构建cd frontend npm install npm run build构建成功后dist目录就是所有前端静态文件。把dist目录上传到服务器的某个路径比如/opt/campus-delivery/dist然后配置Nginx。Nginx配置注意两点第一root路径指向dist目录index选index.html第二前端路由使用history模式时必须配置try_files否则刷新页面会出现404这是一个极其经典的部署坑。配置如下server { listen 80; server_name your.domain.com; root /opt/campus-delivery/dist; index index.html; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }配置完成后nginx -t检查语法service nginx reload重载配置。前端通过/api这个前缀访问后端接口跨域问题在这里被Nginx的代理直接解决前端和后端服务器之间完全避免跨域。7. 常见问题与排查实录7.1 数据库连接失败与时区报错这个问题的特征非常明显启动日志里出现Communications link failure或者The server time zone value开头的报错。前者通常检查MySQL是否启动、账号密码是否正确、端口是否是3306后者则直接在JDBC连接串里补上serverTimezoneAsia/Shanghai。我排查这类问题养成了一个习惯先手动在服务器命令行里用mysql客户端连接数据库确认账号密码和远程访问权限都没问题再去看SpringBoot的日志避免把问题归结到代码上其实只是权限没开。7.2 Vue打包后刷新404这是history模式路由的经典问题。前端构建完用户访问首页正常但点击路由跳转没问题一旦手动刷新某个子页面比如商家列表就会出现404。原因就是Nginx找不到这个路径对应的物理文件。解决方案就是我上面提到的在location /里加try_files逻辑把所有路径回退到index.html让前端路由器接管路由解析。7.3 开发环境跨域配置后依然报错前端走了代理仍然报跨域大概率是代理没有生效或者接口baseURL没有走代理前缀。Vite开发环境中代理配置在vite.config.js的server.proxy里前端请求的是/api/xxx代理把/api开头的请求转发到后端。如果页面里直接请求了完整的后端地址比如http://localhost:8080/api/xxx那代理就完全不生效自然就报跨域了。记住一个原则开发环境所有请求都走相对路径由代理转发生产环境所有请求也都走/api前缀由Nginx转发。这样可以保证前后端的代码里只维护一个环境切换变量。7.4 JWT Token失效和用户仍然能访问接口这个问题很隐蔽。JWT令牌过期后前端应该在收到401响应时跳转登录页。但有些时候后端接口返回的不是401而是把业务异常正常返回了比如空指针异常统一包装成500前端拦截器只判断401其他错误码全部放行导致用户其实已经登录过期了还在正常浏览页面等到下单时才突然失败。解决思路是后端拦截器里识别出Token问题必须返回401前端响应拦截器看到401统一处理登录跳转中间不要做任何业务兜底。7.5 购物车数据不同步导致下单金额错误前端购物车展示数量和后端实际存储不一致通常是因为前后端各自维护了一份数据没有以服务端为准。我碰到过一个情况用户在两个浏览器标签页同时操作一个标签页加购另一个标签页下单最后结算时后端按最新购物车数据计算前端页面显示的还是旧数据。最终我把提交订单时的金额校验改成了以后端计算为准前端展示金额只作为参考提交后返回实际结算金额再让用户确认彻底解决了这个不一致问题。7.6 部署后静态资源请求404前端dist目录里的资源路径是绝对路径默认打包出来index.html引用的js和css路径是/assets/xxx.js。如果后端接口反向代理配置了静态资源路径的拦截或者base路径设置不对就会出现资源404。Vue3的Vite配置里可以通过base参数来调整。一般情况下只要Nginx的root路径配正确dist目录完整上传这个问题基本不会出现。有一次我把dist目录上传到了错误层级导致root路径指向了上一级目录页面打开是目录列表而不是应用这个细节很容易被忽略。8. 避坑经验与个人体会整个项目做下来我最大的感受是校园外卖系统这种项目技术含量不在于用了多新潮的框架而在于能不能把一套业务闭环完整地跑通。从数据库表设计到后端接口从Vue页面到Nginx部署每一个环节都有它自己的坑真正把它们逐个解决掉之后前后端分离架构的开发模式基本上就能融会贯通了。再分享一个实用的经验做这类项目时不要一头扎进写代码先花时间把表结构和接口文档定清楚。我用了两周时间写后端第一周其实只在做表和接口定义真正写业务代码速度反而不慢。接口返回数据结构的统一以及订单流程的状态流转需要绘制一张简单的状态表这些前期规划省下来的时间远超想象。比如订单状态我定义的是待支付、已支付/待接单、配送中、已完成、已取消看似简单但前端页面、后端逻辑和数据库字段全部都要围绕这套状态统一如果中途随便改前后端联调时的返工量会非常大。最后再补一个扩展方向我现在已经在这套系统基础上加了商家端的销量统计接口用MyBatis写了一条简单的分组合计SQL把每天的订单数和销售额统计出来前端接入一个图标库显示趋势图工作量很小但效果非常明显。如果你正在做类似的系统我强烈建议先把核心流程跑通并部署上线再考虑这些锦上添花的功能一个能访问的系统永远比一个写了一堆功能但跑不起来的东西更有价值。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑