前言
在项目开发交互过程中,难免会遇到一些数据校验。以校验客户端发送数据的合法性,对于一些非空校验,我们也许可以使用@NonNull,@NotNull 等注解,可是对于一些常规的,如手机号,身份证等等的校验,我们就还要判断处理每个请求的参数的合法性。
但是合法性的判断是难以避免的,我们是否可以精简工作量、提高工作效率呢。
思考
我们或许应该从@NonNull @NotNull等其他注解那里受到些启发。
我们或许可以结合正则表达式及注解对某些通用数据进行验证。
注解可以设置参数,我们可以设置参数为校验规则,通过枚举列举出来,同时也应该允许用户自定义正则等校验。
我们知道,注解有三种类型
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME。
SOURCE主要用于编译之前,编译过程中会被丢弃如@Override注解。
CLASS主要用于编译,运行时会被丢弃。
RUNTIME在源码,编译,运行时始终会存在。
可以利用反射,拿到具有特定注解的bean,并处理。所以我们定义的注解应该是RUNTIME类型。同时声明注作用范围为FIELD及PARAMETER。
实践
定义注解
/**
* 数据验证注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.FIELD,ElementType.PARAMETER})
public @interface DataValid {
//是否可以为空
boolean nullable() default false;
//提供几种常用的正则验证
RegexType regexType() default RegexType.NONE;
//自定义正则验证
String regexExpression() default "";
//参数或者字段描述
String description() default "";
}
定义如上注解,nullable用来校验参数是否可空,默认不可以为空,false。
同时提供几种通用的正则校验,用枚举列出,如手机号码校验,身份证信息校验等等。
同时如果没有规定的正则表达式,可以让用户自定义自己的正则表达式。
另增加描述字段,用来说明这个paramer的用途。
定义常用正则枚举
/**
* 正则类型枚举
*/
public enum RegexType {
NONE,
SPECIALCHAR,
CHINESE,
EMAIL,
IP,
NUMBER,
NUMBERORNIL,
PHONENUMBER,
ID;
}
列出几种常用枚举。非空,特殊字符,中文,邮箱,IP,数字等等
枚举规则
定义了枚举,要定义它们的具体对应的方法,以便后续调用。
/**
* 常用正则表达式
*/
public class RegexUtils {
/**
* 判断是否是正确的IP地址
*
* @param ip
* @return boolean true,通过,false,没通过
*/
public static boolean isIp(String ip) {
if (null == ip || "".equals(ip))
return false;
String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
return ip.matches(regex);
}
/**
* 判断是否是正确的邮箱地址
*
* @param email
* @return boolean true,通过,false,没通过
*/
public static boolean isEmail(String email) {
if (null == email || "".equals(email))
return false;
String regex = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
return email.matches(regex);
}
/**
* 判断是否含有中文,仅适合中国汉字,不包括标点
* @param text
* @return boolean true,通过,false,没通过
*/
public static boolean isChinese(String text) {
if (null == text || "".equals(text))
return false;
Pattern p = Pattern.<