跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

商铺分页查询逻辑导致前端滚动异常修复

商铺分页查询时前端滚动无响应及首页重复查询的问题。经排查,根源在于后端 Redis GEO 查询的 Limit 参数与前端分页大小不匹配,导致数据流截断异常。解决方案是调整后端 Service 层中的默认分页大小常量,确保 Redis 预查数据量足够支撑前端分页需求,从而修复了滚动加载失效的问题。

佛系玩家发布于 2026/4/5更新于 2026/10/25107 浏览
商铺分页查询逻辑导致前端滚动异常修复

问题描述

在商铺分页查询功能中,前端存在以下显示问题:

  1. 选择分类后往下翻不能自动滚动分页查询所有数据。
  2. 点击距离排序后,第一页数据被查询了两次,后续页面正常。

原因分析

经排查,根源在于后端 Redis GEO 查询的 Limit 参数与前端分页大小不匹配,导致数据流截断异常。Redis 预查的数据量不足以满足当前分页需求,造成前端滚动加载失效或重复请求。

代码实现

Controller 层

/**
 * 根据商铺类型分页查询商铺信息
 * @param typeId 商铺类型
 * @param current 页码
 * @param x 经度
 * @param y 纬度
 * @return 商铺列表
 */
@GetMapping("/of/type")
public Result queryShopByType(
        @RequestParam("typeId") Integer typeId,
        @RequestParam(value = "current", defaultValue = "1") Integer current,
        @RequestParam("x") Double x,
        @RequestParam("y") Double y) {
    // 调用 Service 层方法(修正方法名驼峰规范)
    return shopService.queryShopByType(typeId, current, x, y);
}

ServiceImpl 层

@Override
public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
    if (x == null || y == null) {
        // 直接返回对应类型的店铺就行了
        Page<Shop> page = query()
                .eq("type_id", typeId)
                .page(new Page<>(current, SystemConstants.DEFAULT_PAGE_SIZE));
        return Result.ok(page.getRecords());
    }

    int from = (current - ) * SystemConstants.DEFAULT_PAGE_SIZE;
       current * SystemConstants.DEFAULT_PAGE_SIZE;
        + typeId;

    
        (, Metrics.METERS);

    
    GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = stringRedisTemplate.opsForGeo()
            .search(key,
                    GeoReference.fromCoordinate( (x, y)),
                    distance,
                    RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                            .sortAscending() 
                            .limit(end) 
                            .includeDistance() 
                            .includeCoordinates()); 

    
     (geoResults ==  || geoResults.getContent().isEmpty()) {
         Result.ok(Collections.emptyList());
    }

    
    List<GeoResult<RedisGeoCommands.GeoLocation<String>>> pageGeoList = geoResults.getContent().stream()
            .skip(from) 
            .limit(SystemConstants.DEFAULT_PAGE_SIZE) 
            .collect(Collectors.toList()); 

    
    List<Long> shopIds = pageGeoList.stream()
            .map(geoResult -> Long.valueOf(geoResult.getContent().getName()))
            .collect(Collectors.toList());

     (shopIds.isEmpty()) {
         Result.ok(Collections.emptyList());
    }

       StringUtil.join(shopIds, );

    
    List<Shop> shopList = query().in(, shopIds).last(( + shopIdstr + )).list();

    
     (   ; i < pageGeoList.size(); i++) {
        GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = pageGeoList.get(i);
           shopList.get(i);
        
           geoResult.getDistance().getValue();
        shop.setDistance(distValue); 
    }

     Result.ok(shopList);
}
1
int
end
=
String
key
=
"geo:shop:type:"
// 2. 构造 5000 米的距离对象(核心:指定米为单位,5000m)
Distance
distance
=
new
Distance
5000
// 3. 完整的 GEO 圆形区域查询(补全所有参数)
new
Point
// 按距离从近到远排序(附近商户必备)
// 查询参数配置:按距离由近到远 + 预查足够数据(为后续分页准备)
// 核心:让 Redis 返回每个元素到圆心的距离
// 预查数据,避免分页漏条
// 4. 判空:geoResults 为空 或 无内容,直接返回空列表(修复原判空不完整问题)
if
null
return
// 5. 核心:Stream 分页(skip+limit)并接收结果,提取【商铺 ID+ 距离】
// 跳过前 from 条,实现分页
// 截取分页条数(一页的数量)
// 必须 collect 接收结果,否则跳过不生效
// 6. 提取商铺 ID(批量查库,替代循环单查,提升性能 10 倍+)
if
return
String
shopIdstr
=
","
// 7. 批量查询商铺详情(MyBatis-Plus 批量查,避免循环 eq 单查)
"id"
"ORDER BY FIELD(id, "
")"
// 8. 给商铺赋值距离(并保证 shopList 顺序和 pageGeoList 一致)
for
int
i
=
0
Shop
shop
=
// 距离转 Double,加非空判断(防止空指针)
Double
distValue
=
// 给 Shop 的 distance 字段赋值
return

解决方案

将 DEFAULT_PAGE_SIZE 的大小改为 5 以上即可解决上述分页与滚动异常问题。确保 Redis 预查数据量大于等于前端单次请求的分页数量,以支持连续滚动加载。

目录

  1. 问题描述
  2. 原因分析
  3. 代码实现
  4. Controller 层
  5. ServiceImpl 层
  6. 解决方案

更多推荐文章

查看全部
  • Web 创建与设计指南
  • 前端文件下载实战:从原理到最佳实践
  • 机器学习:网格搜索参数优化
  • AI 产品经理核心能力:技术模型与三大知识体系
  • 基于 AR 眼镜的 Android 亲戚称呼助手开发
  • Xilinx FPGA 外部 SPI Flash 启动时钟频率配置
  • Flutter 三方库 discord_interactions 的鸿蒙化适配指南
  • DeepSeek R1 论文核心机制与实验解析
  • macOS 安装 OpenClaw 实现 Chrome 网站自动化测试
  • 轻小说机翻机器人:日语小说自动翻译工具实现
  • Python 虚拟环境迁移难题:如何让 .venv 随项目文件夹随意搬家也不坏?
  • Stable Diffusion WebUI 云端环境搭建与参数调优实战
  • 智能电视芯片架构对比:ARM Cortex-A73 与 A55 性能差异
  • SQL 注入详解:从原理到实战
  • AI 辅助 FPGA 开发与 Vivado 配置实践
  • Hashcat 实战指南:从安装到高级密码恢复
  • C++ 多态:概念、实现与底层原理详解
  • Faster-Whisper 本地实时语音识别部署实战
  • Python 实现 MCP 客户端调用高德地图天气查询示例
  • CoPaw 个人助理部署与个性化配置实战指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online