java - 使用名称创建 bean 时出错。结合 bean 验证和基于 Spring 的验证

标签 java spring validation spring-mvc

我想结合bean验证和Spring验证(基于《Spring MVC初学者指南》一书),但有错误: 我的日志:

2017-03-04 19:09:54 ERROR DispatcherServlet:502 - Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productValidator'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productValidator': Unsatisfied dependency expressed through field 'beanValidator'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.validation.Validator' available: expected single matching bean but found 2: org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean#0,validator
    at [...]

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productValidator': Unsatisfied dependency expressed through field 'beanValidator'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.validation.Validator' available: expected single matching bean but found 2: org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean#0,validator
    at [...]

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.validation.Validator' available: expected single matching bean but found 2: org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean#0,validator
    at [...]

我的 Controller :

@Controller()
@RequestMapping("/products")
public class ProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductValidator productValidator;
[...]
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String processAddNewProductForm(@Valid @ModelAttribute("newProduct") Product productToBeAdded, BindingResult result,
                                           HttpServletRequest httpServletRequest){
        if(result.hasErrors())
            return "addProduct";

        String[] suppressedFields = result.getSuppressedFields();
        if(suppressedFields.length > 0){
            throw new RuntimeException("abc" + StringUtils.arrayToCommaDelimitedString(suppressedFields));
        }

        MultipartFile productImage = productToBeAdded.getProductImage();

        String rootDirectory = httpServletRequest.getSession().getServletContext().getRealPath("/");
        if(productImage != null && !productImage.isEmpty()){
            try {
                productImage.transferTo(new File(rootDirectory + "resources\\images\\" +
                                                    productToBeAdded.getProductId() + ".png"));
            } catch (IOException e) {
                throw new RuntimeException("abcd", e);
            }
        }

        productService.addProduct(productToBeAdded);
        return "redirect:/products";
    }

    @InitBinder
    public void initialiseBinder(WebDataBinder binder){
        binder.setValidator(productValidator);
    }
[...]
}

我的类(class)验证

@Component
public class ProductValidator implements Validator {
    @Autowired
    private javax.validation.Validator beanValidator;

    private Set<Validator> springValidators;

    public ProductValidator() {
        this.springValidators = new HashSet<>();
    }

    public void setSpringValidators(Set<Validator> springValidators) {
        this.springValidators = springValidators;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return Product.class.isAssignableFrom(aClass);
    }

    @Override
    public void validate(Object target, Errors errors) {
        Set<ConstraintViolation<Object>> constraintViolations = beanValidator.validate(target);
        for(ConstraintViolation<Object> constraintViolation: constraintViolations){
            String propertyPath = constraintViolation.getPropertyPath().toString();
            String message = constraintViolation.getMessage();
            errors.rejectValue(propertyPath, "", message);
        }
        for(Validator validator: springValidators){
            validator.validate(target, errors);
        }
    }
}

我的 DispatcherServlet 上下文

<?xml version="1.0" encoding="UTF-8"?>
[...]

    <mvc:annotation-driven enable-matrix-variables="true"/>
    <mvc:resources mapping="/resource/**" location="/resources/" />
    <mvc:annotation-driven enable-matrix-variables="true" validator="validator"/>

    <context:component-scan base-package="com.packt.webstore" />

[...]

    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <property name="defaultLocale" value="pl" />
    </bean>

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>

    <bean id="productValidator" class="com.packt.webstore.validator.ProductValidator">
        <property name = "springValidators">
            <set>
                <ref bean = "unitsInStockValidator"/>
            </set>
        </property>
    </bean>

    <bean id="unitsInStockValidator" class="com.packt.webstore.validator.UnitsInStockValidator"/>
</beans>

最初没有注解@Component,我添加了它,但没有任何变化

最佳答案

您收到的错误是 b/c spring 无法确定要注入(inject)到 ProductValidator 中的 validator bean,只需在 bean 配置文件中将其标记为主要的,以便 Spring 知道要使用哪一个。

 <bean id="validator" primary="true" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="validationMessageSource" ref="messageSource"/>
 </bean>

关于java - 使用名称创建 bean 时出错。结合 bean 验证和基于 Spring 的验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42599917/

相关文章:

java - 发送邮件在 Spring/Maven/Java 6 环境中不起作用

java - 在 jtextfield 中验证 'price' 的正则表达式是什么

java - @RequestParam 验证

ruby-on-rails - 验证多列的唯一性

java - JVM CMS 垃圾收集问题

java - "The requested resource does not support http method ' GET '"- 但我 'm not using C# or asp.net, I' 是发出请求的人

java - Java 8 重载可以区分函数参数参数类型吗?

java - Spring jms - 重命名 DLQ

java - java 对象的通用导出到 Excel

android - 在android中获取mp3持续时间