自定义注解实现数据库手机号码不重复校验
视频讲解详见 https://www.bilibili.com/video/BV1tq4y1a7B6/
第一步 创建校验手机号格式的正则工具类
public class PhoneUtils {
private static final String REGEX_MOBILE ="((\\+86|0086)?\\s*)((134[0-8]\\d{7})|(((13([0-3]|[5-9]))|(14[5-9])|15([0-3]|[5-9])|(16(2|[5-7]))|17([0-3]|[5-8])|18[0-9]|19([0-9]))\\d{8})|(14(0|1|4)0\\d{7})|(1740([0-5]|[6-9]|[10-12])\\d{7}))";
/**
* 正则:固定电话号码,可带区号,然后至少6,8位数字
*/
private static final String REGEX_TEL = "^(\\d{3,4}-)?\\d{6,8}$";
private static final Pattern PATTERN_REGEX_TEL = Pattern.compile(REGEX_TEL);
/**
* 判断是否是手机号
* @param tel 手机号
* @return boolean true:是 false:否
*/
public static boolean isMobile(String tel) {
if (StringUtils.isEmpty(tel)){
return false;
}
return Pattern.matches(REGEX_MOBILE, tel);
}
/**
* 验证固定电话号码
*/
public static boolean isTel( String str) {
return isMatch(PATTERN_REGEX_TEL, str);
}
public static boolean isMatch(Pattern pattern, String str) {
return StringUtils.isNotEmpty(str) && pattern.matcher(str).matches();
}
public static void main(String[] args) {
System.out.println(isTel("2887438"));
}
}
第二步 编写两个需要的注解
@Target(ElementType.METHOD)//作用于方法
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface CheckPhone {
}
@Target(ElementType.FIELD) //作用于字段
@Retention(RetentionPolicy.RUNTIME) //运行时有效
public @interface PhoneFlag {
}
第三步 编写需要的切面类
@Aspect
@Component
public class CheckPhoneAspect {
@Resource
UserInfoService userInfoService;
/**
* @annotation 声明以注解的方式来定义切点,里面写自己定义的注解的路径即可
*
*/
@Before("@annotation(com.asiainfo.idsp.iptv.common.myAnnotation.CheckPhone)")
public void before(JoinPoint point) throws Throwable {
// 获取所有参数
Object[] args = point.getArgs();
for (Object arg : args) {
if (null == arg){
return;
}
Class c = arg.getClass();
// 获取class对象内的字段
Field[] fields = c.getDeclaredFields();
if (null != fields){
for (Field field : fields) {
String methodName = "get";
// 字段名称
String name = field.getName();
// 组装获取字段方法名
String first = name.substring(0,1).toUpperCase();
if (name.length() > 1){
String second = name.substring(1);
methodName = methodName.concat(first).concat(second);
}else {
methodName = methodName.concat(first);
}
// 获取注解,存在PhoneFlag注解就进行校验
PhoneFlag annotation = field.getAnnotation(PhoneFlag.class);
if (null != annotation){
// 校验电话号码格式是否正确
// invoke()反射获取字段值
String phone = (String) c.getMethod(methodName).invoke(arg);
if (StringUtils.isNotBlank(phone)){
if (!PhoneUtils.isMobile(phone)){
throw new BusinessException("电话格式不正确");
}
// 查询数据库,校验手机号码是否存在
// 先判断id是否为空 如果不为空就是修改操作,修改允许修改的手机号码与原来的手机号码相同
Object id = c.getMethod("getId").invoke(arg);
final QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
wrapper.eq("phone", phone);
if (null == id){
// 如果没有id就是新增操作
final List<UserInfo> list = userInfoService.list(wrapper);
if (list.size() > 0) {
throw new BusinessException("手机号码已存在");
}
}else {
// 如果id不为空,就是修改操作,校验修改的手机号码与原来的手机号码是否相同
// 排除自己
wrapper.ne("id", id);
final List<UserInfo> list = userInfoService.list(wrapper);
if (list.size() > 0){
throw new BusinessException("手机号码已存在");
}
}
}
}
}
}
}
}
}
第四步 在实体类的字段上和需要的校验的方法上加上两个注解