从零到一跑通苍穹外卖:一个大二学生的暑假项目复盘

先说一下背景:我目前刚上大二,计算机相关专业。这个项目是我在大一升大二的暑假做的。在这之前,我学过Java和c基础语法,写过一些控制台小程序,学了一些前端三件套和vue,仅此而已。苍穹外卖是我第一个完整跑通的前后端分离项目。这篇文章记录的是我那个暑假一路摸索的真实过程。

一、为什么暑假要啃这个项目

大一由于还没开设java相关课程,我自己过了一遍Java se基础,但心里一直有个疙瘩:我写的代码全是在IDEA里跑的main方法,从来没有一个能打开浏览器看到页面的东西。

暑假回家前我给自己定了个目标:找一个完整的项目跟着做,不管多难,做出来一个能用的真正体会一下。

选苍穹外卖的原因很实际:B站上播放最多的完整前后端分离项目业务,应该有最完整的资源,不会做不出来。我当时想的是,跟着视频做,总不至于太难吧。

后来证明我还是太年轻了。

二、环境搭建:暑假前三天全耗在这了

  • MySQL :之前装过5.7,项目要求8.0。卸载重装,导入 sky.sql 的时候又报字符集错误,查了才知道要选 utf8mb4
  • Redis :Windows下没有官方安装包,下了个解压版。启动命令 redis-server.exe redis.windows.conf 每次都要开一个黑窗口挂着,后来才知道可以注册成系统服务
  • Nginx :解压后默认80端口,被系统占了,改成8081。然后前端页面能打开,但登录一直报500。查了一整天,最后发现是Nginx的 proxy_pass 转发地址写错了
  • 前端WebSocket:页面一直弹"服务器错误,无法接收实时报警信息"。那时候我还不懂什么叫反向代理,不知道WebSocket需要单独配转发规则。改了前端JS里的端口、重载了Nginx、清了浏览器缓存,折腾了好几个晚上

那几天我的浏览器历史记录全是CSDN、博客园和Stack Overflow。每解决一个问题就截一张图发朋友圈,现在回头看有点好笑,但当时那种"终于通了"的放松感是真的。

三、技术栈:边做边查,边查边记

这个项目用到的技术比我之前接触过的多了不少。暑假里我专门建了一个笔记文档,每碰到新东西就记一笔:

后端

技术 版本 我当时的理解过程
Java JDK 17 从8换到17,发现 var 关键字、switch表达式、Record类这些新特性
SpringBoot 3.1.2 之前只写过纯Java,第一次接触"约定优于配置",@SpringBootApplication 一个注解启动整个项目,很震撼
Spring MVC 内嵌 @RestController@RequestMapping 这些注解一开始死记硬背,后来才理解请求是怎么映射到方法的
MyBatis 3.x 之前用JDBC写过连接数据库,但手写SQL拼接太痛苦了。MyBatis的XML映射让我第一次觉得"ORM真香"
PageHelper 5.x 分页查询不用自己算 LIMIT 的偏移量了,加一行 PageHelper.startPage() 就行
MySQL 8.0 建表、写SQL、事务这些在学校学过,但索引优化、连接池这些完全是现学的
Redis 7.x 暑假前只知道"Redis是缓存",做完项目后理解了它还能做分布式锁、消息发布订阅、令牌存储
JWT (jjwt) 0.11.x 第一次接触"无状态认证"的概念,之前一直以为登录就是session存服务器
WebSocket Jakarta API 第一次写服务端主动推消息给浏览器的功能,理解了HTTP和WebSocket的区别
Knife4j 4.x 接口文档自动生成,写完Controller就能在网页上测试,比Postman方便
Lombok 1.18.x @Data 一个注解省掉所有getter/setter,当时觉得这是魔法
Jackson 内嵌 JSON和Java对象互转,前后端数据交互的桥梁
Apache POI 5.x 导出Excel报表,当时照着视频敲,后来自己研究了单元格样式怎么设置
Quartz 2.x 定时任务框架,用来自动处理超时订单。cron表达式我背了好久
Nginx 1.20.2 反向代理、负载均衡、静态资源托管,暑假里花了很多时间理解"为什么前端不直接连后端"

前端

技术 说明
Vue 2 管理端用的框架,暑假前完全没接触过。跟着视频看 datamethodsmounted 这些概念,慢慢能看懂了
Element UI 组件库,表格、表单、弹窗直接拖。我不用自己写CSS,但得知道怎么改样式
Axios 前端发HTTP请求用的,拦截器、请求头设置这些跟着视频配的
WebSocket API 浏览器端接收实时推送,和后端对应
微信小程序 C端用户端,WXML和WXSS的语法和HTML/CSS略有不同,暑假里跟着视频过了一遍

开发工具

IDEA(写Java)、Navicat(管数据库)、Postman(后来换成Knife4j)、PowerShell(操作Nginx和Redis)、Chrome开发者工具(F12看Network请求,虽然我笔记本按F12会打开计算器,得用Ctrl+Shift+I)

四、项目架构:从"看不懂目录"到"能讲给别人听"

暑假刚开始导入项目的时候,我看着 controllerservicemapperentitydtovo 这些包名完全不知道为什么一个"员工"要搞出这么多类。

后来每写一个模块我就强迫自己画一遍请求链路,画了五六遍之后才真正理解:

请求从浏览器到数据库的完整路径

bash 复制代码
浏览器 localhost:8081 输入账号密码点登录
        │
        ▼
  Nginx (监听8081)
  ├── 静态资源直接返回(HTML/CSS/JS)
  └── /api/* 请求 → proxy_pass 转发到 localhost:8080
                    │
                    ▼
            SpringBoot后端 (8080)
                    │
         ┌──────────┼──────────────┐
         ▼          ▼              ▼
    Filter      Interceptor      Controller
   (字符编码)   (JWT令牌校验)   (接收参数)
                    │                │
                    ▼                ▼
              ┌──────────┐     Service层
              │ 校验失败  │     (业务逻辑、事务)
              │ 返回401   │     │
              └──────────┘  ┌───┼───┐
                            ▼   ▼   ▼
                         Mapper Redis MySQL
                         (SQL) (缓存) (持久化)

我花了最长时间才搞懂的几个概念

DTO / VO / Entity 为什么要分开:

暑假里我一度觉得这是"过度设计"。后来自己写"新增员工"接口时才发现,前端传过来的参数(用户名、密码、姓名、手机号)和数据库表字段不完全对应,而且有些字段(比如密码)需要加密后再存。用DTO接收前端参数,用Entity映射数据库,中间在Service里转换,逻辑清晰很多。

为什么要有Service层:

刚开始我觉得Controller直接调Mapper就行了,为什么非得加一层Service?后来写"下单"功能时明白了------下单要同时操作订单表、订单明细表、购物车表、菜品库存表,还要发WebSocket通知。这些操作要么全成功要么全失败(@Transactional 事务管理),放在Service层统一管理才合理。

拦截器和过滤器的区别:

Filter是Servlet层面的,Interceptor是Spring层面的。JWT校验放在Interceptor里,因为需要用到Spring的容器(获取RedisTemplate)。这个区别我是踩了坑之后才记住的。

Redis在项目里的三个用途:

  1. 存JWT令牌黑名单(用户退出登录时把token加进去,拦截器校验时查)
  2. 存店铺营业状态(0/1,管理端可以切换,用户端查)
  3. WebSocket的Session管理(记录哪个商家端在线,有新订单时推送给对应的连接)

五、AI在暑假里帮了我什么

暑假做项目的时候,我大部分时间是跟着视频走的。但视频不可能覆盖所有问题,尤其是环境配置和报错排查。那时候我已经开始用AI工具了,说实话帮了不少忙。

帮我读懂报错信息:

IDEA控制台报红的时候,我以前的做法是复制第一行错误去百度搜。后来学会把整段报错贴给AI,它会帮我定位到关键行。比如那个WebSocket 404的问题,AI告诉我"404说明Nginx没把 /ws/ 请求转发到后端",一句话省了我两小时瞎试。

帮我解释概念:

视频里老师讲 @Transactional 的传播行为,一笔带过了。我追着AI问了好几轮:REQUIRED和REQUIRES_NEW到底什么区别、为什么同类方法互相调用事务不生效、什么情况下事务会失效。AI的回答比视频更细,而且我可以随时追问"为什么"。

帮我review自己写的代码:

暑假后期我开始尝试不跟视频、自己写一些接口。写完贴给AI让它帮我看,它指出过几次问题:比如我在Controller里直接调了Mapper没走Service(事务没生效),比如密码字段忘了加密,比如分页查询的 PageHelper.startPage() 放错了位置。

但也有帮不了的地方:

AI不能替我理解"为什么Nginx要配 proxy_set_header Upgrade 才能转发WebSocket"。这个东西我翻了Nginx官方文档、看了好几篇博客才搞明白。AI能给方向,但理解的过程还是得自己来。

六、手写代码还有没有必要

暑假里我确实动摇过。

有一次我让AI直接生成"员工分页查询"的代码,三秒钟出来了,能跑。但我看着那几行 LambdaQueryWrapper 的链式调用,完全不知道它在干什么------因为视频里教的是 PageHelper + XML 的写法。

从那以后我给自己定了个规矩:核心代码必须自己敲,AI用来辅助理解而不是代写。

我的做法是:先看视频理解思路 → 自己关掉视频凭记忆敲 → 卡住了再看一眼 → 敲完之后和视频对比 → 有空的话再让AI生成一版对比学习。

这样虽然慢,但暑假结束时我能不依赖视频,自己从零写一个"分类管理"模块的增删改查,包括Controller、Service、Mapper、XML全套。

我的感受是:手写的意义不在于记住语法,而在于建立"看到需求→想到实现方案→写出代码"这条链路。 ​ AI能帮你跳过中间步骤,但跳过的东西迟早会在调试的时候找回来。

七、暑假结束时的状态

项目做完那天,我截图发了条朋友圈。但说实话,真正让我有成就感的不是"跑通了",而是暑假最后几天我试着自己改了一个小功能------给"菜品管理"加了一个"按分类筛选"的查询条件,从改SQL到改前端请求参数全是我自己搞定的。

那一刻我知道,这个暑假没白费。

八、大二开学后的计划

现在上了大二,课表比大一满了不少。但我还是想保持自学的节奏:

复制代码
当前:✅ 苍穹外卖(暑假完成)
  ↓
本学期:SpringCloud Alibaba(Nacos、OpenFeign、Gateway、Sentinel)
  ↓
并行:MySQL深入(索引原理、Explain执行计划、慢查询优化)
  ↓
寒假目标:Redis深入(底层数据结构、缓存三大问题、分布式锁实战)
  ↓
大二下学期:JVM + 并发编程(这是校招面试重点,得认真啃)
  ↓
最终目标:大三前能独立设计一个中小型系统,从架构到部署全流程自己搞定

九、最后想说的

暑假做这个项目的时候,我妈好几次路过我房间看到我盯着屏幕发呆,问我是不是在打游戏。我说我在debug,她不懂,但那种"明明每一行代码都认识,合在一起就报错"的无力感,估计只有做过项目的人才懂。

如果你也是大一大二的学生,也在自学Java,也想找个完整项目练手,我的建议是:

别怕慢,别怕报错,别怕问AI,但也别让AI替你思考。

每一行你亲手敲出来的代码,都会变成你理解下一个概念的基础。暑假里那些让我头疼的报错,现在回头看都是最值钱的学习经历。


写这篇文章的时候,那个暑假的很多细节又浮上来了。如果你也在做苍穹外卖,或者也在自学路上,评论区可以交流。大二菜鸟互相鼓励,一起进步。

相关推荐
她的男孩1 小时前
账号锁定配了"错 4 次锁 30 分钟",我连错 100 次一次没锁上:扒完 4091 行认证源码,找到 5 个坑
java·后端·架构
程序猿乐锅1 小时前
【黑马点评 | 第二篇】Redis 缓存更新策略与商铺缓存实现
java·网络·redis·spring·mybatis
livemetee1 小时前
MySQL联合唯一索引(code,deleted)与逻辑删除问题
java·数据库
MacroZheng1 小时前
Redis官方发布高颜值可视化工具,功能更是强的离谱!
java·redis·后端
wuminyu1 小时前
纯轻量级锁体系下C2编译器锁粗化和消除机制剖析
java·linux·c语言·jvm·c++
ss2731 小时前
AI全栈实战 | 1.4-02 Spring AOP:@Transactional 失效的 N 种场景,根因其实只有一个
java·spring·ai编程
梦想平凡2 小时前
情怀棋牌源代码焕新记录(一):全新国风UI与原版工程梳理
java·服务器·数据库·websocket·网络协议·cocos2d
ba_pi2 小时前
springAI2.0接入mcp读取mysql
java·agent·spring ai
宸津-代码粉碎机2 小时前
Java面试核心:JVM三大GC垃圾回收算法原理与生产场景落地分析
java·大数据·人工智能·python·spring