SpringBoot异常处理(二)
参数校验机制
JSR-303 Hibernate
参数接收方式:
- URL路径中的参数 {id} (@PathVariable(name="id") int-whatever)
- URL中的查询参数 ?name=Chanuncy (@RequestPara(name String-whatever)
- requestbody中的json字符串 {"name":"7yue","age":18} (@RequestBody Map<String,Object> person)
- 一般会新建一个dto(data transfer object) 来接受和发送参数,一个对象一个dto
@Getter
@Builder
public class PersonDTO {
private String name;
private Integer age;
private String password1;
private String password2;
}
简单参数检验:
@Validated 开启验证
@Range @Max @Min
@RestController
@RequestMapping("/banner")
//开启验证 下文@Max验证
@Validated
public class BannerController {
@RequestMapping("/test1/{id}")
public String test1(@PathVariable @Max(5) int id,
@RequestBody @Validated PersonDTO person){
//开启PersonDTO @Length验证
return "ok";
}
复杂参数验证:(对象)
@Validated 开启验证
@Valid 级联验证
PersonDTO:
@Getter
@Builder
//自定义注解后面会讲到
@PasswordEqual
public class PersonDTO {
@Length(min = 2, max=10, message = "大小不匹配")
private String name;
private Integer age;
private String password1;
private String password2;
//@Valid 开启SchoolDTO schoolName 验证
private SchoolDTO school;
}
@Getter
@Setter
public class SchoolDTO{
@Length(min=2)
priavte String schoolName;
}
自定义参数校验注解:
当逻辑十分复杂时就要自己定义参数校验注解
先导:注解和反射
四个元注解:
- @Target
- @Rentention
- @Documented
- @Inherited
使用注解的机制:反射
通过反射获取Class实例的方法:
- 对象.getClass()
- 类.class
- Class.forName(全类名)
新建一个验证两次输入相同字符串的注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
//将注解和逻辑处理类关联
@Constraint(validatedBy = PasswordValidator.class)
public @interface PasswordEqual {
String message() default "passwords are not equal";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
逻辑处理:
//ConstraintValidator<注解的名字,注解修饰的对象>
public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> {
@Override
public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) {
String password1 = personDTO.getPassword1();
String password2 = personDTO.getPassword2();
boolean match = password1.equals(password2);
return match;
}
}
上述参数校验会抛出一个未处理的异常,所以我们要写对应的异常处理
在Spring-Boot异常处理(一)中的GlobalExceptionAdvice中添加:
//dto参数校验异常
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public UnifyResponse handleBeanValidation(HttpServletRequest req,MethodArgumentNotValidException e){
List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
String errorMessage = this.formatAllErrorMessages(allErrors);
return new UnifyResponse(10001,errorMessage,req.getMethod() + ' ' + req.getRequestURI());
}
//url参数异常
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public UnifyResponse handleConstraintViolationException(HttpServletRequest req, ConstraintViolationException e){
return new UnifyResponse(10001,e.getMessage(),req.getMethod() + ' ' + req.getRequestURI());
}
//格式化dto参数校验异常错误信息
private String formatAllErrorMessages(List<ObjectError> errors){
StringBuffer errorMsg = new StringBuffer();
errors.forEach(error -> errorMsg.append(error.getDefaultMessage()).append(';'));
return errorMsg.toString();
}

浙公网安备 33010602011771号