我一直在尝试将 spring 验证器添加到 spring-data-rest 项目中。
我按照以下链接设置了“入门”应用程序:http://spring.io/guides/gs/accessing-data-rest/
...现在我尝试按照此处的文档添加自定义 PeopleValidator: http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html
我的自定义 PeopleValidator 看起来像
package hello;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class PeopleValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public void validate(Object target, Errors errors) {
errors.reject("DIE");
}
}
...我的 Application.java 类现在看起来像这样
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public PeopleValidator beforeCreatePeopleValidator() {
return new PeopleValidator();
}
}
我希望 POST 到
http://localhost:8080/people
URL 会导致某种错误,因为 PeopleValidator 会拒绝所有内容。但是,不会引发任何错误,也不会调用验证器。
我还尝试手动设置验证器,如 spring-data-rest 文档的第 5.1 节所示。
我错过了什么?
因此,“保存”事件之前/之后似乎仅在 PUT 和 PATCH 上触发。发布时,会触发之前/之后的“创建”事件。
我使用
configureValidatingRepositoryEventListener
覆盖再次尝试手动方式,它起作用了。我不确定我在工作中所做的事情与在家里所做的事情有何不同。明天我得看看。
我当然很想听听其他人是否有关于为什么它不起作用的建议。
郑重声明,新的 Application.java 类如下所示。
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application extends RepositoryRestMvcConfiguration {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", new PeopleValidator());
}
}
看起来该功能目前尚未实现(2.3.0),不幸的是事件名称没有常量,否则下面的解决方案不会那么脆弱。
Configuration
使用正确的事件将所有正确命名的 Validator
beans 添加到 ValidatingRepositoryEventListener
。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.validation.Validator;
@Configuration
public class ValidatorRegistrar implements InitializingBean {
private static final List<String> EVENTS;
static {
List<String> events = new ArrayList<String>();
events.add("beforeCreate");
events.add("afterCreate");
events.add("beforeSave");
events.add("afterSave");
events.add("beforeLinkSave");
events.add("afterLinkSave");
events.add("beforeDelete");
events.add("afterDelete");
EVENTS = Collections.unmodifiableList(events);
}
@Autowired
ListableBeanFactory beanFactory;
@Autowired
ValidatingRepositoryEventListener validatingRepositoryEventListener;
@Override
public void afterPropertiesSet() throws Exception {
Map<String, Validator> validators = beanFactory.getBeansOfType(Validator.class);
for (Map.Entry<String, Validator> entry : validators.entrySet()) {
EVENTS.stream().filter(p -> entry.getKey().startsWith(p)).findFirst()
.ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
}
}
}
有点在黑暗中刺伤 - 我没有使用过
spring-data-rest
。然而,在阅读了您正在关注的教程后,我认为问题是您需要 PersonValidator
而不是 PeopleValidator
。相应地重命名所有内容:
个人验证器
package hello;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class PersonValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public void validate(Object target, Errors errors) {
errors.reject("DIE");
}
}
申请
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public PersonValidator beforeCreatePersonValidator() {
return new PersonValidator();
}
}
另一种方法是使用此处指定的带注释的处理程序 http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/events-chapter.html#d5e443
以下是如何使用带注释的处理程序的示例:
import gr.bytecode.restapp.model.Agent;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.HandleBeforeSave;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import org.springframework.stereotype.Component;
@Component
@RepositoryEventHandler(Agent.class)
public class AgentEventHandler {
public static final String NEW_NAME = "**modified**";
@HandleBeforeCreate
public void handleBeforeCreates(Agent agent) {
agent.setName(NEW_NAME);
}
@HandleBeforeSave
public void handleBeforeSave(Agent agent) {
agent.setName(NEW_NAME + "..update");
}
}
示例来自 github,为简洁起见进行了编辑。
我猜 spring-data-rest 是基于 Spring Data PersistentEntity 构建的,直接应用验证(针对来自模型对象的验证信息)可能并不容易。
您可能需要执行以下操作才能使请求验证工作:
@配置 公共类 BeanValidatorConfig {
@Bean
LocalValidatorFactoryBean localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
}
@组件 @RequiredArgsConstructor 公共类 CustomizedRepositoryRestConfiguration 实现 RepositoryRestConfigurer {
private final LocalValidatorFactoryBean validator;
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
v.addValidator("beforeCreate", validator);
v.addValidator("beforeSave", validator);
v.addValidator("beforeLinkSave", validator);
}
}