如何将Spring控制器中Java对象类型的请求参数设为必填?
嘿,这个场景太常见了!Spring默认确实会把封装对象的参数都当成可选的,但要设置必填项其实很简单,用JSR-380的校验注解就能轻松搞定,我给你一步步拆解:
1. 先引入校验依赖
如果是Spring Boot项目,直接加这个starter就行:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
要是普通Spring项目,需要引入hibernate-validator和相关API依赖。
2. 给Filter类的字段加校验注解
根据字段类型选对应的注解:
- 对于
Integer这种包装类,用@NotNull(确保参数不为null,不会接受空字符串转成null的情况) - 对于
String类型,要是需要非空且不能是空白字符串,用@NotBlank;如果允许空字符串但不能为null,用@NotEmpty
修改后的Filter类示例:
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotBlank; public class Filter { @NotNull(message = "page参数不能为空,请传入有效页码") private Integer page; @NotNull(message = "size参数不能为空,请传入每页条数") private Integer size; @NotBlank(message = "sort参数不能为空,请指定排序字段") private String sort; // 其他众多参数... // 别忘了加getter和setter,Spring需要通过它们注入参数 }
3. 在控制器参数上触发校验
只需要在Filter参数前面加上@Validated(或者@Valid)注解,Spring就会自动帮你校验参数:
@GetMapping("/users") public ResponseEntity<UserDto> getUsers(@Validated Filter filter) { return ResponseEntity.ok(userService.findUsers(filter)); }
这里说下@Valid和@Validated的小区别:@Valid是JSR标准注解,@Validated是Spring的扩展,支持分组校验、校验组序列这些高级功能,一般用@Validated更灵活。
4. 处理校验失败的情况
如果参数不符合要求,Spring会抛出MethodArgumentNotValidException,你可以写个全局异常处理器来捕获它,返回友好的错误信息给前端:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalValidationExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) { Map<String, String> errorMap = new HashMap<>(); // 遍历所有校验错误,把字段名和错误信息对应起来 ex.getBindingResult().getAllErrors().forEach(error -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errorMap.put(fieldName, errorMessage); }); return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST); } }
进阶:分组校验(部分场景必填,部分可选)
要是你有不同的接口场景,比如有的接口需要page和size必填,有的不需要,就可以用分组校验:
- 先定义两个分组接口:
public interface RequiredPagingGroup {} public interface OptionalPagingGroup {}
- 在Filter的注解上指定分组:
@NotNull(message = "page参数不能为空", groups = RequiredPagingGroup.class) private Integer page;
- 控制器里指定要触发的分组:
@GetMapping("/users") public ResponseEntity<UserDto> getUsers(@Validated(RequiredPagingGroup.class) Filter filter) { return ResponseEntity.ok(userService.findUsers(filter)); }
这样就能灵活控制不同场景下的必填参数啦!
内容的提问来源于stack exchange,提问作者Archie
相关产品推荐
相关产品推荐

