Spring Boot实体校验失效:Postman可提交不符合规则的JSON
Spring Boot参数校验注解不生效问题排查与解决
我用Java搭建了Spring Boot项目,在User实体类中通过@NotBlank、@Size、@Email等校验注解设置了JSON入参规则,但使用Postman提交不符合规则的JSON时,接口仍接收所有输入值;已添加相关Gradle依赖但问题未解决。
User.java实体类
package com.example.demo.model; import javax.persistence.*; import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size; import java.util.Objects; @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotBlank(message = "Name field cannot be blank.") @Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters.") private String name; @NotBlank(message = "DDD field cannot be blank.") @Size(min = 2, max = 2, message = "DDD must have 2 characters.") private String ddd; @NotBlank(message = "Phone Number field cannot be blank.") @Size(min = 8, max = 9, message = "Phone number must have between 8 and 9 digits.") private String phoneNumber; @NotBlank(message = "Email field cannot be blank.") @Email(message = "Invalid email format.") @Column(unique = true) private String email; @NotBlank(message = "Password field cannot be blank.") @Size(min = 8, max = 12, message = "Password must be between 8 and 12 characters") private String password; public User() { } public User(String name, String ddd, String phoneNumber, String email, String password) { this.name = name; this.ddd = ddd; this.phoneNumber = phoneNumber; this.email = email; this.password = password; } // Standard getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public String getPassword() { return password; } public String getPhoneNumber() { return phoneNumber; } public String getDdd() { return ddd; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(id, user.id) && Objects.equals(email, user.email); } @Override public int hashCode() { return Objects.hash(id, email); } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", ddd='" + ddd + '\'' + ", phoneNumber='" + phoneNumber + '\'' + ", email='" + email + '\'' + '}'; } }
UserController.java控制器类
package com.example.demo.controller; import com.example.demo.model.User; import com.example.demo.service.UserService; import com.example.demo.service.MailService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/api/users") public class UserController { private final UserService userService; private final MailService mailService; @Autowired public UserController(UserService userService, MailService mailService) { this.userService = userService; this.mailService = mailService; } @GetMapping public ResponseEntity<List<User>> getAllUsers() { List<User> users = userService.getAllUsers(); return new ResponseEntity<>(users, HttpStatus.OK); } @GetMapping("/{id}") public ResponseEntity<User> getUserById(@PathVariable Long id) { Optional<User> userOptional = userService.getUserById(id); return userOptional .map(user -> new ResponseEntity<>(user, HttpStatus.OK)) .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND)); } @PostMapping public ResponseEntity<User> createUser(@Valid @RequestBody User user) { if (userService.existsByEmail(user.getEmail())) { return new ResponseEntity<>(HttpStatus.CONFLICT); // Email already exists } User newUser = userService.saveOrUpdateUser(user); return new ResponseEntity<>(newUser, HttpStatus.CREATED); } @PutMapping("/{id}") public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) { Optional<User> userOptional = userService.getUserById(id); if (userOptional.isPresent()) { // Ensure the ID from the path matches the ID of the user being updated user.setId(id); User updatedUser = userService.saveOrUpdateUser(user); return new ResponseEntity<>(updatedUser, HttpStatus.OK); } return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @PostMapping("/sendVerificationEmail") public ResponseEntity<String> sendVerificationEmail(@RequestParam String email) { // Generate a verification code or content if needed String verificationContent = "Your verification content here"; // Use your MailService to send the email mailService.sendVerificationEmail(email, "Verification Email", verificationContent); return ResponseEntity.ok("Email sent successfully."); } @DeleteMapping("/{id}") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { if (userService.getUserById(id).isPresent()) { userService.deleteUser(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } return new ResponseEntity<>(HttpStatus.NOT_FOUND); } }
已添加的Gradle依赖
dependencies { implementation 'org.hibernate.validator:hibernate-validator:7.0.2.Final' implementation 'org.hibernate:hibernate-core:5.5.6.Final' implementation 'org.springframework.boot:spring-boot-starter-validation' }
问题排查与解决步骤
1. 清理冗余依赖,避免版本冲突
当前依赖同时引入了hibernate-validator、hibernate-core和spring-boot-starter-validation,会导致版本兼容问题。spring-boot-starter-validation已包含了Hibernate Validator的正确依赖,无需单独引入其他两个。修改依赖为:
dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' // 保留项目其他必要依赖,如spring-boot-starter-data-jpa等 }
2. 补全Update接口的校验注解
updateUser方法未添加@Valid注解,导致更新操作时参数校验不生效。修改该方法:
@PutMapping("/{id}") public ResponseEntity<User> updateUser(@PathVariable Long id, @Valid @RequestBody User user) { Optional<User> userOptional = userService.getUserById(id); if (userOptional.isPresent()) { user.setId(id); User updatedUser = userService.saveOrUpdateUser(user); return new ResponseEntity<>(updatedUser, HttpStatus.OK); } return new ResponseEntity<>(HttpStatus.NOT_FOUND); }
3. 添加全局异常处理器,统一返回校验错误
默认的校验错误响应不够直观,可添加全局异常处理器,返回结构化的错误信息:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach(error -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } }
4. 验证Spring Boot版本与注解包的匹配
如果是Spring Boot 3.x版本,校验注解应从jakarta.validation.constraints包导入;Spring Boot 2.x版本则使用javax.validation.constraints包。根据你的代码,当前包导入正确,无需修改。
5. 检查依赖树确认无冲突
执行./gradlew dependencies命令查看项目依赖树,确保spring-boot-starter-validation引入的Hibernate Validator版本与项目其他依赖兼容。
内容的提问来源于stack exchange,提问作者NickVnkn
相关产品推荐
相关产品推荐

