day8--- 苍穹外卖-day02

37 阅读3分钟

Day02 要完成的事(课程主线)

两个模块:员工管理 + 分类管理

员工管理实现 4 个核心功能:

  1. 新增员工
  2. 员工分页查询
  3. 启用/禁用员工账号
  4. 编辑员工(回显 + 修改)

分类管理:导入分类模块功能代码(并理解接口/表结构/关键校验)


一套通用开发套路(记住就能做 CRUD)

把系统想成一家店:

  • Controller = 前台接单(接收请求参数,返回结果)
  • Service = 店长做业务判断(默认值、校验、组装数据)
  • Mapper = 仓库管理员(真正查库/写库)
  • DTO = 前台写的“下单小票” (前端传来的数据)
  • Entity = 仓库里的“货物对象” (和数据库表对应)
  • VO = 给顾客看的“出餐结果” (返回给前端的数据)

1) 新增员工(最典型的“新增一条数据”)

做什么

employee 表插入一条员工记录。

关键业务规则(必背)

  • 用户名要唯一(重复会触发数据库唯一索引异常)
  • 密码默认 123456,并且要 MD5 加密后存库
  • status 默认启用(1)
  • createTime / updateTime 设置为当前时间
  • createUser / updateUser 不能写死,要取“当前登录人 id”

常见坑(最容易卡的点)

  • 接口返回 401:不是你代码没进 Controller,而是 JWT 校验没过
    ✅ 解决:先调登录拿 token,再带 token 调新增接口。
  • 用户名重复报错很丑:会抛 SQLIntegrityConstraintViolationException
    ✅ 解决:用全局异常处理把它转成友好的提示。

2) 员工分页查询(= “列表页 + 条件搜索”)

核心点

  • 前端传:page / pageSize / name(可选)
  • 后端返回:total + records

你要掌握的“分页三件套”

  1. DTO:EmployeePageQueryDTO
  2. PageHelper:PageHelper.startPage(page, pageSize)
  3. 统一返回:PageResult(total, records)

Mapper SQL 特点(动态 SQL)

在 xml 里用:

  • <where> + <if> 做条件拼接(name 为空就不拼)
  • order by create_time desc

3) 启用/禁用员工账号(本质是更新 status)

接口特征

  • 路径上带 status/status/{status}
  • 同时传 id(要改哪个员工)

业务上要记住

更新时除了 status,一般还要顺手更新:

  • updateTime = now
  • updateUser = 当前登录人

4) 编辑员工(两个接口合起来才叫“编辑”)

编辑其实分两步:

  1. 回显GET /{id}

    • 根据 id 查员工
    • 密码不要回显(讲义里做法是返回前把密码改成 "****"
  2. 修改PUT /admin/employee

    • 用 DTO 接收表单数据
    • BeanUtils.copyProperties(dto, entity)
    • 设置 updateTime/updateUser
    • Mapper 用动态 <set><if>:有值才更新(避免把空覆盖掉)

5) 分类模块功能代码导入(你要看懂“它在干嘛”)

分类模块通常包含 6 个接口:

  • 新增分类
  • 分类分页查询
  • 根据 id 删除分类
  • 修改分类
  • 启用/禁用分类
  • 根据类型查询分类

表:category(你至少要有印象:type/name/sort/status + create/update 信息)

一个很重要的业务点:

  • 删除分类前,往往要检查 有没有菜品/套餐引用这个分类
    所以会有 DishMapper / SetmealMapper 这类 countByCategoryId 的检查逻辑:
    count > 0 → 不允许删(避免删了分类导致菜品/套餐“挂空”)

JWT + ThreadLocal(重要)

你可以这样记:

  • JWT 像“入场手环” :证明你是谁
  • ThreadLocal 像“本次请求的胸牌” :把当前登录人的 id 放进去,整条链路都能随时取

流程是:

  1. 拦截器校验 JWT
  2. 解析出员工 id
  3. BaseContext(ThreadLocal) 保存当前 id
  4. Service 里需要 createUser/updateUser 时直接取

复习清单(自测 5 个问题)

  1. 新增员工时,哪些字段是“前端传的”,哪些是“后端补的默认值”?
  2. 分页查询为什么要 PageHelper.startPage()?它返回的 total 怎么来的?
  3. 为什么有时你打断点进不了 Controller?(提示:401 + 拦截器)
  4. ThreadLocal 在这个项目里到底解决了什么问题?
  5. 编辑员工为什么要拆成“回显 + 修改”两个接口?密码为什么要隐藏?