You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在REST调用中分离映射动态查询参数与Pageable信息?

问题描述

处理REST接口时,前端会在URL中传入page、size、sort等分页参数,以及数量不固定的动态查询参数。当前参数映射方式如下:

请求示例

http://localhost:8080/something/search?page=0&size=10&sort=applicationId,asc&applicationId=name1&applicationId=name2&reference=12345

参数映射代码

public ResponseEntity<Page<ObjectToReturn>> getObjectWithDynamicCriteria(Pageable pageable, @RequestParam MultiValueMap<String, String> params) 

当前问题

Pageable对象与MultiValueMap中同时包含分页相关信息:

Page request [number: 0, size 10, sort: applicationId: ASC]
params {page=[0], size=[10], sort=[applicationId,asc], applicationId=[name1, name2], reference=[12345]} 

需要处理MultiValueMap中的applicationId、reference等动态参数,但必须先移除其中的page、size、sort信息,希望让MultiValueMap仅保留动态查询参数。

解决方案

方法1:手动移除分页参数

这是最简单直接的方式,在方法内部直接删除MultiValueMap中的分页相关key:

public ResponseEntity<Page<ObjectToReturn>> getObjectWithDynamicCriteria(Pageable pageable, @RequestParam MultiValueMap<String, String> params) {
    // 移除分页参数
    params.remove("page");
    params.remove("size");
    params.remove("sort");
    
    // 处理剩余的动态查询参数
    // ...
    return ResponseEntity.ok(...);
}

如果不想修改原始参数Map,可以先复制一份再操作:

// 复制原始参数到新的Map
MultiValueMap<String, String> dynamicParams = new LinkedMultiValueMap<>(params);
// 移除分页参数
dynamicParams.remove("page");
dynamicParams.remove("size");
dynamicParams.remove("sort");

方法2:自定义参数解析器(适合多接口复用)

如果多个接口都需要过滤分页参数,可以自定义参数解析器,自动处理参数过滤:

  1. 定义自定义注解,标记需要过滤的参数:
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface DynamicQueryParams {
}
  1. 实现参数解析器:
public class DynamicQueryParamsResolver implements HandlerMethodArgumentResolver {
    // 定义需要过滤的分页参数集合
    private static final Set<String> PAGE_PARAMS = Set.of("page", "size", "sort");

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterAnnotation(DynamicQueryParams.class) != null 
                && MultiValueMap.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        MultiValueMap<String, String> dynamicParams = new LinkedMultiValueMap<>();
        // 遍历所有请求参数,过滤掉分页参数
        webRequest.getParameterMap().forEach((key, values) -> {
            if (!PAGE_PARAMS.contains(key)) {
                dynamicParams.put(key, Arrays.asList(values));
            }
        });
        return dynamicParams;
    }
}
  1. 注册解析器到Spring配置:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new DynamicQueryParamsResolver());
    }
}
  1. 在接口中使用自定义注解:
public ResponseEntity<Page<ObjectToReturn>> getObjectWithDynamicCriteria(Pageable pageable, 
                                                                         @DynamicQueryParams MultiValueMap<String, String> dynamicParams) {
    // dynamicParams中仅包含动态查询参数,无需手动处理分页参数
    // ...
    return ResponseEntity.ok(...);
}

方法3:利用Spring Data Querydsl自动处理动态查询(可选)

如果项目中使用Querydsl,可以借助Spring Data的特性,让框架自动转换动态参数为查询条件,同时分页参数由Pageable单独处理:

  1. 扩展Repository接口:
public interface ObjectToReturnRepository extends JpaRepository<ObjectToReturn, Long>, QuerydslPredicateExecutor<ObjectToReturn> {
}
  1. 在接口方法中使用@QuerydslPredicate:
@Autowired
private ObjectToReturnRepository repository;

public ResponseEntity<Page<ObjectToReturn>> getObjectWithDynamicCriteria(Pageable pageable, 
                                                                         @QuerydslPredicate(root = ObjectToReturn.class) Predicate predicate) {
    // 框架自动将前端动态参数转换为Predicate,分页参数由Pageable处理
    Page<ObjectToReturn> resultPage = repository.findAll(predicate, pageable);
    return ResponseEntity.ok(resultPage);
}

这种方式无需手动解析参数,适合复杂的动态查询场景。

内容的提问来源于stack exchange,提问作者BillUser88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:05:22