【问题标题】:Spring Boot - Custom validation annotation on form not workingSpring Boot - 表单上的自定义验证注释不起作用
【发布时间】:2016-12-07 14:57:19
【问题描述】:

我想要一个注释来验证 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 文件中设置验证器,见https://stackoverflow.com/a/21965098/4161471

@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;
}

}

【问题讨论】:

  • 糟糕,我点击提交太早了。我会尽快添加更多信息。
  • MultipartFileConstraintValidator 应该实现 ConstraintValidatorForm 类中是否存在其他约束,例如 @Size,或者您在另一个类中验证了它们?
  • @DanielOlszewski 这是一个错误,现已更正。其他约束在同一个 Form 类中起作用
  • 好吧,从头开始。其他约束,例如 @NotEmpty,不适用于同一个 Form 对象中的其他字段。
  • 您手动创建所有这些与验证器相关的 bean 并且不依赖默认配置有什么特别的原因吗?

标签: java validation spring-boot hibernate-annotations


【解决方案1】:

我的原始代码中缺少信息,特别是关于控制器的信息,其中定义和绑定了一个额外的验证器。它使用错误的方法来包含验证器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 类中的 Bean MethodValidationPostProcessor

【讨论】:

    猜你喜欢
    • 2017-04-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 2013-05-18
    相关资源
    最近更新 更多