苍穹外卖-day02

[!IMPORTANT]

新增员工

  1. 新增员工功能的整体流程是怎样的?
  2. 如何将前端提交的DTO对象转换为数据库实体对象?
  3. 新增员工时如何解决接口测试中JWT令牌校验失败导致的401错误?
  4. 如何处理用户名重复的异常?如何返回提示信息?
  5. 如何动态获取当前登录用户的ID来设置创建人和修改人?ThreadLocal在此处的作用是什么?

员工分页查询

  1. 分页查询功能的实现流程是怎样的?PageHelper插件的作用是什么?

  2. 返回结果中的时间格式不统一,如何全局处理日期格式化问题?

启用禁用员工账号

  1. 启用/禁用员工账号的流程是怎样的?

编辑员工

  1. 编辑员工功能的整体流程是怎样的?

  2. 如何实现数据回显?为什么要隐藏密码字段?

  3. 修改员工信息时,如何确保更新时间和修改人信息正确?

分类模块

  1. 菜品分类模块包含哪些核心功能?

  2. 删除分类时需要注意什么约束条件?

新增员工

  1. 新增员工功能的整体流程是怎样的?

    请添加图片描述

    1. 客户端发起一个 POST 请求,将前端填写的员工相关表单数据发送给后端。
    2. 后端的控制器接收到这个 POST 请求后,利用 @RequestBody 注解把请求体里的数据绑定到 EmployeeDTO 对象,完成数据封装。
    3. 控制器接着调用 Service 层的 save 方法,同时把封装好的 EmployeeDTO 对象作为参数传递过去。
    4. Service 层开始处理业务逻辑:
      1. 首先创建一个 Employee 实体对象,这将用于后续存储完整的员工信息。
      2. 运用 BeanUtils.copyProperties 方法,把 EmployeeDTO 对象中同名的属性复制到新创建的 Employee 实体对象里。
      3. Employee 实体对象设置账号状态,使用 StatusConstant.ENABLE 来表示该账号为启用状态。
      4. 对默认密码 "123456" 进行处理,通过 DigestUtils.md5DigestAsHex 方法对其进行 MD5 加密,然后把加密后的密码设置到 Employee 实体对象中。
      5. 获取系统当前时间,借助 LocalDateTime.now() 方法得到的时间作为 Employee 实体对象的创建时间。
      6. Employee 实体对象的最后修改时间初始化为与创建时间相同。
      7. 从线程局部变量里获取当前操作者的 ID,使用 BaseContext.getCurrentId() 方法,把这个 ID 设置为 Employee 实体对象的创建人 ID。
      8. 同样把该 ID 也设置为 Employee 实体对象的最后修改人 ID。
    5. Service 层调用持久层的 employeeMapper.insert 方法,把装配好所有信息的 Employee 实体对象插入到数据库中。
    6. 持久层完成插入操作后,将结果返回给 Service 层,Service 层再把结果返回给控制器。
    7. 控制器使用 Result.success() 方法,把成功标识和空数据体包装成统一的响应结构。
    8. 最后,控制器返回 HTTP 200 状态码给客户端,客户端接收到这个响应后,就确认员工信息创建操作已成功完成。
  2. 如何将前端提交的DTO对象转换为数据库实体对象?

    (1) 使用BeanUtils.copyProperties()方法,将DTO对象的属性拷贝到Entity对象中。

    (2) 然后手动设置Entity对象中DTO没有的字段(如状态、密码、创建时间等)。

  3. 新增员工时如何解决接口测试中JWT令牌校验失败导致的401错误?

    1. 在接口测试工具中,先调用登录接口获取JWT令牌。
    2. 将JWT令牌添加到全局请求头中。
    3. 确保每次请求都携带该令牌。
  4. 如何处理用户名重复的异常?如何返回友好提示信息?

使用全局异常处理器捕获SQLIntegrityConstraintViolationException → 提取异常消息 → 判断是否包含Duplicate entry关键字 → :按空格分割消息 → 提取索引为2的字段(如'zhangsan') → 去除单引号 → 拼接友好提示(用户名 zhangsan 已存在) → 返回统一错误响应(Result.error(msg));:返回未知错误提示。

潜在问题
错误的分割方式
依赖固定索引
应改用split空格或单引号
按单字符分割字符串 split
若数据库消息格式变化会崩溃
尝试获取split[2]作为用户名
捕获SQLIntegrityConstraintViolation异常
提取异常消息ex.getMessage
消息包含'Duplicate entry'?
拼接ALREADY_EXISTS常量
返回带具体错误信息的Result
返回UNKNOWN_ERROR常量
  1. 如何动态获取当前登录用户的ID来设置创建人和修改人?ThreadLocal在此处的作用是什么?

    动态获取

    1. 在JWT拦截器中解析令牌,获取当前用户ID。
    2. 将用户ID存入ThreadLocal(BaseContext.setCurrentId())。
    3. 在Service层通过BaseContext.getCurrentId()获取当前用户ID。

    ThreadLocal作用:为每个线程提供独立的存储空间,确保在同一次请求中共享数据(如当前用户ID)。


员工分页查询

  1. 分页查询功能的实现步骤是怎样的?PageHelper插件的作用是什么?

    前端 Controller层 Service层 Mapper层 数据库 传递分页参数和查询条件 封装为EmployeePageQueryDTO 调用分页查询服务 调用PageHelper.startPage()设置分页 执行动态SQL查询 发送SQL查询请求 返回查询结果 返回Page<Employee>分页对象 提取总记录数和数据列表,封装为PageResult 返回PageResult 封装为统一响应Result<PageResult> 返回统一响应 渲染分页数据 前端 Controller层 Service层 Mapper层 数据库

    流程:整体流程概述

    前端传递分页参数(页码、每页记录数)和查询条件,后端通过 Controller 层接收并封装参数,Service 层设置分页并调用 Mapper 层进行数据库查询,最后将查询结果封装返回给前端进行渲染。其中,PageHelper 可自动拦截 SQL 语句添加 limit 分页条件,简化分页逻辑。

    Controller 层

    1. 接收请求:接收来自前端传递的分页参数(页码、每页记录数)和查询条件。
    2. 参数封装:将接收到的参数封装为 EmployeePageQueryDTO 对象,以便后续传递给 Service 层进行处理。
    3. 调用服务:调用 Service 层的对应方法,将封装好的 EmployeePageQueryDTO 对象作为参数传入。
    4. 返回响应:接收 Service 层返回的处理结果,将其封装为统一响应 Result<PageResult> 并返回给前端。

    Service 层

    1. 设置分页:调用 PageHelper.startPage() 方法,根据 EmployeePageQueryDTO 中的页码和每页记录数设置分页信息。PageHelper 会自动拦截后续执行的 SQL 语句,在其中添加 limit 分页条件,从而简化手动编写分页逻辑的操作。
    2. 调用数据访问:调用 Mapper 层的方法,传入 EmployeePageQueryDTO 对象,执行数据库查询操作。
    3. 结果处理:接收 Mapper 层返回的 Page<Employee> 分页对象,从中提取总记录数和当前页的数据列表。
    4. 结果封装:将提取的总记录数和数据列表封装为 PageResult 对象,返回给 Controller 层。

    Mapper 层

    1. 执行动态 SQL 查询:根据 EmployeePageQueryDTO 中的查询条件,执行动态 SQL 查询。若包含姓名条件,则拼接 LIKE 查询语句进行模糊查询。
    2. 返回查询结果:将查询结果封装为 Page<Employee> 分页对象并返回给 Service 层。

    PageHelper作用

    自动拦截SQL语句,添加limit分页条件,简化分页逻辑。

  2. 返回结果中的时间格式不统一,如何全局处理日期格式化问题?

    1. 扩展Spring MVC的消息转换器,在WebMvcConfiuration中重写extendMessageConverters方法

      开始
      扩展消息转换器
      创建MappingJackson2HttpMessageConverter对象
      设置ObjectMapper
      将消息转换器加入容器
      结束
    2. 使用自定义的JacksonObjectMapper,统一设置日期格式为"yyyy-MM-dd HH:mm "。


启用/禁用员工账号

前端 Controller层 Service层 Mapper层 数据库 点击操作 URL: /status/{status}?id=1 提取路径参数`status` 隐式接收请求参数`id` 调用Service方法 传递`status`和`id` 构建`Employee`对象 设置`status`、`id` 补充`updateTime`(当前时间) 补充`updateUser`(当前操作人ID) 调用Mapper方法 传递`Employee`对象 执行动态SQL 更新`status`、`update_time`、`update_user` 返回影响行数 返回影响行数 返回影响行数 返回统一响应`Result.success()` 刷新状态 前端 Controller层 Service层 Mapper层 数据库

流程
前端点击操作 → URL路径参数传递状态值(/status/{status}) + URL请求参数传递员工ID(?id=1) → Controller层通过@PathVariable提取状态、隐式接收ID → Service层构建Employee对象(设置statusid补充updateTime(当前时间)和updateUser(当前操作人ID)) → Mapper层执行动态SQL(通过<set>标签更新status及审计字段update_timeupdate_user) → 数据库返回影响行数 → Controller层返回统一响应Result.success() → 前端刷新状态。


编辑员工

1. 编辑员工功能的整体流程是怎样的?

前端传递员工ID → Controller层调用employeeService.getById()查询员工信息 → 返回数据并回显到编辑页面 → 用户修改信息后提交 → 前端传递修改后的数据(EmployeeDTO) →Service层将EmployeeDTO转换为Employee对象 → Controller层调用employeeService.update() → Mapper层执行动态SQL更新 → 返回操作结果(Result.success()) → 前端刷新页面。

前端 Controller层 Service层 Mapper层 数据库 查询员工信息流程 传递员工ID 调用employeeService.getById() 传递员工ID 调用Mapper方法 查询员工信息 执行SQL查询 返回员工信息 返回员工信息 返回员工信息 返回员工信息并回显到编辑页面 更新员工信息流程 用户提交修改后的数据 传递EmployeeDTO 调用employeeService.update() 传递EmployeeDTO 将EmployeeDTO转换为Employee对象 调用Mapper方法 传递Employee对象 执行动态SQL更新 返回操作结果 返回操作结果 返回操作结果 返回统一响应`Result.success()` 刷新页面 前端 Controller层 Service层 Mapper层 数据库

2. 如何实现数据回显?为什么要隐藏密码字段?

  1. 前端请求员工信息(传递ID) → Controller层调用getById → Service层查询数据库 → 隐藏密码字段(setPassword("****")) → 返回Employee对象 → 前端渲染表单。。
  2. 隐藏密码字段
    • getById()方法中,将密码字段设置为****,避免敏感信息泄露。
    • 前端不需要显示或修改密码字段。

3. 修改员工信息时,如何确保更新时间和修改人信息正确?

  1. 更新时间:在Service层的update()方法中,手动设置updateTime为当前时间(LocalDateTime.now())。

  2. 修改人ID:通过BaseContext.getCurrentId()从ThreadLocal中获取当前登录用户ID,并设置为updateUser


分类模块

  1. 菜品分类模块包含哪些核心功能?
    • 新增分类
    • 分页查询分类
    • 根据ID删除分类
    • 修改分类信息
    • 启用/禁用分类
    • 分类类型查询(用于下拉列表)
  2. 删除分类时需要注意什么约束条件?
    • 约束条件:如果分类关联了菜品或套餐,则不允许删除。
    • 实现:在删除前检查关联关系,确保数据完整性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值