一、为什么要进行参数校验?
当我们在服务端控制器接受前台数据时,肯定首先要对数据进行参数验证,判断参数是否为空?是否为电话号码?是否为邮箱格式?等等。
这里有个问题要注意:
前端代码一般上会对这些数据进行验证,为什么后台还要验证一次呢?
前台验证针对的是系统用户,保证用户的输入没有问题。
后台验证针对的是客户端传输到服务器的这一过程中可能出现的问题导致的数据异常。
二、为什么要使用jsr303参数校验器?
不是用jsr303验证器我们是如何进行参数验证的呢?
首先创建一个参数校验工具类(这里我只是简单验证传入的是否是以1开头的11位数字)
public class ValidatorUtil { private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}"); public static boolean isMobile(String src) {
if(StringUtils.isEmpty(src)) {
return false;
}
Matcher m = mobile_pattern.matcher(src);
return m.matches();
} }
然后在控制器中判断是否为空,然后验证格式
这种方式在每个需要参数验证地方都需要写这么一大堆,不符合复用性原则而且不美观。
那使用jsr303验证器最终结果是怎样呢?
最终的控制器代码:
三、jsr303使用步骤
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2、定义注解
模仿官方的@NotNull来写
官方@NotNull:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = { })
public @interface NotNull { String message() default "{javax.validation.constraints.NotNull.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; /**
* Defines several {@link NotNull} annotations on the same element.
*
* @see javax.validation.constraints.NotNull
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@interface List { NotNull[] value();
}
}
自己定义的:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class })
public @interface IsMobile {
//是否允许为空,true表示不允许
boolean required() default true;
//如果校验不通过给出的提示信息
String message() default "手机号码格式错误"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { };
}
定义完注解还不够,因为系统不知道怎样去校验该注解,所有还需要编写一个校验器类,并且在@Constraint注解中指明校验器类。(注意将注解文件和校验器类文件放在同一包下)
3、编写注解验证器类
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> { //是否可以为空
private boolean required = false; public void initialize(IsMobile constraintAnnotation) {
required = constraintAnnotation.required();
} 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);
}
}
} }
4、使用注解
四、还存在的问题
使用jsr303校验器校验参数,如果不通过则直接抛出异常,我们必须定义全局异常处理器来捕获这个异常,否则前台用户必须打开浏览器控制台才能看到错误信息。
关于全局异常处理器的使用请看我的下篇文章。