java每日精进 5.15【分页实现】

一、前端分页实现

1.1 Vue 界面

前端使用 Element UI 的 Pagination 组件 实现分页,结合搜索功能,展示租户列表。代码位于 tenant/index.vue,以下是核心部分的分析和注释。

  • 搜索工作栏
    • 使用 创建搜索表单,绑定 queryParams 对象,包含分页和搜索参数(如 name、contactName、contactMobile、status)。
    • 每个 对应一个搜索条件:
      • name、contactName、contactMobile 使用 ,支持模糊查询。
      • status 使用 ,从字典 DICT_TYPE.COMMON_STATUS 获取状态选项(如 0=正常,1=停用)。
    • 搜索按钮触发 handleQuery,重置按钮触发 resetQuery。
  • 列表展示
    • 绑定 list 数据,显示租户列表,v-loading 控制加载状态。
  • 分页组件
    • 是 Element UI 的分页组件,显示当 total > 0 时。
    • 属性:
      • :total:总记录数,从后端返回。
      • :page.sync:绑定当前页码 queryParams.pageNo,双向同步。
      • :limit.sync:绑定每页条数 queryParams.pageSize,双向同步。
      • @pagination:页码或条数变化时触发 getList,重新查询数据。

JavaScript 逻辑

  • 数据初始化
    • queryParams 包含分页参数(pageNo、pageSize)和搜索条件。
    • total 和 list 用于存储后端返回的分页数据。
  • 查询逻辑
    • getList:调用 getTenantPage API,传递 queryParams,更新 list 和 total。
    • handleQuery:点击搜索按钮,重置 pageNo 为 1,调用 getList。
    • resetQuery:重置表单,重置后重新查询。
  • 加载状态:loading 控制表格的加载动画,提升用户体验。

1.2 API 请求

前端通过 system/tenant.js 定义 API 请求,调用后端分页接口。

import request from '@/utils/request'

// 获得租户分页
export function getTenantPage(query) {
    return request({
        url: '/system/tenant/page',
        method: 'get',
        params: query
    })
}
  • 功能:发送 GET 请求到 /system/tenant/page,携带 query 参数(包括 pageNo、pageSize 和搜索条件)。
  • 实现
    • request 是基于 Axios 的封装,处理 HTTP 请求。
    • params: query 将 queryParams 作为查询参数附加到 URL(如 /system/tenant/page?pageNo=1&pageSize=10&name=芋道)。
  • 响应:期待后端返回 CommonResult>,包含 list(租户列表)和 total(总记录数)。

二、后端分页实现

2.1 Controller 接口

后端使用 MyBatis Plus 的分页功能,结合二次封装的 PageResult 类实现分页。TenantController 定义了分页接口。

@Tag(name = "管理后台 - 租户")
@RestController
@RequestMapping("/system/tenant")
public class TenantController {

    @Resource
    private TenantService tenantService;

    @GetMapping("/page")
    @Operation(summary = "获得租户分页")
    @PreAuthorize("@ss.hasPermission('system:tenant:query')") // 权限校验
    public CommonResult> getTenantPage(@Valid TenantPageReqVO pageVO) {
        PageResult pageResult = tenantService.getTenantPage(pageVO); // 调用 Service
        return success(TenantConvert.INSTANCE.convertPage(pageResult)); // 转换并返回
    }
}
  • 功能:处理 /system/tenant/page GET 请求,返回租户分页数据。
  • 参数
    • @Valid TenantPageReqVO pageVO:分页和搜索参数,经过校验。
  • 逻辑
    • 调用 tenantService.getTenantPage 获取 PageResult
    • 使用 TenantConvert 将 TenantDO 转换为 TenantRespVO。
    • 封装为 CommonResult 返回。
  • 权限:@PreAuthorize 确保用户有 system:tenant:query 权限。
分页参数 PageParam

分页请求继承 PageParam 类,定义页码和每页条数。

@Schema(description = "分页参数")
@Data
public class PageParam implements Serializable {

    private static final Integer PAGE_NO = 1; // 默认页码
    private static final Integer PAGE_SIZE = 10; // 默认每页条数

    @Schema(description = "页码,从 1 开始", required = true, example = "1")
    @NotNull(message = "页码不能为空")
    @Min(value = 1, message = "页码最小值为 1")
    private Integer pageNo = PAGE_NO;

    @Schema(description = "每页条数,最大值为 100", required = true, example = "10")
    @NotNull(message = "每页条数不能为空")
    @Min(value = 1, message = "每页条数最小值为 1")
    @Max(value = 100, message = "每页条数最大值为 100")
    private Integer pageSize = PAGE_SIZE;
}
  • 解析
    • pageNo:页码,默认 1,校验非空且 ≥ 1。
    • pageSize:每页条数,默认 10,校验非空,范围 1-100。
    • 使用 @Schema 提供 OpenAPI 文档描述。
搜索条件 TenantPageReqVO

TenantPageReqVO 继承 PageParam,添加搜索条件。

@Schema(description = "管理后台 - 租户分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TenantPageReqVO extends PageParam {

    @Schema(description = "租户名", example = "芋道")
    private String name;

    @Schema(description = "联系人", example = "芋艿")
    private String contactName;

    @Schema(description = "联系手机", example = "15601691300")
    private String contactMobile;

    @Schema(description = "租户状态(0正常 1停用)", example = "1")
    private Integer status;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Schema(description = "创建时间")
    private LocalDateTime[] createTime;
}
  • 解析
    • 继承 pageNo 和 pageSize。
    • 搜索字段:name、contactName、contactMobile 支持模糊查询,status 支持精确匹配,createTime 支持时间范围查询。
    • @DateTimeFormat 解析时间字符串(如 2025-05-14 09:47:00)。
分页结果 PageResult

分页结果使用 PageResult 类封装。

@Schema(description = "分页结果")
@Data
public final class PageResult implements Serializable {

    @Schema(description = "数据", required = true)
    private List list; // 数据列表

    @Schema(description = "总量", required = true)
    private Long total; // 总记录数
}

解析

  • list:当前页的数据列表,泛型支持任意类型(如 TenantRespVO)。
  • total:总记录数,用于前端分页组件计算总页数。

2.2 Mapper 查询

后端使用 MyBatis Plus 的分页功能,TenantMapper 定义分页查询。

@Mapper
public interface TenantMapper extends BaseMapperX {

    default PageResult selectPage(TenantPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX()
                .likeIfPresent(TenantDO::getName, reqVO.getName()) // 模糊查询租户名
                .likeIfPresent(TenantDO::getContactName, reqVO.getContactName()) // 模糊查询联系人
                .likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()) // 模糊查询联系手机
                .eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) // 精确匹配状态
                .betweenIfPresent(TenantDO::getCreateTime, reqVO.getCreateTime()) // 时间范围查询
                .orderByDesc(TenantDO::getId)); // 按 ID 倒序
    }
}
  • 功能:执行分页查询,根据 TenantPageReqVO 的条件构建动态 SQL。
  • 逻辑
    • 使用 LambdaQueryWrapperX(MyBatis Plus 增强封装)动态拼接查询条件。
    • likeIfPresent:当字段非空时添加模糊查询(如 name LIKE '%芋道%')。
    • eqIfPresent:当字段非空时添加精确匹配。
    • betweenIfPresent:当 createTime 非空时添加时间范围查询。
    • orderByDesc:按 id 倒序排序。
  • 返回:PageResult,包含当前页数据和总记录数。
MyBatis Plus 分页封装

BaseMapperX 封装了 MyBatis Plus 的分页逻辑。

default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) {
    return selectPage(pageParam, null, queryWrapper);
}

default PageResult selectPage(PageParam pageParam, Collection sortingFields, @Param("ew") Wrapper queryWrapper) {
    // 特殊:不分页,直接查询全部
    if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
        List list = selectList(queryWrapper);
        return new PageResult<>(list, (long) list.size());
    }

    // MyBatis Plus 查询
    IPage mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
    selectPage(mpPage, queryWrapper);
    // 转换返回
    return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
}

解析

  • PageParam:提供 pageNo 和 pageSize。
  • IPage:MyBatis Plus 的分页对象,设置页码和条数。
  • MyBatisUtils.buildPage:将 PageParam 转换为 IPage。
  • 特殊情况:当 pageSize 为 PAGE_SIZE_NONE 时,查询所有数据。
  • 转换:将 IPage 的 records 和 total 转为 PageResult。

你可能感兴趣的:(Java每日进步,java,开发语言,spring,boot,jvm)