苍穹外卖-DAY02

一、员工模块

1.新增

  • 设置默认token方便测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    https://www.jwt.io/
    jwt加解密

    https://tool.lu/timestamp/
    时间戳转换

    jwt校验
    try {
    log.info("jwt校验:{}", token);
    Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
    Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
    log.info("当前员工id:", empId);
    //3、通过,放行
    return true;
  • 简单增删改查

  • 异常处理

    com/sky/handler/GlobalExceptionHandler.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){

    // Duplicate entry '袁明' for key 'employee.idx_username'
    String message = ex.getMessage();
    if(message.contains("Duplicate entry")){
    String username = message.split(" ")[2];
    String msg = username + MessageConstant.ALREADY_EXISTS;
    log.error("异常信息:{}", msg);
    return Result.error(msg);
    }else {
    return Result.error(MessageConstant.UNKNOWN_ERROR);
    }
    }

    数据重复异常

  • ThreadLocal处理员工id

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
                log.info("jwt校验:{}", token);
    Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
    Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
    log.info("当前员工id:", empId);
    BaseContext.setCurrentId(empId);
    //3、通过,放行
    return true;

    employee.setCreateUser(BaseContext.getCurrentId());
    employee.setUpdateUser(BaseContext.getCurrentId());

    用户的每一次请求都当做一个线程

    ThreadLocal

    1. 隔离性:每个会员(线程)只能打开自己的储物柜,绝对看不到别人的柜子里装了什么。
    2. 随取随用:会员在健身房的任何角落(Controller、Service、Dao 层),只要想用,随时都能回柜子里拿东西。
    3. 用完即走:健身结束(响应完成),会员必须清空柜子,把钥匙还回去。

    ThreadLocal 为每个线程提供了一份独立的变量副本,互不干扰。

2.分页查询

  • 分析

  • 开发

  • 测试

  • 完善

PageHelper插件

MyBatis 的 XML配置中,resultType 指定的永远是 List 中每一个元素的类型,而不是 List 本身。

  • 不管你 Java 接口返回值是 List<Employee> 还是 Page<Employee>,对于 XML 来说,它只需要知道:“查出来的每一行数据,我要映射成哪个类?”
  • 答案就是 com.sky.entity.Employee

预编译问题

${} 的生命周期:

  1. Java端:like '%${name}%'
  2. MyBatis处理:直接把字符串拼好了 -> like '%张三%' (注意:此时还在 Java 内存里)
  3. 发送给数据库:select ... where ... like '%张三%'
  4. 数据库执行:正常执行,因为它看到的语法完全没毛病。

#{} 的生命周期:

  1. Java端:like '%#{name}%'
  2. MyBatis处理:变成占位符 -> like '%?%'
  3. 发送给数据库:select ... where ... like '%?%'
  4. 数据库编译:数据库认为 ' ' 里面的都是字面意思。
  5. 数据库填参:数据库找不到可以填参的地方(因为 ? 被引号屏蔽了),参数没法传进去,或者传进去也没用。

concat 的使用

1
concat` 是数据库的一个**内置函数**。 它的定义大概是这样的(伪代码): `String concat(str1, str2, str3)

所以,当 SQL 执行到 concat('%', '张三', '%') 时,这个函数会在数据库内部运行,运行完之后,它会吐出一个带单引号属性的结果(或者说是 String 类型的数据):'%张三%'

concat 函数本身就代表了一个字符串结果

时间处理问题

image-20260201171515524

3.启用与禁用员工账号

参数注解


模式一:【查】普通查询 / 搜索 / 分页

特点: 参数都在 URL 的问号 ? 后面。

  • 场景: 列表查询、分页、根据名字搜索。
  • 请求方式: GET
  • URL 样子: /employee/page?page=1&pageSize=10&name=张三
Java 写法 注解 适用情况 代码示例
单个参数 @RequestParam 参数少,想要默认值或强制必填 list(@RequestParam String name)
单个参数 (无) 参数少,变量名和 URL 一致 list(String name)
多个参数 (无) **最常用!**用 DTO 对象接收 list(EmployeePageQueryDTO dto)

⚠️ 死记: 这种模式下,绝对不要加 @RequestBody


模式二:【定】精准定位资源

特点: 参数直接嵌在 URL 路径里。

  • 场景: 删除某个人、查询某个人的详情、修改某个人的状态。
  • 请求方式: GET / DELETE / POST / PUT
  • URL 样子: /employee/101 (这里的 101 是 ID)
Java 写法 注解 适用情况 代码示例
路径变量 @PathVariable 只要参数在 / 之间 getById(@PathVariable Long id)

模式三:【增/改】提交复杂数据

特点: 参数看不见,藏在 HTTP 的 Body 里(JSON 格式)。

  • 场景: 新增员工、修改员工完整信息。
  • 请求方式: POST (新增) / PUT (修改)
  • URL 样子: /employee (干净,没参数)
Java 写法 注解 适用情况 代码示例
JSON 对象 @RequestBody 必须加! 前端传 JSON 时 save(@RequestBody EmployeeDTO dto)

⚠️ 死记: 只要是 JSON,必须加 @RequestBody,否则对象全是 null。