当涉及校验用户输入时,如果由开发人员编码校验数据,那么验证数据的代码和业务逻辑代码会耦合在一起。Spring Framework 4.0支持Bean Validation 1.0(JSR-303)和Bean Validation 1.1(JSR-349),也将其改写成了Spring的Validator接口。使用Spring Validation可以方便的进行数据校验。
1.引入依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
|
2.实体类中添加校验注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package io.github.lmy.springbootinaction.request;
import io.github.lmy.springbootinaction.entity.User; import lombok.Data; import org.hibernate.validator.constraints.Range; import org.springframework.beans.BeanUtils;
import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern;
@Data public class UserRequest {
@NotBlank(message = "用户名不能为空") private String name;
@Range(min = 0, max = 150, message = "年龄格式不正确") @NotNull private Integer age;
@Email(message = "邮箱格式不正确") @NotBlank(message = "邮箱不能为空") private String email;
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$", message = "手机号码格式不正确") @NotBlank(message = "手机号不能为空") private String phone;
@NotBlank(message = "密码不能为空") private String password; }
|
3.在Controller层校验数据
对需要校验的参数添加注解@Valid或@Validated,如果需要获取校验的信息,可以在被校验参数后面添加一个BindingResult参数,Spring会将校验的信息填充到该校验参数后面的BindingResult中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package io.github.lmy.springbootinaction.controller;
import io.github.lmy.springbootinaction.request.LoginRequest; import io.github.lmy.springbootinaction.request.UserRequest; import io.github.lmy.springbootinaction.service.UserService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.Valid;
@Controller @RequestMapping("/user") @Slf4j public class UserController {
@Autowired private UserService userService;
@PostMapping("/register") @ResponseBody public boolean register(@Valid @RequestBody UserRequest userRequest, BindingResult result) { if (result.hasErrors()) { for (FieldError fieldError : result.getFieldErrors()) { log.info("field: {}, message: {}", fieldError.getField(), fieldError.getDefaultMessage()); } return false; } boolean success = userService.register(userRequest); return success; }
@PostMapping("/login") public String login(@Validated @RequestBody LoginRequest loginRequest) { userService.login(loginRequest); return "index"; }
}
|
4.校验失败统一处理
如果校验参数后没有BindingResult参数,且校验参数校验失败,则会抛出MethodArgumentNotValidException 异常。可以使用 @ExceptionHandler 注解统一处理参数校验失败。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package io.github.lmy.springbootinaction.global;
import org.springframework.http.HttpStatus; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Map; import java.util.stream.Collectors;
@RestControllerAdvice public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> result = ex.getBindingResult() .getFieldErrors() .stream() .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage)); return result; }
}
|
参考链接: