该方案是,在保留Log
实体类之前,应检查其属性String description
是否至少包含在IllegalWord
实体类中找到的单词。这是两个实体类的映射:
// Log.java
@Entity
public class Log {
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Id
private Long id;
@NotContainingIllegalWords
private String description;
}
// IllegalWord.java
@Entity
public class IllegalWord {
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Id
private Long id;
private String word;
}
由于我将对select *
实体类执行IllegalWord
,因此我为其创建了一个存储库类:// IllegalWordRepository.java
@Repository
public interface IllegalWordRepository extends CrudRepository<IllegalWord, Long> {}
然后创建了ConstraintValidator
验证器类,该类将由NotContainingIllegalWords
批注使用,而该类又将用于注释String description
实体类的Log
字段:// NotContainingIllegalWordsValidator.java
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
private static final Logger log = LoggerFactory.getLogger(NotContainingIllegalWordsValidator.class);
@Autowired
private IllegalWordRepository illegalWordRepository;
public void initialize(NotContainingIllegalWords constraintAnnotation) {}
public boolean isValid(String value, ConstraintValidatorContext cxt) {
log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
// Returns "illegalWordRepository is null? true"
// It is not injected even with the @Autowired annotation.
boolean valid = true;
Collection<IllegalWord> illegalWords = illegalWordRepository.findAll();
// Encounters a NullPointerException here.
// valid = ...loop through illegalWords collection and match regex (or whatever optimal approach)
// with @param value to check if it contains the illegal word.
return valid;
}
我认为那样会很简单。但是语句illegalWordRepository.findAll()
引发错误,因为illegalWordRepository
变量为null。请注意,我在前面的语句中尝试检查它是否为null
。我以为我在存储库类中编码有误,因此我尝试在带注释的
@Autowired private IllegalWordRepository illegalWordRepository
的类中使用@Service
,并令人惊讶地将其正确地注入到其中(例如,不是null
):// IllegalWordService.java
@Service
public class IllegalWordService {
private static final Logger log = LoggerFactory.getLogger(IllegalWordService.class);
@Autowired
private IllegalWordRepository illegalWordRepository;
public IllegalWord generate(String word) {
log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
// Returns "illegalWordRepository is null? false"
IllegalWord illegalWord = new IllegalWord();
illegalWord.setWord(word);
illegalWordRepository.save(illegalWord);
// Didn't encounter a NullPointerException here.
return illegalWord;
}
}
因此,我猜IllegalWordRepository
存储库类没有什么不妥。只是它没有注入NotContainingIllegalWordsValidator
验证器类中,因为我希望它与@Autowired
注释一起使用(如果那是@Autowired
注释甚至旨在起作用的方式,对不起,我是Spring Framework中的新手。)如果有适当的方法可以在
ConstraintValidator
实例中执行@Entity查询,请告诉我。相关的未解答的SO问题:Inject Repository inside ConstraintValidator with Spring 4 and message interpolation configuration
尝试失败:
我试图用
NotContainingIllegalWordsValidator
注释对@Configurable
类进行注释,如下所示:@Configurable(autowire=Autowire.BY_NAME, preConstruction=true)
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
但是illegalWordRepository
属性仍然是null
。 最佳答案
由于您的验证器不是由Spring初始化的,因此您无法向其中注入任何内容。您必须通过静态变量访问ApplicationContext
。
@SpringBootApplication
public class MyApplication {
private static ApplicationContext applicationContext;
public static void main(final String[] args) {
applicationContext = SpringApplication.run(MyApplication.class, args);
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
在你的ConstraintValidator
中:public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
public boolean isValid(String value, ConstraintValidatorContext cxt) {
ApplicationContext applicationContext = MyApplication.getApplicationContext();
IllegalWordRepository illegalWordRepository = applicationContext.getBean(IllegalWordRepository.class);
...
}
}