简体   繁体   English

如何在ConstraintValidator中自动装配服务

[英]How to autowire service in ConstraintValidator

I'm writting my application using Spring MVC. 我正在使用Spring MVC编写我的应用程序。 I want to validate is e-mail exists in database when user is registering. 我想验证用户注册时数据库中是否存在电子邮件。 I've written my own annotation constraint named UniqueEmail . 我编写了自己的注释约束,名为UniqueEmail

My User entity User.java : 我的用户实体User.java

@Entity
@Table(name="users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "email", length = 100, nullable = false, unique = true)
    @NotEmpty
    @Email
    @UniqueEmail(message = "E-mail is not unique")
    private String email;

    @Column(name = "password", nullable = false)
    @NotEmpty
    @Size(min = 5, message = "size must be more 5")
    private String password;
}

My annotation constraint UniqueEmail.java : 我的注释约束UniqueEmail.java

@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueEmailValidator.class)
@Documented
public @interface UniqueEmail {
    String message() default "Email is exist";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

My validator UniqueEmailValidator.java : 我的验证器UniqueEmailValidator.java

@Component
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {

    @Autowired
    private UserService userService;

    @Override
    public void initialize(UniqueEmail uniqueEmail) {
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        try {
            return userService.isExistEmail(s);
        } catch (Exception e) {
            System.out.println(e);
            return false;
        }
    }
}

This code works in application. 此代码适用于应用程序。

When I run my test code its return NullPointerException. 当我运行我的测试代码时,它返回NullPointerException。 In my validation class userService is null. 在我的验证类中, userService为null。

I've read http://docs.spring.io/spring/docs/3.0.0.RC3/reference/html/ch05s07.html but cannot any solution. 我已阅读http://docs.spring.io/spring/docs/3.0.0.RC3/reference/html/ch05s07.html无法解决任何问题。

Any idea? 任何的想法?

Update 更新

I use JUnit. 我使用JUnit。 UserClassTest.java UserClassTest.java

@ContextConfiguration("file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml")
public class UserClass {

    private static Validator validator;

    @BeforeClass
    public static void setup() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

    @Test
    public void emailIsUnique() {

        User user = new User();
        user.setEmail("mail@example.com"); // I've written exist email in DB.

        Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "email");

        assertEquals(1, constraintViolations.size());
        assertEquals("E-mail is not unique", constraintViolations.iterator().next().getMessage());
    }
}

Update 更新

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<context:component-scan base-package="ru.yadoka"/>

<import resource="db/db-config.xml"/>

<!-- Apache tiles -->
<bean id="tilesConfigurer"
      class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/tiles.xml</value>
        </list>
    </property>
</bean>

<bean id="viewResolver"
      class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
</bean>

<!-- Mapping resources from theme -->
<mvc:resources mapping="/css/**" location="/resources/css/"/>
<mvc:resources mapping="/js/**" location="/resources/js/"/>
<mvc:resources mapping="/fonts/**" location="/resources/
<mvc:annotation-driven/>

Don't you have a Validator configured in your bean context. 您是否在bean上下文中配置了Validator。 If you are bootstrapping Validator via Validation.buildDefaultValidatorFactory(); 如果您通过Validation.buildDefaultValidatorFactory()引导Validator ; you are bypassing the Spring mechanism and you get a Validator which is not aware of Spring beans and components. 你绕过Spring机制,你得到一个不知道Spring bean和组件的Validator。 Hence injection is not working. 因此注射不起作用。 In your test you want to get hold of the Spring provided Validator. 在您的测试中,您希望获得Spring提供的Validator。

If your main code is working, then it should be straight forward to get your test working. 如果您的主要代码正常工作,那么应该直接进行测试。 You need to use @ContextConfiguration on your test class, see this for more details: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html 您需要在测试类上使用@ContextConfiguration,有关详细信息,请参阅此内容: http ://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html

In general, there are 2 ways to test this: 一般来说,有两种方法可以测试:

  • unit test 单元测试
  • integration test 整合测试

For unit test, you need to create an instance of the UniqueEmailValidator and set a UserService on that instance (normally a mock UserServer). 对于单元测试,您需要创建UniqueEmailValidator的实例并在该实例上设置UserService(通常是模拟UserServer)。

For integration test, you need to have the spring context initialized as I mentioned above. 对于集成测试,您需要如上所述初始化spring上下文。

You can call injection all @Autowired service: 您可以调用注射所有@Autowired服务:

@Override
public void initialize(UniqueEmail uniqueEmail) {
   org.springframework.web.context.support.SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM