2010-08-27 24 views
9

Ví dụ này hơi bị giả tạo; Tôi đã đơn giản hóa nó để loại bỏ các chi tiết không liên quan và tập trung vào vấn đề tôi đang gặp phải. Tôi có một validator trông như thế này:Tự động dịch vụ vào bộ xác thực

@Component 
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> { 

    @Autowired 
    UsernameService usernameService; 

    @Override 
    public void initialize(UniqueUsername uniqueUsername) { 
    } 

    @Override 
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { 
     return !usernameService.exists(s); 
    } 
} 

tôi gọi là validator từ bộ điều khiển của tôi như thế này:

@RequestMapping 
public void checkUsername(Model model, User user) { 
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
    Validator validator = factory.getValidator(); 

    Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username"); 
    model.addAttribute("error", constraintViolations.size() > 0); 
} 

Tuy nhiên, tôi tiếp tục nhận một ngoại lệ NullPointerException. Tôi đã thêm điểm ngắt trong trình xác thực của mình và thấy rằng usernameServicenull. Tại sao nó không nhận được autowired? Ban đầu tôi nghĩ rằng đó là vì tôi đã không chú thích trình xác nhận với @Component, nhưng tôi vẫn có cùng một vấn đề ngay cả sau khi chú thích nó. Lớp UsernameService đã được chú thích với @Service và tôi có thể xác minh rằng hàm tạo của nó đang được gọi.

Tôi mới làm quen với Spring, vì vậy tôi thậm chí không chắc chắn có thể kết nối dịch vụ vào trình xác thực hay không. Tôi đang làm gì sai?

Trả lời

11

Vào mùa xuân, bạn cần tự lấy ValidatorFactory (hoặc Validator) qua LocalValidatorFactoryBean thay vì Validation.buildDefaultValidatorFactory(), như được mô tả in the reference.

@Autowired 
Validator validator; 

@RequestMapping 
public void checkUsername(Model model, User user) { 
    Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username"); 
    model.addAttribute("error", constraintViolations.size() > 0); 
} 

-

<bean id="validator" 
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 

EDIT: Nhưng có lẽ cách tốt hơn để làm điều đó là sử dụng xác nhận tự động Spring MVC với @Valid chú thích:

@RequestMapping 
public void checkUsername(Model model, @Valid User user, BindingResult result) { 
    if (result.hasErrors()) { 
     ... 
    } 
} 

này cũng đòi hỏi <mvc:annotation-driven/> trong cấu hình.

+0

Cảm ơn bạn! Đó chính xác là những gì tôi đang tìm kiếm. Tôi đã đi qua tài liệu tham khảo nhưng tôi đã tìm kiếm những thứ như "dịch vụ autowiring thành ràng buộc". Cảm ơn một lần nữa! –

+0

Tôi thích chỉnh sửa với @Valid. Chúc các bạn có thể upvote nhiều hơn một lần :) –

+0

Cảm ơn rất nhiều, câu trả lời của bạn đã giúp tôi tiết kiệm thời gian! –

0

Thay vì tạo trình xác thực mới, bạn phải tự động hoặc đưa nó vào bộ điều khiển. NPE từ dịch vụ không được tiêm vì trình xác thực của bạn không được tạo/quản lý vào mùa xuân.

+0

Nếu tôi tự động xác thực trình xác thực trực tiếp, tôi cần 'ConstraintValidatorContext' để gọi' isValid'. Làm thế nào để có được điều đó? Nó cũng có vẻ hơi kludgey với tôi. Có cách nào tốt hơn để làm những gì tôi đang cố gắng làm không? –

Các vấn đề liên quan