validation统一表单验证(含自定义枚举验证)

一般我们对前端传输的参数做判断时,可能都是以以下方式进行判断,如果再加上字段的长度、正则等校验的话就会显得代码很累赘了。

// 新增/修改通用参数非空校验
if (StringUtil.isBlank(menu.getParentId())) {
  throw new LsException(ResultEnum.PARAM_MISSING_ERROR, "父级菜单ID不能为空!");
}
if (StringUtil.isBlank(menu.getMenuName())) {
  throw new LsException(ResultEnum.PARAM_MISSING_ERROR, "菜单名称不能为空!");
}
if (StringUtil.isBlank(menu.getMenuName())) {
  throw new LsException(ResultEnum.PARAM_MISSING_ERROR, "菜单类型不能为空!");
}
/**>>>>>>>>>>>>>>>>>>>>>>>>枚举类字段校验开始<<<<<<<<<<<<<<<<<<<<<<<<<**/
// 校验菜单类型是否存在
if (Objects.nonNull(model.getMenuType())) {
  MenuEnum.MenuType menuType = MenuEnum.MenuType.getByType(model.getMenuType());
  if (Objects.isNull(menuType)) {
    throw new LsException(ResultEnum.PARAM_CHECKED_ERROR, "此菜单类型不存在!");
  }
}
// 校验打开方式是否存在
if (Objects.nonNull(model.getTarget())) {
  MenuEnum.Target target = MenuEnum.Target.getByTarget(model.getTarget());
  if (Objects.isNull(target)) {
    throw new LsException(ResultEnum.PARAM_CHECKED_ERROR, "此打开方式不存在!");
  }
}
// 校验菜单状态是否存在
if (Objects.nonNull(model.getVisible())) {
  MenuEnum.Visible visible = MenuEnum.Visible.getByVisible(model.getVisible());
  if (Objects.isNull(visible)) {
    throw new LsException(ResultEnum.PARAM_CHECKED_ERROR, "此菜单状态不存在!");
  }
}
/**>>>>>>>>>>>>>>>>>>>>>>>>枚举类字段校验结束<<<<<<<<<<<<<<<<<<<<<<<<<**/

改进方案,使用Spring表单验证注解:

1、表单验证工具类ModelValidator

/**
 * 软件版权:流沙~~
 * 修改日期   修改人员     修改说明
 * =========  ===========  =====================
 * 2019/9/30    liusha   新增
 * =========  ===========  =====================
 */
package com.sand.base.util.validator;

import com.sand.base.enums.CodeEnum;
import com.sand.base.exception.LsException;
import com.sand.base.util.lang3.StringUtil;
import com.sand.base.util.spring.SpringUtil;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 功能说明:表单校验
 * 开发人员:@author liusha
 * 开发日期:2019/9/30 13:57
 * 功能描述:表单校验,验证非空、长度、正则等等
 */
public class ModelValidator {
  /**
   * 校验失败条数key值
   */
  public static final String CHECKED_FAIL_NUM = "checkedFailNum";
  /**
   * 校验失败原因key值
   */
  public static final String CHECKED_FAIL_MSG = "checkedFailNum";
  /**
   * 校验通过的数据列表key值
   */
  public static final String CHECKED_ENTITY_LIST = "checkedEntityList";

  /**
   * 表单验证(对应实体类配置注解)
   *
   * @param entity 校验对象
   * @param <T>
   */
  public static <T extends Object> void checkModel(T entity) {
    checkModel(entity, null);
  }

  /**
   * 表单验证指定字段(对应实体类配置注解)
   *
   * @param entity 校验对象
   * @param <T>
   */
  public static <T extends Object> void checkModel(T entity, String fieldName) {
    Set<ConstraintViolation<T>> violationSet;
    if (StringUtil.isNotBlank(fieldName)) {
      violationSet = SpringUtil.getBean(Validator.class).validateProperty(entity, fieldName);
    } else {
      violationSet = SpringUtil.getBean(Validator.class).validate(entity);
    }
    if (violationSet.size() > 0) {
      String errorMsg = violationSet.iterator().next().getMessage();
      if (StringUtil.isBlank(errorMsg)) {
        errorMsg = "请求参数有误";
      }
      throw new LsException(CodeEnum.PARAM_CHECKED_ERROR, errorMsg);
    }
  }

  /**
   * 批量表单验证(对应实体类配置注解)
   *
   * @param entityList 校验对象列表
   * @param <T>
   * @return 校验结果
   */
  public static <T extends Object> Map<String, Object> checkModelList(List<T> entityList) {
    Map<String, Object> checkedMap = new HashMap<>();
    // 校验通过的数据列表
    List<T> checkedEntityList = new ArrayList<>();
    // 校验失败原因
    StringBuilder checkedFailMsg = new StringBuilder();
    // 校验失败条数
    int checkedFailNum = 0;
    for (int i = 0; i < entityList.size(); i++) {
      try {
        checkModel(entityList.get(i));
      } catch (Exception e) {
        checkedFailNum++;
        checkedFailMsg.append("第" + (i + 1) + "条数据:" + e.getMessage() + ";");
      }
      checkedEntityList.add(entityList.get(i));
    }
    checkedMap.put(CHECKED_FAIL_NUM, checkedFailNum);
    checkedMap.put(CHECKED_FAIL_MSG, checkedFailMsg);
    checkedMap.put(CHECKED_ENTITY_LIST, checkedEntityList);
    return checkedMap;
  }
}

2、自定义枚举验证

1)、枚举注解@EnumValidAnnotation

/**
 * 软件版权:流沙~~
 * 修改日期   修改人员     修改说明
 * =========  ===========  =====================
 * 2019/9/26    liusha   新增
 * =========  ===========  =====================
 */
package com.sand.base.annotation;

import com.sand.base.util.lang3.StringUtil;
import com.sand.base.util.validator.EnumValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 功能说明:验证枚举类
 * 开发人员:@author liusha
 * 开发日期:2019/9/26 13:46
 * 功能描述:对表单中存在枚举类型的字段进行校验
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumValidator.class})
@Documented
public @interface EnumValidAnnotation {
  /**
   * 提示消息
   *
   * @return
   */
  String message() default StringUtil.EMPTY;

  /**
   * 对应的枚举类
   *
   * @return
   */
  Class<?>[] target() default {};

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};
}

2)、枚举验证器EnumValidator

/**
 * 软件版权:流沙~~
 * 修改日期   修改人员     修改说明
 * =========  ===========  =====================
 * 2019/9/26    liusha   新增
 * =========  ===========  =====================
 */
package com.sand.base.util.validator;

import com.sand.base.annotation.EnumValidAnnotation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.Objects;

/**
 * 功能说明:枚举验证器
 * 开发人员:@author liusha
 * 开发日期:2019/9/26 13:51
 * 功能描述:自定义枚举验证器
 */
public class EnumValidator implements ConstraintValidator<EnumValidAnnotation, String> {
  /**
   * 枚举类
   */
  Class<?>[] clzs;

  @Override
  public void initialize(EnumValidAnnotation constraintAnnotation) {
    clzs = constraintAnnotation.target();
  }

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    if (clzs.length > 0) {
      try {
        for (Class<?> clz : clzs) {
          if (clz.isEnum()) {
            // 枚举类验证
            Object[] objs = clz.getEnumConstants();
            for (Object obj : objs) {
              Class<?> enumClz = obj.getClass();
              Field[] fields = enumClz.getDeclaredFields();
              for (Field field : fields) {
                // 访问私有成员属性开关
                field.setAccessible(true);
                EnumValidAnnotation enumValidAnnotation = field.getAnnotation(EnumValidAnnotation.class);
                if (Objects.nonNull(enumValidAnnotation)) {
                  // 获取成员属性的值
                  Object enumValue = field.get(obj);
                  if (value.equals(enumValue.toString())) {
                    return true;
                  }
                }
              }
            }
          }
        }
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    } else {
      return true;
    }
    return false;
  }
}

3)、枚举类中要转换的成员属性也需要添加@EnumValidAnnotation(主要是为了通用)

/**
 * 软件版权:流沙~~
 * 修改日期   修改人员     修改说明
 * =========  ===========  =====================
 * 2019/8/28    liusha   新增
 * =========  ===========  =====================
 */
package com.sand.sys.enums;

import com.sand.base.annotation.EnumValidAnnotation;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Objects;

/**
 * 功能说明:存放系统菜单枚举类
 * 开发人员:@author liusha
 * 开发日期:2019/8/28 19:48
 * 功能描述:使用@EnumValidAnnotation可用于表单校验,使用getBy*返回给客户端转译等
 */
public final class MenuEnum {
  @Getter
  @AllArgsConstructor
  public enum MenuType {
    // 菜单类型
    M("M", "目录"),
    C("C", "菜单"),
    F("F", "按钮");

    @EnumValidAnnotation
    private final String type;
    private final String description;

    public static MenuType getByType(String type) {
      for (MenuType item : MenuType.values()) {
        if (Objects.equals(type, item.getType())) {
          return item;
        }
      }
      return null;
    }
  }

  @Getter
  @AllArgsConstructor
  public enum Target {
    // 打开方式
    ITEM("_item", "页签中打开"),
    BLANK("_blank", "新窗口打开"),
    CURRENT("_current", "当前窗口打开");

    @EnumValidAnnotation
    private final String target;
    private final String description;

    public static Target getByTarget(String target) {
      for (Target item : Target.values()) {
        if (Objects.equals(target, item.getTarget())) {
          return item;
        }
      }
      return null;
    }
  }

  @Getter
  @AllArgsConstructor
  public enum Visible {
    // 菜单状态
    SHOW("0", "显示"),
    HIDE("1", "隐藏");

    @EnumValidAnnotation
    private final String visible;
    private final String description;

    public static Visible getByVisible(String visible) {
      for (Visible item : Visible.values()) {
        if (Objects.equals(visible, item.getVisible())) {
          return item;
        }
      }
      return null;
    }
  }
}

3、需要验证的实体类添加相应注解,@NotBlank、@Length以及自定义枚举注解@EnumValidAnnotation

/**
 * 软件版权:流沙~~
 * 修改日期   修改人员     修改说明
 * =========  ===========  =====================
 * 2019/8/26    liusha   新增
 * =========  ===========  =====================
 */
package com.sand.sys.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sand.base.annotation.EnumValidAnnotation;
import com.sand.base.constant.Constant;
import com.sand.base.core.entity.BaseEntity;
import com.sand.sys.enums.MenuEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;

/**
 * 功能说明:系统菜单
 * 开发人员:@author liusha
 * 开发日期:2019/8/26 13:38
 * 功能描述:系统菜单
 */
@Data
@Accessors(chain = true)
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@TableName(Constant.TABLE_PREFIX_SYS + "menu")
public class SysMenu extends BaseEntity {
  private static final long serialVersionUID = -2854114810573968874L;
  /**
   * 菜单ID
   */
  @TableId
  private String menuId;
  /**
   * 父菜单ID
   */
  @NotBlank(message = "[父级菜单ID]不能为空哟!")
  private String parentId;
  /**
   * 菜单名称
   */
  @NotBlank(message = "[菜单名称]不能为空哟!")
  @Length(max = 64, message = "[菜单名称]不能超过64个字符呢!")
  private String menuName;
  /**
   * 菜单类型(M目录 C菜单 F按钮)
   */
  @NotBlank(message = "[菜单类型]不能为空哟!")
  @EnumValidAnnotation(message = "[菜单类型]不存在!", target = MenuEnum.MenuType.class)
  private String menuType;
  /**
   * 菜单URL
   */
  @Length(max = 128, message = "[菜单URL]不能超过128个字符呢!")
  private String menuUrl;
  /**
   * 显示顺序
   */
  private int orderNum;
  /**
   * 打开方式(_item 页签中打开,_blank 新窗口打开,_current 当前窗口打开)
   */
  @EnumValidAnnotation(message = "[打开方式]不存在!", target = MenuEnum.Target.class)
  private String target;
  /**
   * 菜单状态(0显示 1隐藏)
   */
  @EnumValidAnnotation(message = "[菜单状态]不存在!", target = MenuEnum.Visible.class)
  private String visible;
  /**
   * 权限标识
   */
  @Length(max = 128, message = "[权限标识]不能超过128个字符呢!")
  private String purview;
  /**
   * 菜单图标
   */
  private String icon;

}

4、如果需要使用表单验证,可以在对应的controller或者service上加上:

// 表单注解验证,非空,长度,正则等校验
ModelValidator.checkModel(model);

列举一些Spring表单验证常用的注解:


注解


适用的数据类型


说明


@AssertFalse


Boolean, boolean


验证注解的元素值是false


@AssertTrue


Boolean, boolean


验证注解的元素值是true


@DecimalMax(value=x)


BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence.


验证注解的元素值小于等于@ DecimalMax指定的value值


@DecimalMin(value=x)


BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence.


验证注解的元素值小于等于@ DecimalMin指定的value值


@Digits(integer=整数位数, fraction=小数位数)


BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence.


验证注解的元素值的整数位数和小数位数上限


@Future


java.util.Date, java.util.Calendar; Additionally supported by HV, if theJoda Time date/time API is on the class path: any implementations ofReadablePartial andReadableInstant.


验证注解的元素值(日期类型)比当前时间晚


@Max(value=x)


BigDecimal, BigInteger, byte, short,int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type ofCharSequence (the numeric value represented by the character sequence is evaluated), any sub-type of Number.


验证注解的元素值小于等于@Max指定的value值


@Min(value=x)


BigDecimal, BigInteger, byte, short,int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the char sequence is evaluated), any sub-type of Number.


验证注解的元素值大于等于@Min指定的value值


@NotNull


Any type


验证注解的元素值不是null


@Null


Any type


验证注解的元素值是null


@Past


java.util.Date, java.util.Calendar; Additionally supported by HV, if theJoda Time date/time API is on the class path: any implementations ofReadablePartial andReadableInstant.


验证注解的元素值(日期类型)比当前时间早


@Pattern(regex=正则表达式, flag=)


String. Additionally supported by HV: any sub-type of CharSequence.


验证注解的元素值与指定的正则表达式匹配


@Size(min=最小值, max=最大值)


String, Collection, Map and arrays. Additionally supported by HV: any sub-type of CharSequence.


验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小


@Valid


Any non-primitive type(引用类型)


验证关联的对象,如账户对象里有一个订单对象,指定验证订单对象


@NotEmpty


CharSequence,CollectionMap and Arrays


验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)


@Range(min=最小值, max=最大值)


CharSequence, Collection, Map and Arrays,BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types


验证注解的元素值在最小值和最大值之间


@NotBlank


CharSequence


验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格


@Length(min=下限, max=上限)


CharSequence


验证注解的元素值长度在min和max区间内


@Email


CharSequence


验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

原文地址:https://www.cnblogs.com/54hsh/p/11614803.html

时间: 2024-10-01 02:42:16

validation统一表单验证(含自定义枚举验证)的相关文章

jquery.validation.js 表单验证

jquery.validation.js 表单验证 官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation jQuery plugin: Validation 使用说明 一导入js库 <script src="../js/jquery.js" type="text/javascript"></script> <script src="../js/jq

jQuery插件——Validation Plugin表单验证

jQuery表单验证插件:https://plugins.jquery.com/tag/validate/ jQuery Validation插件是最常用的插件之一:http://jqueryvalidation.org/ 一.基本API rules里面的“username”是input中的“name”,不是“id”. 表单验证,主要是俩:一是规则,二是提示信息 当在使用validate插件的时候: 使用validate()方法的时候将debug设置为true,那么表单不会提交,只进行检查,调试

jQuery Validation Engine 表单验证

功能强大的 jQuery 表单验证插件,适用于日常的 E-mail.电话号码.网址等验证及 Ajax 验证,除自身拥有丰富的验证规则外,还可以添加自定义的验证规则. 兼容 IE 6+, Chrome, Firefox, Safari, Opera 10+ 版本: jQuery v1.7+ jQuery Validation Engine v2.6.2 相对 2.2.4 版本的一些区别: 部分参数功能发生变化: 输入控件可以不写 id 属性: 参数 onSuccess 和 onFailure 改为

jQuery Validate 表单验证插件----自定义一个验证方法

一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW  访问密码 f224 二.引入依赖包 <script src="../../scripts/jquery-1.3.1.js" type="text/javascript"></script> <script src="lib/jquery.validate.js" type="text/javascript"

jQuery Validate【为表单提供了强大的验证功能,让客户端表单验证变得更简单】

jQuery Validate jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求.该插件捆绑了一套有用的验证方法,包括 URL 和电子邮件验证,同时提供了一个用来编写用户自定义方法的 API.所有的捆绑方法默认使用英语作为错误信息,且已翻译成其他 37 种语言. 该插件是由 J?rn Zaefferer 编写和维护的,他是 jQuery 团队的一名成员,是 jQuery UI 团队的主要开发人员,是 QUn

【ExtJs】ExtJs的表单插件与表单布局、提交与验证

利用ExtJs的Anchor可以为ExtJs自带的表单Form各个组件进行布局,当然,使用<[ExtJs]带日期组件的文本输入框.容器与Ext.Msg.alert告警框告警两次>(点击打开链接)中的vbox也是可以的.其实ExtJs的表单插件与表单布局并不是关键,ExtJs的表单验证还好,就几行语句就能够完成.关键是ExtJs的表单提交必须通过Ajax方式,而在后台必须传回一个Json完成表单的提交,可能有点复杂,下面就以php作为ExtJs的后台处理来说明问题ExtJs的表单.aspx,js

提交表单的时候加上Ajax验证

<form id="fo" action="addDiskSr.action" method="post" > <table> <tr> <td colspan="2" class="subtitle" >存储服务器内容录入</td> </tr> <tbody> <tr> <th width="3

jquery.validation.js 表单验证 完整例子使用

1 <form id="registerform" method="get"> 2 <table> 3 <tbody> 4 <tr> 5 <td class="w140"><i class="mark orange">*</i>邮箱:</td> 6 <td class="w348"><input

yii 使用cactiveform 创建表单时候遇到的一些验证问题和使用ajax_form时重置验证规则的解决办法

yii  cactiveform 在添加验证信息的时候, 有时候稍有不慎,可能导致客户端验证不起作用,尤其是像我这种初学者来说,更是无解了, 好在今天有点时间, 一路追查这个问题,最后从js 端一直追到了php中, 终于找到了罪魁祸首,原来还是我们自己,哈哈  接下来就简单分享一下: 首先让我们来看看所有的客户端js验证是怎么添加上去的: 在CActiveForm.php :383行 中有这么一句话: $options=CJavaScript::encode($options); $cs->re