目录
- 概述
- 案例需求分析
- 案例自定义校验实现
- 案例业务对象使用
概述
spring mvc 工程中,后端接收前端传入的对象时,需要对对象中的属性做合法性校验,避免业务数据出现脏数据, spring 自身有多重校验方式,本文基于java bean校验方式进行阐述, spring java bean 校验依赖于hibernate validator, 详细校验属性参考官网: https://hibernate.org/validator/
本文框架版本:
spring boot: 2.3.5.RELEASE
案例需求分析
开发项目中,经常会使用到枚举,前端传入到后端时,需要知道对应的值,是否在枚举范围内,如果没在枚举范围内,则提示异常信息
异常抛给前端的格式自定义,本人使用的spring 自定义异常,将此异常捕获后,包装成前端可解析的格式
案例自定义校验实现
自定义注解:EnumValid
@Constraint(validatedBy = {EnumValidator.class}) @Target({ElementType.FIELD, TYPE_USE, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface EnumValid { String message(); Class>[] groups() default {}; Class extends Payload>[] payload() default {}; Class> target(); String field() default "name"; }
校验器实现: EnumValidator
public class EnumValidator implements ConstraintValidator{ /** 枚举需要校验的属性名**/ private static final String DEFAULT_FIELD = "code"; /** 枚举类 */ private Class> clazz; /** 比较的属性 */ private String field; @Override public void initialize(EnumValid constraintAnnotation) { this.clazz = constraintAnnotation.target(); this.field = constraintAnnotation.field(); } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { if (null == value) { return true; } if (!clazz.isEnum()) { return false; } Object[] enumOptions = clazz.getEnumConstants(); try { Method method; if (StringUtils.equals(field, DEFAULT_FIELD)) { method = clazz.getMethod(field); } else { String getMethodName = "get" + upperCaseFirstChar(this.field); method = clazz.getMethod(getMethodName); } for (Object obj : enumOptions) { Object code = method.invoke(obj, null); if (StringUtils.equals(value.toString(), code.toString())) { return true; } } } catch (Exception e) { return false; } return false; } private static String upperCaseFirstChar(String str) { char[] cs = str.toCharArray(); cs[0] -= 32; return String.valueOf(cs); } }
案例业务对象使用
Note: 案例中使用了lombok,如未使用,则自行生成get以及构造方法; cotroller 以及实现类这里就不再赘述
枚举类: SexEnum
@Getter @NoArgsConstructor @AllArgsConstructor public enum SexEnum { YEAR(1, "年"), SELF_YEAR(10, "半年"), QUARTER(20, "季度"), MONTH(30, "月"); private Integer code; private String desc; }
接收前端的对象类: UserVo ,此对象中@EnumValid为自定义校验注解
@Data public class RatingLevelTaskVo implements Serializable { @NotBlank(message = "用户名称不可为空") private String userName; @NotNull(message = "用户性别不可为空") @EnumValid(target = SexEnum.class, field = "code", message = "用户性别不允许非法值") private Integer sex; }