苍穹外卖笔记day2

第二天 员工管理、分类管理

gitee项目代码

第二节 – 员工分页查询

一、 需求分析和设计
产品原型:
业务规则:
  • 根据页码展示员工信息
  • 每页展示10条数据
  • 分页查询是可以更具需要,输入员工姓名进行查询
接口设计

data的里面有:tatal总的数据和recaords分页数据,分页数据下就是单表查询的内容。

二、代码开发
根据分页查询设计的DTO

位置:sky-pojo/src/main/java/com/sky/dto/EmployeePageQueryDTO.java

@Data
public class EmployeePageQueryDTO implements Serializable {
    //员工姓名
    private String name;
    //页码
    private int page;
    //每页显示记录数
    private int pageSize;

}
后面所有的分页查询,统一都封装成PageResult对象

位置:sky-common/src/main/java/com/sky/result/PageResult.java

/** * 封装分页查询结果 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
    private long total; //总记录数    private List records; //当前页数据集合
}

再把PageResult对象统一封装成Result对象,然后把Result转成Json格式,返回
给前端。数据格式:


代码实现:

  1. 在Ctroller层sky-server/src/main/java/com/sky/controller/admin/EmployeeController.java新增page方法。
/**
 * 员工模块 - 分页查询接口
 * 请求方式:GET
 * 请求路径:/admin/employee/page
 * 请求参数:EmployeePageQueryDTO 中的字段(如 page、pageSize、name 等)会以 URL 查询字符串形式自动封装
 * 返回结果:Result<PageResult> 统一包装类,里面包含总记录数、当前页数据列表
 */
@GetMapping("/page")    // 1. 只接受 GET 请求,映射路径 /page
public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO) {
    // 2. 打印请求参数,方便线上排查问题;使用 slf4j 的占位符写法,避免字符串拼接
    log.info("员工分页查询:参数为:{}", employeePageQueryDTO);

    // 3. 调用业务层 pageQuery 方法,拿到封装好的分页结果(总条数 + 当前页数据)
    PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);

    // 4. 使用统一返回包装类 Result 返回成功结果,前端拿到 json 结构:
    //    {"code":1,"msg":null,"data":{"total":100,"records":[...]}}
    return Result.success(pageResult);
}
  1. 在service接口层sky-server/src/main/java/com/sky/service/EmployeeService.java写pageQuery分页查询方法
  /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

3.在ServiceImpl实现类
一般我们查数据:select * from employee limit 0,10,但是我们已经封装好了Page为DTO,这样我们可以使用一些已经有的插件:PageHelper,我们只需要在pom.xml中导入即可:

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper}</version>
        </dependency>

ServiceImpl实现类sky-server/src/main/java/com/sky/service/impl/EmployeeServiceImpl.java

/**
 * 员工分页查询业务实现
 * 1. 利用 PageHelper 拦截下一次 SQL 执行,自动拼 LIMIT
 * 2. 调用 Mapper 进行条件查询,返回 MyBatis 的 Page 对象(继承自 ArrayList)
 * 3. 把 Page 对象里的 total/records 封装成自定义 PageResult 返回
 *
 * @param employeePageQueryDTO 封装了 page、pageSize、name 等查询条件
 * @return PageResult 统一分页结果(总条数 + 当前页数据)
 */
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
   // 1. 对 MyBatis 说:“接下来的第一条 SQL 要分页”
	//  ThreadLocal 里存了一个 Page 对象,记录页码、每页条数
	PageHelper.startPage(employeePageQueryDTO.getPage(),
                    employeePageQueryDTO.getPageSize());

	// 2. 执行 SQL,返回的 page 就是“装了 10 条数据 + 总条数”的盒子
	//  底层:MyBatis 拦截器把你的 SQL 后面自动拼上 LIMIT ?, ?
	Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

// 3. 从盒子里拿标签
	long   total   = page.getTotal();      // 总记录数 287
	List<Employee> records = page.getResult(); // 本页数据 10 条

// 4. 装进我们自己的统一返回对象
return new PageResult(total, records);
}
  1. Mapper层,/要获取动态sql,就不适用注解插入sql,可以写到映射文件里面去
    sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java
/**
     *  员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    // 要获取动态sql,就不适用注解插入sql,写到映射文件里面去
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

映射文件:sky-server/src/main/resources/mapper/EmployeeMapper.xml

<!-- 员工分页 + 条件查询 SQL 映射
     id:与 Mapper 接口中的方法名 pageQuery 一一对应
     resultType:查询结果直接封装成 com.sky.entity.Employee 实体 -->
<select id="pageQuery" resultType="com.sky.entity.Employee">
    SELECT * FROM employee
    <!-- <where> 标签会自动处理多余的 AND/OR,并生成 WHERE 关键字 -->
    <where>
        <!-- 只有当 name 不为 null 且不为空字符串时才拼接模糊查询条件 -->
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
    </where>
    <!-- 按创建时间倒序,保证最新创建的员工排在前面 -->
    ORDER BY create_time DESC
    <!-- 注意:分页语句 LIMIT ?,? 由 PageHelper 拦截器自动追加,这里不需要手写 -->
</select>

能否扫描到映射文件?在yml文件里面,已经配置好了classpath:mapper/*.xml就可以扫描到。
在这里插入图片描述

三、功能测试

可以通过swagger接口文档进行测试,也可以进行前后端联调测试,最后操作视角字段展示有问题,如下:

通过Swagger接口文档测试:
  1. 运行项目,debug运行,在员工分页查询(http://localhost:8080/doc.html#/default/员工接口文档/pageUsingGET)接口文档 →调试 →请求参数下,输入page值和pageSize值,点击发送。
    在这里插入图片描述
  2. 我们在响应内容暂时没有,我们需要到控制台查看,因为有log.info,但是我们也没有看到,接口文档中的响应内容报401
    在这里插入图片描述
  3. 原因:我们jwt令牌的有效时间是7200秒=2小时,所以2小时后jwt令牌的token会失效。
    在这里插入图片描述
  4. 解决方法:在员工登录处,重新登录一下,复制新生成的令牌在这里插入图片描述
  5. 然后在 文档管理 →全局参数设置中粘贴刚刚我们复制的jwt临牌的token值过去,然后再关闭所有标签
    在这里插入图片描述
  6. 重新进入 员工相关接口 → 员工分页查询 →调试 →请求参数,点击发送,获取到分页内容。
    在这里插入图片描述
四、功能完善
问题1:时间格式:数组

前端时间格式不直观,不符合我们可读格式,这里格式呈现的是数组格式。
在这里插入图片描述
解决方法:

方式一:在属性上加入注释,对日期进行格式化

在这里插入图片描述
在这里插入图片描述
重启项目,在接口文档重新发送分页信息,查看显示的时间,对比,添加了注解的和没有添加注解的
在这里插入图片描述

方式二:在WebMvcConfiguration中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理(本项目推荐)
  1. 在我们的sky-server/src/main/java/com/sky/config/WebMvcConfiguration.java文件中 WebMvcConfiguration继承了WebMvcConfigurationSupport父类,我们只需要重写WebMvcConfigurationSupport的一个方法:extendMessageConverters扩展消息转换器
    /**
     * 扩展Spring MVC框架的消息转换器(JSON 刷子)
     * 目标:统一返回格式、时间转字符串、中文不乱码、null 也显示
     * @param converters
     */
       protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        // 1. 创建一个消息转换器对象:造一把“新刷子”——专门刷 JSON 的转换器
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        // 2. 需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象转化为json数据
        //   给刷子装上“定制笔芯”——我们写好的 JacksonObjectMapper
    		 //   JacksonObjectMapper 里已经配好:
    		 //   • 日期格式 yyyy-MM-dd HH:mm:ss
        converter.setObjectMapper(new JacksonObjectMapper());

        // 3. 将自己的消息转换器加入容器中
        //   把新刷子插到工具箱最前面(索引 0)
    		 //   Spring 会按顺序找转换器,找到我们的就直接用,不再用默认老刷子
        converters.add(0, converter);
    }

在这里插入图片描述
2. 这个JacksonObjectMapper类在我们的sky-common/src/main/java/com/sky/json/JacksonObjectMapper.java中,规定日期格式

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    //public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

  1. 自己创建的消息转换器需要加入到转换器里面才会生效converters.add(0, converter);
    验证:添加断点,运行后,查看converters,size为8,共有8个消息转换器,我们继续单步运行到90行
    在这里插入图片描述
    可以看到,我们刚刚新增的消息转换器加入到了容器中,位置在0,共有9个消息转换器。
    在这里插入图片描述
  2. 放行,启动完成后,在员工接口文档→员工分页查询页面,再次点击发送。我们可以看到我们的响应内容,已经符合我们的可读格式
    在这里插入图片描述
    在前端我们也可以看到,时间符合我们的可读格式。
    在这里插入图片描述
🙋‍ 学习知识,内容讲解

1. 先搞懂 下面的核心概念

名词 作用
HttpMessageConverter Spring 的“数据翻译器”——把 Java 对象 ⇄ JSON(前后端互相能看懂)。
MappingJackson2HttpMessageConverter 官方提供的“JSON 翻译官”,底层靠 Jackson。
ObjectMapper Jackson 的“大管家”:负责 序列化/反序列化 规则
JacksonObjectMapper 我们自己继承 ObjectMapper 并写好配置的“翻译官笔芯”。是自定义的词典(规定日期格式、遇到未知字段别报错等)。
extendMessageConverters SpringMVC 专门留给用户的“插刷子”口子;只要添加就会优先使用

2. 自定义词典里写了啥(JacksonObjectMapper

规则 作用 例子
FAIL_ON_UNKNOWN_PROPERTIES = false JSON 里多出来的字段不报错 前端多传了 "xxx":123" 也能接受
注册 SimpleModule 告诉 Jackson 如何翻译 LocalDateTime / LocalDate / LocalTime 日期统一格式 yyyy-MM-dd HH:mm
加序列化器 & 反序列化器 出→ Java 变 JSON 用 LocalDateTimeSerializer
入→ JSON 变 Java 用 LocalDateTimeDeserializer
避免写成时间戳
  1. 不写会怎么样?
    | 不写 | 写了 |
    | ---------- | --------------------------- |
    | 时间戳 long | 可读字符串 “2024-06-18 12:00:00” |
    | null 字段被忽略 | null 字段也返回,前端不报错 |
    | 可能出现中文乱码 | 强制 UTF-8,中文正常 |
    | 全局格式不统一 | 整个项目返回 JSON 风格一致 |
员工分页查询的完整流程:
  阶  段    位置(文件/类 ) 关键代码/动作 输入→输出 时间格式
处理说明
1. 浏览器发请求 前端JS axios.get('/admin/employee/page', {params:{name:'',page:1,pageSize:2}}) 仅分页参数
page=1 &
pageSize=2
不传时间;createTime/updateTime由后端直接返回数组
2. 接收参数 EmployeeController page(EmployeePageQueryDTO dto) QueryString→DTO字段 无,普通字符串/数字
3. 查询入口 EmployeeController

EmployeeService
employeeService.
pageQuery(dto)
DTO→PageResult 日期字段未上传,
使用数据库值
4. 分页插件 EmployeeServiceImpl PageHelper.startPage
(dto.getPage(),
dto.getPageSize())
设置LIMIT 无时间处理
5. 条件查询 EmployeeMapper.xml <select id="pageQuery">
<if test="name!=null and name!=''">
SQL带模糊查询 无时间参数
6. 结果封装 EmployeeMapper

EmployeeServiceImpl
Page<Employee> page=
employeeMapper.
pageQuery(dto)
数据库行→List<Employee> 数据库DateTime字段被MyBatis自动映射成Java LocalDateTime
7. 返回前端 EmployeeServiceImpl

EmployeeController
return new PageResult(
page.getTotal(),
page.getResult())
Java对象→JSON 对象里已是LocalDateTime
8. 统一序列化 WebMvcConfiguration
+
JacksonObjectMapper
LocalDateTimeSerializer LocalDateTime→"2025-11-09 16:46" Jackson按yyyy-MM-dd HH:mm把LocalDateTime转成字符串输出
9. 浏览器收到 前端表格组件 res.data.records JSON字符串→表格列 时间从数组变为"yyyy-MM-dd HH:mm"直观格式

时序图(简化)

浏览器 EmployeeController EmployeeServiceImpl PageHelper EmployeeMapper DB GET /admin/employee/page?name=&page=1&pageSize=2 pageQuery(dto) startPage(1,2) pageQuery(dto) SELECT ... FROM employee ORDER BY create_time DESC LIMIT 0,2 List<Employee> (DateTime→LocalDateTime) Page<Employee> PageResult(total, records) JSON {"total":...,"records":[{"createTime":"2025-11-09 16:46"}]} 浏览器 EmployeeController EmployeeServiceImpl PageHelper EmployeeMapper DB
提交代码

Git →commit,输入“员工分页查询业务代码开发”,点击Commit and Push…
在这里插入图片描述
然后Push
在这里插入图片描述
显示已提交,提交完成
在这里插入图片描述
gitee上刷新,显示刚刚push的文件。
在这里插入图片描述

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐