弹簧数据rest文档描述了验证实体 的方法:
您只需要向验证器的实例注册 正确的事件
在调用验证器的bean
是否有一种方法可以应用[声明性] JSR-303实体的验证 它们被传递给" beforesave" RepositoryEventHandler
s?
从我到目前为止的调试,事实并非如此," beforesave" RepositoryEventHandler
s在进行任何验证之前就被解雇了。
我可以直接在处理程序中编写验证呼叫,但这与"验证后"的处理方式有所不同。
顺便说一句。事件处理程序呼叫的顺序似乎在Spring Boot 1.3.8和1.5.1之间发生了变化。过去,验证发生在@HandleBeforeSave
处理程序之前。在1.5.1 ValidatingRepositoryEventListener
fires 之后 @HandleBeforeSave
处理程序。
更新:
如评论中所述,弹簧数据中似乎有一张票,静止jira对此开放。
作为解决方法:
-
创建
PreflightValidatingRepositoryEventListener
,该CC_7扩展ValidatingRepositoryEventListener
并用@Order(Ordered.HIGHEST_PRECEDENCE)
。@Component @Order(Ordered.HIGHEST_PRECEDENCE) public class PreflightValidatingRepositoryEventListener extends ValidatingRepositoryEventListener { public PreflightValidatingRepositoryEventListener(ObjectFactory<PersistentEntities> persistentEntitiesFactory) { super(persistentEntitiesFactory); } }
-
添加与
相同的验证器RepositoryEventHandler
0@Configuration @Import(RepositoryRestMvcConfiguration.class) public class Config extends RepositoryRestConfigurerAdapter { @Bean @Primary public Validator validator() { return new LocalValidatorFactoryBean(); } @Autowired private PreflightValidatingRepositoryEventListener preflightValidatingRepositoryEventListener; @Override public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) { Validator validator = validator(); validatingListener.addValidator("beforeCreate", validator); validatingListener.addValidator("beforeSave", validator); preflightValidatingRepositoryEventListener.addValidator("beforeCreate", validator); preflightValidatingRepositoryEventListener.addValidator("beforeSave", validator); } }
注意:验证将进行两次
作为替代方法,这是基于此示例(次要更改)的完全验证方面。不要忘记添加@EnableAspectJAutoProxy
激活该方面并将其放入扫描config的包装中。
@Aspect
@Component
public class RestRepositoryValidationAspect {
@Autowired
private Validator validator;
@Pointcut("@annotation(org.springframework.data.rest.core.annotation.HandleBeforeCreate)")
private void beforeCreateInvocation() {
}
@Pointcut("@annotation(org.springframework.data.rest.core.annotation.HandleBeforeSave)")
private void beforeSaveInvocation() {
}
@Around("beforeCreateInvocation() || beforeSaveInvocation()")
public Object validateBeforeRepostioryEventHandler(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
Annotation[][] argAnnotations = method.getParameterAnnotations();
String[] argNames = methodSignature.getParameterNames();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
if (hasValidAnnotations(argAnnotations[i])) {
validateArg(args[i], argNames[i]);
}
}
return joinPoint.proceed(args);
}
private boolean hasValidAnnotations(Annotation[] annotations) {
if (annotations.length < 1) {
return false;
}
for (Annotation annotation : annotations) {
if (Valid.class.isInstance(annotation)) {
return true;
}
}
return false;
}
private void validateArg(Object arg, String argName) {
BindingResult result = getBindingResult(arg, argName);
validator.validate(arg, result);
if (result.hasErrors()) {
throw new RepositoryConstraintViolationException(result);
}
}
private BindingResult getBindingResult(Object target, String targetName) {
return new BeanPropertyBindingResult(target, targetName);
}
}
必须用@Valid
注释标记需要验证的存储库事件处理程序参数,例如
@HandleBeforeSave
public void handleSave(@Valid MyEntity myEntity) {
...
}