Spring Boot中如何优雅校验GET请求的@RequestParam参数?
GET请求参数批量校验规范方案
完全可以采用和POST请求DTO校验一致的实现方式,Spring MVC原生支持GET请求的查询参数直接绑定到自定义JavaBean对象,配合校验注解即可实现批量参数校验,无需逐个在@RequestParam上添加注解。
1. 定义参数接收DTO类
将所有请求参数封装为一个普通JavaBean,在对应字段上添加校验注解:
import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; public class StockQueryParam { @NotBlank(message = "color参数不能为空") @Pattern(regexp = "^[A-Za-z0-9]+$", message = "color参数仅支持字母数字组合") private String color; @NotBlank(message = "op参数不能为空") @Pattern(regexp = "^(up|down|equal)$", message = "op参数仅支持up/down/equal") private String op; @NotNull(message = "size参数不能为空") @Min(value = 1, message = "size参数最小值为1") @Max(value = 999, message = "size参数最大值为999") private Integer size; // 必须提供无参构造 public StockQueryParam() {} // 所有字段需提供对应的getter、setter方法 public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getOp() { return op; } public void setOp(String op) { this.op = op; } public Integer getSize() { return size; } public void setSize(Integer size) { this.size = size; } }
2. 改造Controller接口
将原方法中多个@RequestParam参数替换为上述DTO,添加@Valid注解开启校验:
import jakarta.validation.Valid; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class StockController { @GetMapping("/stocks") public String getStocks(@Valid StockQueryParam queryParam) { return service.getStocks(queryParam.getColor(), queryParam.getOp(), queryParam.getSize()); } }
Spring会自动将URL中的查询参数按照字段名映射到DTO的对应属性,校验逻辑和POST请求的DTO校验完全一致。
3. 可选:统一处理校验异常
GET请求参数校验失败会抛出BindException,可通过全局异常处理器统一返回友好的错误提示:
import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.StringJoiner; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) public String handleBindException(BindException e) { StringJoiner errorMsg = new StringJoiner(";"); e.getFieldErrors().forEach(fieldError -> errorMsg.add(fieldError.getField() + fieldError.getDefaultMessage()) ); return errorMsg.toString(); } }
注意事项
- Spring Boot 2.3及以上版本需手动引入
spring-boot-starter-validation依赖,校验注解使用jakarta.validation包下的类;2.3以下版本使用javax.validation包下的类 - 如果URL参数名和DTO字段名不一致,可在对应DTO字段上添加
@RequestParam("url参数名")注解指定映射关系 - DTO必须提供无参构造方法和所有字段的get/set方法,否则会出现参数绑定失败的问题
内容的提问来源于stack exchange,提问作者fxvlad
相关产品推荐
相关产品推荐

