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

Spring Boot中如何接收多组Query参数为对象列表并校验

解决思路与方案

Spring MVC默认的集合对象绑定需要索引式参数名(如sortList[0].sortBy),而你的请求参数是平级重复的sortBy和sortDirection,因此无法自动映射为List<PageSort>。以下是三种可行的解决方法:

方案一:调整请求参数格式(零后端代码修改)

直接修改请求参数为Spring默认支持的集合绑定格式,原控制器代码无需改动:

localhost:8081/api/projects?page=2&size=3&sortList[0].sortBy=projectName&sortList[0].sortDirection=desc&sortList[1].sortBy=startDate&sortList[1].sortDirection=asc

方案二:手动接收参数并转换(无需修改请求格式)

分别接收sortBy和sortDirection的列表,手动组装为List<PageSort>,同时保留校验逻辑:

@GetMapping
public ResponseEntity<ApiResponseDTO> getProjects(
        @Valid ProjectPage projectPage,
        @RequestParam List<String> sortBy,
        @RequestParam List<String> sortDirection,
        @Autowired Validator validator) {

    // 校验参数数量一致性
    if (sortBy.size() != sortDirection.size()) {
        throw new IllegalArgumentException("sortBy与sortDirection参数数量不匹配");
    }

    List<PageSort> sortList = new ArrayList<>();
    for (int i = 0; i < sortBy.size(); i++) {
        PageSort pageSort = PageSort.builder()
                .sortBy(sortBy.get(i))
                .sortDirection(sortDirection.get(i))
                .build();

        // 触发PageSort的注解校验(如@SortValueConstraint)
        BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(pageSort, "sortList[" + i + "]");
        validator.validate(pageSort, bindingResult);
        if (bindingResult.hasErrors()) {
            throw new MethodArgumentNotValidException(null, bindingResult);
        }

        sortList.add(pageSort);
    }

    // 后续业务逻辑处理
    return null;
}

方案三:自定义参数解析器(优雅适配原请求格式)

通过自定义HandlerMethodArgumentResolver,让Spring MVC直接支持平级参数到List<PageSort>的绑定:

1. 定义标记注解(用于指定需要解析的参数)

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface SortListParam {
}

2. 实现参数解析器

@Component
public class PageSortListArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private Validator validator;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(List.class)
                && parameter.hasParameterAnnotation(SortListParam.class)
                && PageSort.class.equals(GenericTypeResolver.resolveTypeArgument(parameter.getParameterType(), List.class));
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String[] sortByArray = webRequest.getParameterValues("sortBy");
        String[] sortDirectionArray = webRequest.getParameterValues("sortDirection");

        if (sortByArray == null || sortDirectionArray == null || sortByArray.length != sortDirectionArray.length) {
            throw new IllegalArgumentException("sortBy与sortDirection参数数量不匹配");
        }

        List<PageSort> sortList = new ArrayList<>();
        for (int i = 0; i < sortByArray.length; i++) {
            PageSort pageSort = PageSort.builder()
                    .sortBy(sortByArray[i])
                    .sortDirection(sortDirectionArray[i])
                    .build();

            // 执行参数校验
            BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(pageSort, parameter.getParameterName() + "[" + i + "]");
            validator.validate(pageSort, bindingResult);
            if (bindingResult.hasErrors()) {
                throw new MethodArgumentNotValidException(parameter, bindingResult);
            }

            sortList.add(pageSort);
        }
        return sortList;
    }
}

3. 注册解析器到Spring MVC

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private PageSortListArgumentResolver pageSortListArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(pageSortListArgumentResolver);
    }
}

4. 修改控制器参数

@GetMapping
public ResponseEntity<ApiResponseDTO> getProjects(
        @Valid ProjectPage projectPage,
        @Valid @SortListParam List<PageSort> sortList) {
    // 直接使用sortList即可
    return null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:54:52