一般我们对前端传输的参数做校验时,可能都是以以下方式进行,如果再加上字段的长度、正则等校验的话就会显得代码很累赘。
// 新增/修改通用参数非空校验 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, "此菜单状态不存在!"); } } /**>>>>>>>>>>>>>>>>>>>>>>>>枚举类字段校验结束<<<<<<<<<<<<<<<<<<<<<<<<<**/
改进方案,使用Hibernate Validator嵌入式注解处理器(概念可参考《深入理解Java虚拟机》——周志明第10.4节)进行表单验证:
1、表单验证工具类ModelValidator
/** * 软件版权:流沙~~ * 修改日期 修改人员 修改说明 * ========= =========== ===================== * 2019/9/30 liusha 新增 * ========= =========== ===================== */ package com.sand.common.util.validator; import com.sand.common.enums.CodeEnum; import com.sand.common.exception.BusinessException; import com.sand.common.util.lang3.StringUtil; import com.sand.common.util.spring.SpringUtil; import lombok.extern.slf4j.Slf4j; 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 * 功能描述:表单校验,验证非空、长度、正则等等 */ @Slf4j public class ModelValidator { /** * 校验失败条数key值 */ public static final String CHECKED_FAIL_NUM = "checkedFailNum"; /** * 校验失败原因key值 */ public static final String CHECKED_FAIL_MSG = "checkedFailMsg"; /** * 校验通过的数据列表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) { try { 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 msg = violationSet.iterator().next().getMessage(); if (StringUtil.isBlank(msg)) { msg = "请求参数有误"; } throw new BusinessException(CodeEnum.PARAM_CHECKED_ERROR, msg); } } catch (Exception e) { log.error("表单验证出错,", e); String errorMsg = (e instanceof BusinessException) ? e.getMessage() : "表单验证出错"; throw new BusinessException(CodeEnum.PARAM_CHECKED_ERROR, errorMsg); } } /** * 批量表单验证(对应实体类配置注解) * * @param entityList 校验对象列表 * @param <T> * @return 校验结果 */ public static <T extends Object> Map<String, Object> checkModelList(List<T> entityList) { // 校验失败条数 int checkedFailNum = 0; // 校验失败原因 StringBuilder checkedFailMsg = new StringBuilder(); // 校验通过的数据列表 List<T> checkedEntityList = new ArrayList<>(); for (int i = 0; i < entityList.size(); i++) { try { checkModel(entityList.get(i)); } catch (Exception e) { checkedFailNum++; checkedFailMsg.append("第" + (i + 1) + "条数据:" + e.getMessage() + ";"); continue; } checkedEntityList.add(entityList.get(i)); } Map<String, Object> checkedMap = new HashMap<>(); checkedMap.put(CHECKED_FAIL_NUM, checkedFailNum); checkedMap.put(CHECKED_FAIL_MSG, checkedFailMsg); checkedMap.put(CHECKED_ENTITY_LIST, checkedEntityList); return checkedMap; } }