记录一个自定义校验注解,作用是验证该字段是不是一个正确的手机号码的格式
/**
* @program: jpademo
* @description: TelphoneValidator
* @author: ZengGuangfu
* @create 2018-10-25 14:42
*/
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyTelphoneValidator.class)
public @interface Telphone {
/** 一个是否验证的开关,默认要验证 */
boolean isValidetor() default true;
/** 默认的报错信息 */
String message() default "这不是一个正确的手机号码";
/** 分组信息,可通过空内容的接口去实现分组验证 */
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
-
@Target:说明了注解所修饰的对象范围,注解可被用于 packages、types(类、接口、枚举、注解类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在注解类型的声明中使用了target可更加明晰其修饰的目标。
在ElementType枚举中:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域(字段、枚举的常量)
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明 -
@Retention:定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留) - @Documented:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
/**
* @program: jpademo
* @description: MyTelphoneValidator
* @author: ZengGuangfu
* @create 2018-10-25 14:45
*/
public class MyTelphoneValidator implements ConstraintValidator<Telphone,String> {
private String telphoneNumberValid = "/^1(?:3\\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\\d|9\\d)\\d{8}$/";
//可以调用上层的这个方法设置一个默认值,也可以自己传值
//如果传值了,不是用的默认值的话,false就代表不进行验证,true就代表要验证,这个可以在isValid()方法中进行验证
boolean isValidetor;
/**
* 加载方法,准备校验
*/
@Override
public void initialize(Telphone telphone) {
System.out.println("自定义validator加载完成");
isValidetor = telphone.isValidetor();
}
/**
* 返回true表示验证通过,false则不通过,提示错误信息message()
*/
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
if(isValidetor){
if (value == null) {
return false;
}
return Pattern.matches(telphoneNumberValid,value);
}else{
return true;
}
}
}
分组验证举例
字段有分类Gourp1.class (Gourp1是一个空内容的接口)
/**
* @program: jpademo
* @description: Grade Entity
* @author: ZengGuangfu
* @create 2018-10-24 09:09
*/
@Entity
@Table(name = "t_grade")
@Data
public class Grade {
/**
* 主键
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "grade_id")
private Integer gradeId;
/**
* 班级
*/
@Column(nullable = false,name = "remo")
@Range(min = 1,max = 30,groups = {Group2.class},message = "班级号remo超过1-30的限制")
private Integer remo;
/**
* 班主任
*/
@Column(unique = true)
@NotNull(message = "班主任不能为空")
private String teacher;
/**
* 楼层
*/
@Column(name = "floor")
@Min(value = 5,message = "楼层最小为5",groups = {Group1.class})
private Integer floor;
}
@RestController 仅验证分组Group1.class
@PostMapping
public String insert(@Validated(Group1.class) Grade grade, BindingResult results){
if(results!=null && results.hasErrors()){
List<ObjectError> globalErrors = results.getAllErrors();
for (ObjectError error :globalErrors
) {
System.out.println("-----------"+error.getDefaultMessage());
return SysNode.Judge.FAILD.getResult();
}
}
Integer inse = gradeService.insert(grade);
return inse == 0 ? SysNode.Judge.FAILD.getResult() : SysNode.Judge.SUCCESS.getResult();
}