Spring 启动 - 表单上的自定义验证注释不起作用
Spring Boot - Custom validation annotation on form not working
我想要一个注释来验证 MultipartFile
是一个图像。我创建了一个 @interface
和一个 ConstraintValidator
,并将注释添加到我的字段中。
其他验证注释,如 @NotEmpty
和 @Size(min = 0, max = 2)
工作正常。
这里是代码的总结。 This question有同样的问题,但答案对我不起作用。
Form.java:
@Validated
public class Form {
@MultipartImage
private MultipartFile image;
...
}
@Interface MultipartImage
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import validation.MultipartFileImageConstraintValidator;
@Documented
@Constraint(validatedBy = { MultipartFileImageConstraintValidator.class })
@Target({ LOCAL_VARIABLE, FIELD, METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MultipartImage {
String message() default "{MultipartImage.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
验证者,MultipartFileConstraintValidator.java
import java.io.IOException;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.web.multipart.MultipartFile;
public class MultipartFileConstraintValidator implements ConstraintValidator<MultipartImage, MultipartFile> {
@Override
public void initialize(final MultipartImage constraintAnnotation) {
}
@Override
public boolean isValid(final MultipartFile file, final ConstraintValidatorContext context) {
return false;
}
这是控制器中的表单提交方法
@RequestMapping(value = "/formsubmit", method = RequestMethod.POST)
public ModelAndView handleForm(@Validated final Form form,
final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
...
// returns the model
}
}
验证器在@Configuration 文件中设置,参见
@Configuration
@ConfigurationProperties("static")
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class StaticResourceConfig extends WebMvcConfigurerAdapter {
...
@Bean(name = "validator")
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
final MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
@Override
public Validator getValidator() {
return validator();
}
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
// Load files containing message keys.
// Order matters. The first files override later files.
messageSource.setBasenames(//
// load messages and ValidationMessages from a folder relative to the jar
"file:locale/messages", //
"file:locale/ValidationMessages", //
// load from within the jar
"classpath:locale/messages", //
"classpath:locale/ValidationMessages" //
);
messageSource.getBasenameSet();
messageSource.setCacheSeconds(10); // reload messages every 10 seconds
return messageSource;
}
}
我的原始代码中缺少信息,特别是关于控制器的信息,其中定义和绑定了一个额外的验证器。它使用了错误的方法来包含验证器 FormValidator
,并覆盖了注释验证。
binder.setValidator(formValidator)
覆盖任何其他验证器。相反,应该使用 binder.addValidators(formValidator)
!
@Controller
public class FormController {
@Autowired
final private FormValidator formValidator;
@InitBinder("form")
protected void initBinder(WebDataBinder binder) {
// correct
binder.addValidators(formValidator);
// wrong
//binder.setValidator(formValidator);
}
...
@RequestMapping(value = "/formsubmit", method = RequestMethod.POST)
public ModelAndView handleForm(@Validated final Form form, final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
...
// returns the model
}
...
}
}
我还删除了 @Configuration
class 中的 Bean MethodValidationPostProcessor
。
我想要一个注释来验证 MultipartFile
是一个图像。我创建了一个 @interface
和一个 ConstraintValidator
,并将注释添加到我的字段中。
其他验证注释,如 @NotEmpty
和 @Size(min = 0, max = 2)
工作正常。
这里是代码的总结。 This question有同样的问题,但答案对我不起作用。
Form.java:
@Validated
public class Form {
@MultipartImage
private MultipartFile image;
...
}
@Interface MultipartImage
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import validation.MultipartFileImageConstraintValidator;
@Documented
@Constraint(validatedBy = { MultipartFileImageConstraintValidator.class })
@Target({ LOCAL_VARIABLE, FIELD, METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MultipartImage {
String message() default "{MultipartImage.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
验证者,MultipartFileConstraintValidator.java
import java.io.IOException;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.web.multipart.MultipartFile;
public class MultipartFileConstraintValidator implements ConstraintValidator<MultipartImage, MultipartFile> {
@Override
public void initialize(final MultipartImage constraintAnnotation) {
}
@Override
public boolean isValid(final MultipartFile file, final ConstraintValidatorContext context) {
return false;
}
这是控制器中的表单提交方法
@RequestMapping(value = "/formsubmit", method = RequestMethod.POST)
public ModelAndView handleForm(@Validated final Form form,
final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
...
// returns the model
}
}
验证器在@Configuration 文件中设置,参见
@Configuration
@ConfigurationProperties("static")
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class StaticResourceConfig extends WebMvcConfigurerAdapter {
...
@Bean(name = "validator")
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
final MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
@Override
public Validator getValidator() {
return validator();
}
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
// Load files containing message keys.
// Order matters. The first files override later files.
messageSource.setBasenames(//
// load messages and ValidationMessages from a folder relative to the jar
"file:locale/messages", //
"file:locale/ValidationMessages", //
// load from within the jar
"classpath:locale/messages", //
"classpath:locale/ValidationMessages" //
);
messageSource.getBasenameSet();
messageSource.setCacheSeconds(10); // reload messages every 10 seconds
return messageSource;
}
}
我的原始代码中缺少信息,特别是关于控制器的信息,其中定义和绑定了一个额外的验证器。它使用了错误的方法来包含验证器 FormValidator
,并覆盖了注释验证。
binder.setValidator(formValidator)
覆盖任何其他验证器。相反,应该使用 binder.addValidators(formValidator)
!
@Controller
public class FormController {
@Autowired
final private FormValidator formValidator;
@InitBinder("form")
protected void initBinder(WebDataBinder binder) {
// correct
binder.addValidators(formValidator);
// wrong
//binder.setValidator(formValidator);
}
...
@RequestMapping(value = "/formsubmit", method = RequestMethod.POST)
public ModelAndView handleForm(@Validated final Form form, final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
...
// returns the model
}
...
}
}
我还删除了 @Configuration
class 中的 Bean MethodValidationPostProcessor
。