Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化 (2)

需要被 springboot 扫描并注册为单例

@Component public class ValidUtil { @Autowired private Validator validator; public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) { return validator.validate(object, groups); } public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) { return validator.validateValue(beanType, propertyName, value, groups); } /** * 校验参数,并返回第一个错误提示 * @param t 验证的对象 * @param groups 验证的组别 * @param <T> 对象擦除前原类型 * @return 第一个错误提示 */ public <T> void validAndReturnFirstErrorTips(T t, Class<?>... groups) { Set<ConstraintViolation<T>> validate = validator.validate(t, groups); if (validate.size() > 0) { ConstraintViolation<T> next = validate.iterator().next(); String message = next.getRootBeanClass().getName() + "-" + next.getPropertyPath() + "-" + next.getMessage(); throw new ValidError(message); } } /** * 校验参数,并返回第一个错误提示 * @param targetClass 验证的对象的 class 类型 * @param fieldName 需要验证的名字 * @param obj 需要属性值 * @param groups 验证的组别 * @param <T> 对象擦除前原类型 * @return 第一个错误提示 */ public <T> void validAndReturnFirstErrorTips(Class targetClass, String fieldName, Object obj, Class<?>... groups) { Set<ConstraintViolation<T>> validate = validator.validateValue(targetClass, fieldName, obj, groups); if (validate.size() > 0) { String message = targetClass.getName() + "-" + fieldName + "-" + validate.iterator().next().getMessage(); throw new ValidError(message); } } } AOP 配置

主要原理是利用 aop 拦截方法执行参数,对参数获取注解。再利用工具类来验证参数,如果验证不通过,直接抛出自定义错误,自定义错误已经全局统一处理了。

@Aspect @Component public class ValidatorAOP { @Autowired private ValidUtil validUtil; /** *  定义拦截规则:拦截 com.servic  包下面的所有类中,有 @Service 注解的方法。 */ @Pointcut("execution(* com.service..*(..)) and @annotation(org.springframework.stereotype.Service)") public void controllerMethodPointcut() { } /** *  拦截器具体实现 */ @Around("controllerMethodPointcut()") // 指定拦截器规则;也可以直接把 “execution(* com.xjj.........)” 写进这里 public Object Interceptor(ProceedingJoinPoint pjp) { MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); Method method = methodSignature.getMethod(); Annotation[][] argAnnotations = method.getParameterAnnotations(); Object[] args = pjp.getArgs(); for (int i = 0; i < args.length; i++) { for (Annotation annotation : argAnnotations[i]) { if (Validated.class.isInstance(annotation)) { Validated validated = (Validated) annotation; Class<?>[] groups = validated.value(); validUtil.validAndReturnFirstErrorTips(args[i], groups); } } } try { return pjp.proceed(args); } catch (Throwable throwable) { throwable.printStackTrace(); } return true; } } 验证注解 @Min @NotNull 使用方法

不能写在实现类上,只能在接口中使用注解

与 Controller 使用方式基本一样

@Validated public interface TodoService { /** * 查询 单个待办 * @param id 序号 * @return 单个待办 */ Msg getVo(@Min(value = 1, message = "待办 id 不能小于 1。") long id); /** * 添加数据 * @param todo 对象 */ Msg add(@Validated({S.Insert.class}) Todo todo); } 分享几个自定义验证注解 字符串判空验证 package javax.validation.constraints; import javax.validation.Constraint; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.Payload; import java.lang.annotation.*; /** * 字符串判空验证,hibernate 自带的可能有问题,使用不了,需要重写,package 是不能变的。 */ @Documented @Constraint( validatedBy = {NotBlank.NotBlankValidator.class} ) @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface NotBlank { Class<?>[] groups() default {}; String message() default "{notBlank}"; Class<? extends Payload>[] payload() default {}; class NotBlankValidator implements ConstraintValidator<NotBlank, Object> { public NotBlankValidator() { } @Override public void initialize(NotBlank constraintAnnotation) { } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { return value != null && !value.toString().isEmpty(); } } } 类型判断,判断 type 是否为其中一个值,可以根据验证组自定义判断

resources/todo.properties

todo.todoType.insert=新增时,待办类型只能是 非项目任务、项目任务、问题 之中一。 todo.todoType.update=修改时,待办类型只能是风险、评审待办问题 之中一。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyyydg.html