Springboot动态装载卸载Bean
springboot的validation(转)
springboot数据格式验证(二)——自定义日期格式验证
springboot数据格式验证(一)
在springboot中自定义了一个校验注解
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD,ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint(validatedBy = UniqueProcessInfoValidator.class) public @interface UniqueProcessInfo { String message() default "jobName在当前项目中已存在!"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
下面是指定的校验逻辑类
//研究发现hibernate验证器拿不到spring bean, processInfoService总是null!!! @Service public class UniqueProcessInfoValidator implements ConstraintValidator<UniqueProcessInfo, ProcessInfo> { @Autowired private ProcessInfoService processInfoService; @Override public boolean isValid(ProcessInfo processInfo, ConstraintValidatorContext constraintValidatorContext) { boolean exists = processInfoService.existsDuplicateProcess(processInfo); return !exists; } }
经研究发现validator是hibernate维护的,所以在启动的时候拿不到spring中的Bean。
不得已需要用到spring动态装载bean的方式。
改写成下面这种写法
@Slf4j public class UniqueProcessInfoValidator implements ConstraintValidator<UniqueProcessInfo, ProcessInfo> { @Override public boolean isValid(ProcessInfo processInfo, ConstraintValidatorContext constraintValidatorContext) { ProcessInfoService processInfoService = SpringContextUtil.getBean(ProcessInfoService.class); boolean exists = processInfoService.existsDuplicateProcess(processInfo); log.info(String.valueOf(exists)); return !exists; } }
然后就可以了!
附录:
验证经验
1.把校验行为从分层中剥离出来,不是在哪一层做,而是在 Bean 上做。
2.要对校验项预置好默认的提示信息,这样当校验不通过时,用户能获得明确的修正提示
3.要把不带业务含义的格式校验注解放到 Bean 的类定义之上,把带业务逻辑的校验放到 Bean 的类定义的外面,
原因是放在类定义中的注解能够自动运行,而放到类外面的业务校验需要像前面的示例代码那样,明确标出注解时才会运行,带业务逻辑的校验,通常就需要外部资源参与执行,这不仅仅是多消耗一点时间和运算资源的问题,因为我们很难保证依赖的每个服务都是幂等的,重复执行校验很可能会带来额外的副作用。因此应该放到外面,让使用者自行判断是否要触发
4.对应校验对象不是bean的情况,请参考下面博文,将校验加在函数参数上