Spring Boot - 表单上的自定义验证注释不起作用

时间:2016-12-07 14:57:19

标签: java validation spring-boot hibernate-annotations

我希望有一个注释来验证MultipartFile是图像。我创建了@interfaceConstraintValidator,并在我的字段中添加了注释。

其他验证注释,例如@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文件中设置Validator,请参阅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;
}

}

1 个答案:

答案 0 :(得分:0)

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

我还删除了MethodValidationPostProcessor类中的Bean @Configuration