当前位置: 移动技术网 > IT编程>开发语言>Java > springboot validator枚举值校验功能实现

springboot validator枚举值校验功能实现

2020年03月09日  | 移动技术网IT编程  | 我要评论

这篇文章主要介绍了springboot validator枚举值校验功能实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一、前言

在spring项目中,校验参数功能使用hibernate validator是一个不错的选择,我们的项目中也是使用它来进行校验的,省去了很多难看的校验逻辑,使代码的可读性也大大增加,本章将带你使用hibernate validator自定义注解功能实现一个 枚举值校验的逻辑。

二、需求

我们先明确下我们的需求,在程序开发过程中,我们经常会有一个对象的属性值只能出现在一组常量中的校验需求,例如:用户性别字段gender只能等于male/female这两个其中一个值,用户账号的状态status只能等于:

normal/disabled/deleted其中一个等等,那么我们怎么能更好的校验这个参数呢?我们想拥有一个java注解,把它标记在所要校验的字段上,当开启hibernate validator校验时,就可以校验其字段值是否正确。

三、实现方案

上面提到的一组常量值,我们第一反应应该是定义一个枚举类,尽量不要放在一个统一的constants类下,这样当系统一旦庞大起来,常量是很难维护和查找的,所以前期代码也应该有一些规范性约束,这里我们约定一组常量值时使用枚举,并把该枚举类放在对应的类对象里(以上述所说的用户功能为例,我们应该把generenum、userstatusenum枚举放在user.java下,方便查找)

这里我们定义一个叫enumvalue.java的注解类,其下有两个主要参数一个是enumclass用于指定枚举类,enummethod指定要校验的方法,下面我们看代码实现。

四、代码实现

package com.zhuma.demo.annotation;
 
import java.lang.annotation.elementtype;
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target;
import java.lang.reflect.invocationtargetexception;
import java.lang.reflect.method;
 
import javax.validation.constraint;
import javax.validation.constraintvalidator;
import javax.validation.constraintvalidatorcontext;
import javax.validation.payload;
 
import org.assertj.core.util.strings;
 
/**
 * @desc 校验枚举值有效性
 *
 * @author zhumaer
 * @since 10/17/2017 3:13 pm
 */
@target({ elementtype.method, elementtype.field, elementtype.annotation_type })
@retention(retentionpolicy.runtime)
@constraint(validatedby = enumvalue.validator.class)
public @interface enumvalue {
 
  string message() default "{custom.value.invalid}";
 
  class<?>[] groups() default {};
 
  class<? extends payload>[] payload() default {};
 
  class<? extends enum<?>> enumclass();
 
  string enummethod();
 
  class validator implements constraintvalidator<enumvalue, object> {
 
    private class<? extends enum<?>> enumclass;
    private string enummethod;
 
    @override
    public void initialize(enumvalue enumvalue) {
      enummethod = enumvalue.enummethod();
      enumclass = enumvalue.enumclass();
    }
 
    @override
    public boolean isvalid(object value, constraintvalidatorcontext constraintvalidatorcontext) {
      if (value == null) {
        return boolean.true;
      }
 
      if (enumclass == null || enummethod == null) {
        return boolean.true;
      }
 
      class<?> valueclass = value.getclass();
 
      try {
        method method = enumclass.getmethod(enummethod, valueclass);
        if (!boolean.type.equals(method.getreturntype()) && !boolean.class.equals(method.getreturntype())) {
          throw new runtimeexception(strings.formatifargs("%s method return is not boolean type in the %s class", enummethod, enumclass));
        }
 
        if(!modifier.isstatic(method.getmodifiers())) {
          throw new runtimeexception(strings.formatifargs("%s method is not static method in the %s class", enummethod, enumclass));
        }
   
        boolean result = (boolean)method.invoke(null, value);
        return result == null ? false : result;
      } catch (illegalaccessexception | illegalargumentexception | invocationtargetexception e) {
        throw new runtimeexception(e);
      } catch (nosuchmethodexception | securityexception e) {
        throw new runtimeexception(strings.formatifargs("this %s(%s) method does not exist in the %s", enummethod, valueclass, enumclass), e);
      }
    }
 
  }
}

备注

1) 自定义注解需要实现constraintvalidator校验类,这里我们定义一个叫validator的类来实现它,同时实现它下面的两个方法initialize、isvalid,一个是初始化参数的方法,另一个就是校验逻辑的方法,本例子中我们将校验类定义在该注解内,用@constraint(validatedby = enumvalue.validator.class)注解指定校验类,内部逻辑实现比较简单就是使用了静态类反射调用验证方法的方式。

2) 对于被校验的方法我们要求,它必须是返回值类型为boolean或boolean,并且必须是一个静态的方法,返回返回值为null时我们认为是校验不通过的,按false逻辑走。

五、使用演示

校验的目标对象类

package com.zhuma.demo.model.po;
 
import java.io.serializable;
import java.util.date;
 
import javax.validation.constraints.pattern;
 
import org.hibernate.validator.constraints.length;
import org.hibernate.validator.constraints.notblank;
import org.hibernate.validator.constraints.range;
 
import com.zhuma.demo.annotation.enumvalue;
import com.zhuma.demo.validator.creategroup;
 
/**
 * @desc 用户po
 
 * @author zhumaer
 * @since 6/15/2017 2:48 pm
 */
public class user implements serializable {
 
  private static final long serialversionuid = 2594274431751408585l;
 
  /**
   * 用户id
   */
  private long id;
 
  /**
   * 登录密码
   */
  @notblank
  private string pwd;
 
  /**
   * 昵称
   */
  @notblank
  @length(min=1, max=64)
  private string nickname;
 
  /**
   * 头像
   */
  private string img;
 
  /**
   * 电话
   */
  @pattern(regexp = "^1[3-9]\\d{9}$")
  private string phone;
 
  /**
   * 账号状态
   */
  @enumvalue(enumclass=userstatusenum.class, enummethod="isvalidname")
  private string status;
 
  /**
   * 最新的登录时间
   */
  private date latestlogintime;
 
  /**
   * 最新的登录ip
   */
  private string latestloginip;
 
  private date createtime;
  private date updatetime;
   
  /**
   * 用户状态枚举
   */
  public enum userstatusenum {
    /**正常的*/
    normal,
    /**禁用的*/
    disabled,
    /**已删除的*/
    deleted;
 
    /**
     * 判断参数合法性
     */
    public static boolean isvalidname(string name) {
      for (userstatusenum userstatusenum : userstatusenum.values()) {
        if (userstatusenum.name().equals(name)) {
          return true;
        }
      }
      return false;
    }
  }
   
  //省略getter、setter方法
 
} 

controller类

package com.zhuma.demo.web.user;
 
import java.util.date;
 
import org.springframework.http.httpstatus;
import org.springframework.validation.annotation.validated;
import org.springframework.web.bind.annotation.postmapping;
import org.springframework.web.bind.annotation.requestbody;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.responsestatus;
import org.springframework.web.bind.annotation.restcontroller;
 
import com.zhuma.demo.model.po.user;
 
/**
 * @desc 用户管理控制器
 *
 * @author zhumaer
 * @since 6/20/2017 16:37 pm
 */
@restcontroller
@requestmapping("/users")
public class usercontroller {
 
  @postmapping
  @responsestatus(httpstatus.created)
  public user adduser(@validated @requestbody user user) {
    user.setid(10000l);
    user.setcreatetime(new date());
    return user;
  }
 
}  

校验结果

最后

好啦,一个简单的校验枚举值的注解功能完成了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网