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
相关产品推荐
相关产品推荐

