Week 1-8: Spring Boot 学习计划完整项目

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-29 23:45:17 +08:00
commit f95aa18724
201 changed files with 18595 additions and 0 deletions

241
week7/教案.md Normal file
View File

@@ -0,0 +1,241 @@
# Week 7前后端分离实战
**目标**:将 Vue 3 前端与 Spring Boot 后端完整对接,交付前后端分离的学生管理系统 v3。
**前置**:完成 Week 5Spring Boot 后端)和 Week 6Vue 3 前端基础)。
**本周产出**:前后端分离的完整 SPA 应用含登录注册、JWT 认证、CRUD、分页搜索、角色权限。
**启动方式**
```bash
# 1. 启动后端IDEA 中运行 Week7Application.java
# 2. 启动前端
cd week7/frontend
npm install # 首次运行
npm run dev # http://localhost:5173
```
---
## Day 1前后端分离架构设计
**知识点**
- 前后端分离 vs 单体架构:各自优劣
- 前端Vite 开发服务器5173→ 用户浏览器渲染
- 后端Spring Boot8080→ 只返回 JSON不渲染 HTML
- 通信方式HTTP + JSONJWT 无状态认证
- Vite proxy开发环境将 `/api` 请求代理到后端(解决跨域)
- 生产环境Nginx 反向代理,统一域名/端口
- CORSCross-Origin Resource SharingSpring Security 如何配置
**动手 → 理解**
1. 阅读 `vite.config.js``server.proxy` 配置,理解代理原理
2. 阅读 `SecurityConfig.java``corsConfigurationSource()` Bean
3. 在 DevTools Network 面板查看:`/api/students` 请求的远程地址是 5173 还是 8080
4. 对比 Week 5 的单体架构和 Week 7 的分离架构图
5. 把 Vite proxy 注释掉观察跨域错误CORS error
**核心文件**
- `frontend/vite.config.js``server.proxy`
- `backend/.../config/SecurityConfig.java` → CORS 配置
- `frontend/src/api/http.js` → Axios 实例
**思考题**前后端分离的核心优势是什么有什么代价首次加载速度、SEO
---
## Day 2登录注册页面 + JWT 对接
**知识点**
- 登录流程:表单输入 → Axios POST → 后端验证 → 返回 JWT → Pinia store 保存 → 跳转首页
- 注册流程:表单输入 → POST → 后端创建用户 → 返回 JWT → 自动登录
- Pinia Auth Store`token``username``role` 状态管理
- `localStorage`:持久化 Token页面刷新不丢失
- `<router-link>` vs 编程式导航 `router.push()`
- 导航守卫:`router.beforeEach()` 检查登录状态
- HTTP 拦截器:自动附加 `Authorization: Bearer <token>`
**动手 → 理解**
1. 打开 DevTools → Application → Local Storage观察 `wk7_token``wk7_username``wk7_role`
2. 在登录页输入错误密码,观察 Network 面板的 401 响应
3. 在 DevTools 中手动删除 Local Storage 的 token刷新页面观察跳转
4. 阅读 `router/index.js``beforeEach` 守卫逻辑
5. 注册一个新账号后,检查数据库中 users 表是否新增记录
**核心文件**
- `frontend/src/views/LoginView.vue` — 登录页面
- `frontend/src/views/RegisterView.vue` — 注册页面
- `frontend/src/stores/auth.js` — 认证状态管理
- `frontend/src/api/auth.js` — 认证 API
- `frontend/src/router/index.js` — 导航守卫
**思考题**:为什么 Token 存在 localStorage 而不是 Pinia store 中Pinia store 刷新后会丢失吗?
---
## Day 3CRUD 页面实现
**知识点**
- 列表渲染:`v-for` + Axios GET 请求
- 新增/编辑弹窗:`v-if` 控制显示,表单双向绑定 `v-model`
- 表单校验HTML5 原生校验 + 自定义 JS 校验
- 删除确认:`confirm()` + DELETE 请求
- 区分新增和编辑:根据是否传入 student 对象
- 角色权限:`v-if="auth.isAdmin"` 控制按钮显示
- 乐观更新 vs 悲观更新(操作后重新拉取数据)
**动手 → 理解**
1. 用 admin 登录,点击"新增",填写表单提交 → 观察 Network 面板 POST 请求
2. 点击"编辑",修改成绩后保存 → 观察 PUT 请求的请求体
3. 点击"删除" → 确认后观察 DELETE 请求,刷新页面确认数据消失
4. 用 user 登录,观察"新增/编辑/删除"按钮是否隐藏
5. 用 user 登录,在浏览器控制台执行 `fetch('/api/students', {method:'POST'})` 看 403
**核心文件**
- `frontend/src/views/StudentListView.vue` — 列表 + 表格
- `frontend/src/components/StudentForm.vue` — 表单弹窗props/emits
- `frontend/src/api/student.js` — CRUD API 调用
**思考题**:为什么不直接在表格行内编辑,而是用弹窗?各自适用什么场景?
---
## Day 4分页、搜索、排序
**知识点**
- 分页参数:`page`0-based`size`(每页数量)
- 前端分页 vs 后端分页:数据量决定策略
- 分页组件:首页/上一页/页码/下一页/末页 + 省略号逻辑
- 搜索防抖:`@keyup.enter` 触发搜索(避免每次按键都请求)
- 排序:后端 `ORDER BY` 实现MP LambdaQueryWrapper / JPA Sort
- URL 状态同步:搜索关键词和页码是否反映在 URL 参数中
**动手 → 理解**
1. 在搜索框输入"张",按回车 → 观察请求 URL 中的 `keyword` 参数
2. 点击分页组件的"下一页" → 观察 page 参数变化
3. 打开 `Pagination.vue`,理解省略号(...)的生成逻辑
4. 修改后端 `StudentMpService.list()` 中的排序字段为 `age` → 观察列表顺序变化
5. 在 Network 面板中对比:搜索前后 total 数量的变化
**核心文件**
- `frontend/src/components/Pagination.vue` — 分页组件
- `frontend/src/views/StudentListView.vue``search()` / `goPage()` 方法
- `backend/.../service/mp/StudentMpService.java` → LambdaQueryWrapper 排序
**思考题**:为什么页码从 0 开始Spring Data Pageable而不是从 1 开始?
---
## Day 5文件上传头像
**知识点**
- 前端:`<input type="file">` + `FormData`
- 后端:`MultipartFile` 接收文件
- Spring Boot 文件上传配置:`spring.servlet.multipart.max-file-size`
- 文件存储:本地目录 vs OSS对象存储
- 文件命名UUID 避免冲突
- 文件访问:静态资源映射 `addResourceHandlers()`
- 预览:上传后在前端显示缩略图
**动手 → 理解**
1. 在表单中增加 `<input type="file">` 字段
2.`FormData` 封装文件 + JSON 字段POST 到后端
3. 检查后端 `StudentController` 中的 `@RequestParam MultipartFile` 处理
4. 上传一个图片后,浏览器直接访问上传后的 URL
5. 尝试上传超大文件(>10MB观察 `MaxUploadSizeExceededException`
**核心文件**
- `frontend/src/components/StudentForm.vue` → 文件输入
- `backend/.../controller/StudentController.java` → MultipartFile 处理
- `backend/.../application.yml` → multipart 配置
**思考题**为什么不在数据库中存储文件二进制数据BLOB而是存储文件路径
---
## Day 6交互体验完善
**知识点**
- Loading 状态:数据加载中显示 spinner/骨架屏
- 错误状态:网络异常、后端报错时的用户提示
- 空状态:无数据时的友好占位
- 按钮 Loading提交时禁用按钮 + 显示"保存中..."
- Toast 消息:操作成功/失败的轻提示
- 乐观更新:先更新 UI 再发请求(失败时回滚)
- 防抖debounce和节流throttle
**动手 → 理解**
1. 强制停止后端,刷新前端页面 → 观察错误状态展示
2. 删除所有学生数据 → 观察空状态提示
3. 点击保存按钮时,快速双击 → 观察 loading 状态是否阻止了重复提交
4. 修改 `StudentListView.vue` 中的 loading 实现为骨架屏
5. 给搜索框加 300ms 的防抖
**核心文件**
- `frontend/src/views/StudentListView.vue` → loading / error / empty 三种状态
- `frontend/src/components/StudentForm.vue``formLoading` 按钮状态
**思考题**Loading、Empty、Error 三种状态分别应该在哪里处理(组件内 vs 全局)?
---
## Day 7前后端联调 & 部署概念
**知识点**
- 前后端联调:同时启动两个项目,确认所有接口正常
- Vite build生产环境构建 → 输出 `dist/` 目录
- Nginx 部署:反向代理将前后端统一到 80 端口
- Nginx 配置示例:`location /api { proxy_pass http://localhost:8080; }` + `location / { root dist/; }`
- 环境变量:`.env.development` vs `.env.production`
- Docker 部署概念:前端容器 + 后端容器 + Nginx 容器
- 部署检查清单数据库连接、Redis 连接、CORS 配置
**动手 → 理解**
1. 运行 `npm run build`,观察生成的 `dist/` 目录结构
2.`npx serve dist/` 预览生产构建
3. 用 Postman 测试后端所有 API 端点GET/POST/PUT/DELETE + Token
4. 画出完整的请求流程图:浏览器 → Nginx → 前端静态文件 / 后端 API
5. 阅读 Nginx 反向代理配置示例
**核心概念**
```
┌─────────────┐
│ 浏览器 │
│ localhost:80 │
└──────┬───────┘
┌──────┴───────┐
│ Nginx │
│ 端口 80 │
└──┬────────┬───┘
│ │
/ │ │ /api
│ │
┌─────┴──┐ ┌─────┴─────┐
│ dist/ │ │ Spring │
│ 静态 │ │ Boot:8080 │
└────────┘ └───────────┘
```
**思考题**Vite proxy 只用于开发环境,为什么生产环境要用 Nginx 而不是继续用 Vite proxy
---
## Week 7 总结
| 维度 | Week 5单体 | Week 6纯前端 | Week 7分离 |
|------|--------------|---------------|-------------|
| 前端框架 | 原生 HTML/JS | Vue 3 独立 | Vue 3 + 后端对接 |
| 页面路由 | 无 | Vue Router | Vue Router + 导航守卫 |
| 状态管理 | localStorage | Pinia 独立 | Pinia + API 同步 |
| 认证 | Login 页面display 切换) | 模拟登录 | JWT 真实认证 |
| 数据 | fetch 直连 | 无后端 | Axios + 拦截器 |
| 部署 | Spring Boot 单端口 | Vite dev | 前后端分端口 / Nginx |
**下一阶段Week 8 — 工程化能力**
- JUnit 5 + Mockito 单元测试
- Testcontainers 集成测试
- Knife4j API 文档
- Docker 容器化
- Git 工作流
- CI/CD 入门