JSR303参数校验
开发web项目有时候我们需要对controller层传过来的参数进行一些基本的校验,比如非空,非null,整数值的范围,字符串的个数,日期,邮箱等等。最常见的就是我们直接写代码校验,这样以后比较繁琐,而且不够灵活。故引出使用JSR303来做参数校验。参数校验的实现:
手机号和密码字段自定义注解
为了让客户端显示更加友好
需要自定义异常拦截器
1. 添加依赖
<!--JSR303参数检验+全局异常处理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
2.在需要验证的类前加@Valid并在该类内需要参数检查的成员上加自定义注解
@Controller
@RequestMapping("/login")
public class LoginController {
@RequestMapping("/do_login")
@ResponseBody
public Result<String> doLogin(HttpServletResponse response,
@Valid LoginVo loginVo){
logger.info(loginVo.toString());
}
}
@Data
public class LoginVo {
@NotNull
@IsMobile
private String mobile;
@NotNull
@Length(min = 32)
private String password;
}
3. IsMobile注解的编写[可参考@NotNull]
@Target({
ElementType.METHOD,
ElementType.FIELD,
ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR,
ElementType.PARAMETER,
ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {IsMobileValidator.class}
)
public @interface IsMobile {
boolean required() default true;
String message() default "电话号码格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
4.指定校验器的实现[IsMobileValidator.class]
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {
private boolean required = false;
@Override
//初始化方法拿到注解,可以定义一个字符为空
public void initialize(IsMobile constraintAnnotation) {
constraintAnnotation.required();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//值是必须的
if(required){
return ValidatorUtil.isMobile(value);
}else{
if(StringUtils.isEmpty(value)){
return true;
}else{
return ValidatorUtil.isMobile(value);
}
}
}
}
5.自定义异常拦截器
当校验不通过时,会抛出异常。这时如果没有定义全局异常处理器进行处理(对异常进行封装和返回)。则会发生400错误(即只有请求的发起,却没有收到正常的响应(response),因为还没有来得及return就抛出了异常(这种异常没有被处理))。
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public Result<String> exceptionHandler(HttpServletRequest request,Exception e){
e.printStackTrace();
if(e instanceof GlobalException) {
GlobalException ex = (GlobalException) e;
return Result.Error(ex.getCm());
}else if(e instanceof BindException){
BindException ex = (BindException) e;
List<ObjectError> errors = ex.getAllErrors();
//为了方便起见,只取第一个错误
ObjectError error = errors.get(0);
String msg = error.getDefaultMessage();
return Result.Error(CodeMsg.BIND_ERROR.fillArgs(msg));
}else{
return Result.Error(CodeMsg.SERVER_ERROR);
}
}
}