如何将多个请求参数分组为@RestController方法的单个参数
解决方案:用
@ModelAttribute替代@RequestParam绑定DTO 核心问题原因
用@RequestParam注解DTO或Map时,Spring Doc会将其识别为单个JSON参数(因为@RequestParam默认用于处理单个键值对或简单集合),而非把DTO的每个字段解析为独立的URL请求参数。GET接口不能使用请求体,因此正确的做法是用@ModelAttribute绑定请求参数到DTO对象。
正确代码实现
1. 修改Controller方法
将@RequestParam替换为@ModelAttribute,Spring会自动把URL中的请求参数(如?name=张三&dateOfBirth=1990-01-01)映射到DTO的对应字段,同时Spring Doc会正确识别每个字段为独立的请求参数:
@GetMapping public ResponseEntity<List<UserResponseDto>> findUsers(@ModelAttribute FindUserRequestDto requestDto) { // 业务逻辑:直接通过requestDto的getter方法获取参数 return ResponseEntity.ok(userService.findUsers(requestDto)); }
2. 保持DTO不变
你的FindUserRequestDto无需修改,Lombok的@Getter/@Setter已足够Spring完成参数绑定:
import lombok.Getter; import lombok.Setter; import java.time.LocalDate; @Getter @Setter public class FindUserRequestDto { private LocalDate dateOfBirth; private String phone; private String name; private String email; private int pageNumber; private int pageSize; }
关于Map<String, String>的替代方案
如果一定要用Map接收参数且希望Swagger正确显示参数列表,可以手动添加OpenAPI注解声明每个参数,但这种方式不如DTO直观:
@GetMapping @Operation(parameters = { @Parameter(name = "dateOfBirth", description = "出生日期", example = "1990-01-01"), @Parameter(name = "phone", description = "手机号"), @Parameter(name = "name", description = "姓名"), // 其他参数依次添加 }) public ResponseEntity<List<UserResponseDto>> findUsers(@RequestParam Map<String, String> parameterMap) { // 业务逻辑 return ResponseEntity.ok(userService.findUsers(parameterMap)); }
不过这种方式需要手动维护参数注解,不如DTO方式自动生成Swagger文档方便,推荐优先使用DTO+@ModelAttribute的方案。
关键注意事项
- 参数名匹配:DTO的字段名要与URL请求参数名完全一致(如DTO的
dateOfBirth对应URL的dateOfBirth参数),若需要不同的参数名,可在DTO字段上添加@RequestParam("paramName")注解指定别名。 - 日期类型解析:Spring默认支持
LocalDate类型的参数解析,只要请求参数是yyyy-MM-dd格式即可;若需要其他格式,可在DTO字段上添加@DateTimeFormat(pattern = "yyyy/MM/dd")指定格式。 - 非必填参数:如果某些参数是可选的,将DTO的字段类型改为包装类(如
Integer pageNumber而非int),或添加@Nullable注解,避免参数缺失时抛出绑定异常。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

