SpringBoot2中的参数校验,以及异常统一处理
一、添加依赖在pom.xml文件中
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
二、实体类参数校验
1)实体对象示例
package com.xc.common.model; import lombok.Data; import javax.validation.constraints.*; /** * Vaild测试对象 * @author Administrator */ @Data public class VaildTestModel { @NotNull(message = "Id不能为空") private Long id; @NotNull(message = "用户账号不能为空") @Size(min = 6, max = 11, message = "账号长度必须是6-11个字符") private String account; @NotNull(message = "用户密码不能为空") @Size(min = 6, max = 11, message = "密码长度必须是6-16个字符") private String password; @NotNull(message = "用户邮箱不能为空") @Email(message = "邮箱格式不正确") private String email; @NotEmpty(message = "姓名不能为空") private String name; @Max(value = 18,message = "年龄不能超过18岁") private String age; @Max(value = 1, message = "性别只能为0和1: 0=女1=男") @Min(value = 0, message = "性别只能为0和1: 0=女1=男") private Short sex; }
2)controller示例
package com.xc.web.controller; import com.xc.common.model.ResponseVO; import com.xc.common.model.VaildTestModel; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.HashMap; import java.util.Map; /** * 测试类 * http://localhost:9004/webacttest/doc.html#/home * @author Administrator */ @Slf4j @RestController @Api(description = "测试接口") @RequestMapping("test") @Validated public class TestController { @ApiOperation("测试@validated注解 类上") @PostMapping("testValidated2") public ResponseVO testValidated2(@Valid @RequestBody @ApiParam("VaildTestModel对象") VaildTestModel vaildTestModel) { return ResponseVO.successInstance(vaildTestModel.getId()); } }
3)全局异常处理类
/** * 全局异常处理器 * @author Administrator */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { /** * 处理所有校验失败的异常(MethodArgumentNotValidException异常) * 设置响应状态码为400 * @param ex * @return */ @ExceptionHandler(value = MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseVO handleBindGetException(MethodArgumentNotValidException ex) { // 获取所有异常 List<String> errors = ex.getBindingResult() .getFieldErrors() .stream() .map(x -> x.getDefaultMessage()) .collect(Collectors.toList()); return ResponseVO.errorInstance(String.join(",", errors)); } }
4)测试结果
5)快速失败模式
package com.xc.common.exception; import org.hibernate.validator.HibernateValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; /** * 效验模式:如果出现多个字段效验失败,会返回所有的验证失败错误信息。通常情况下,当第一个字段/参数效验失败时,直接返回。 * 普通模式:默认使用的就是普通模式,校验完所有的属性之后,返回所有的验证失败信息。 * 快速失败模式:只要有一个字段效验失败,直接返回 * @author Administrator */ @Configuration public class ValidationConfig { /** * 效验@RequestBody时,采用快速失败模式 */ @Bean public Validator validator() { ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class) .configure() //快速失败 .failFast(true) .buildValidatorFactory(); return validatorFactory.getValidator(); } /** * 效验@RequestParam时,采用快速失败模式 */ @Bean public MethodValidationPostProcessor methodValidationPostProcessor(Validator validator) { MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor(); // 设置validator postProcessor.setValidator(validator); return postProcessor; } }
二、单个参数校验
1)直接在参数前加上校验注解 注:类上必须加 @Validated 注解
package com.xc.web.controller; import com.xc.common.model.ResponseVO; import com.xc.common.model.VaildTestModel; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.HashMap; import java.util.Map; /** * 测试类 * http://localhost:9004/webacttest/doc.html#/home * @author Administrator */ @Slf4j @RestController @Api(description = "测试接口") @RequestMapping("test") @Validated public class TestController { @ApiOperation(value = "测试@validated注解",notes = "返回输入的参数") @GetMapping("testValidated") public ResponseVO testValidated( @RequestParam("param") @NotNull(message = "参数不能为空") @ApiParam(value = "参数", required = true, example = "0") String param ){ return getConstant(param); } }
2)全局处理函数
package com.xc.common.exception; import com.xc.common.model.ResponseVO; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.*; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; import java.util.*; import java.util.stream.Collectors; /** * 全局异常处理器 * @author Administrator */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { /** * 处理所有校验失败的异常(MethodArgumentNotValidException异常) * 设置响应状态码为400 * @param ex * @return */ @ExceptionHandler(value = MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseVO handleBindGetException(MethodArgumentNotValidException ex) { // 获取所有异常 List<String> errors = ex.getBindingResult() .getFieldErrors() .stream() .map(x -> x.getDefaultMessage()) .collect(Collectors.toList()); return ResponseVO.errorInstance(String.join(",", errors)); } /** * 处理所有参数校验时抛出的异常 * * @param ex * @return */ @ExceptionHandler(value = ValidationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseVO handleBindException(ValidationException ex) { // 获取所有异常 List<String> errors = new LinkedList<String>(); if(ex instanceof ConstraintViolationException){ ConstraintViolationException exs = (ConstraintViolationException) ex; Set<ConstraintViolation<?>> violations = exs.getConstraintViolations(); for (ConstraintViolation<?> item : violations) { errors.add(item.getMessage()); } } return ResponseVO.errorInstance(String.join(",", errors)); } /** * Controller参数绑定错误 * * @param ex * @return */ @ExceptionHandler(MissingServletRequestParameterException.class) public ResponseVO handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) { return ResponseVO.errorInstance(ex.getMessage()); } }
3)结果验证
完