2015-03-07 6 views
9

मान लीजिए मैं इस तरह एक नमूना इकाई वर्ग है:वसंत MVC - देखने स्वचालित रूप से सत्यापनकर्ताओं

public class Address { 
    ... 
} 

और एक इसी सत्यापनकर्ता:

@Component 
public AddressValidator implements Validator { 

    @Override 
    public boolean supports(Class<?> entityClass) { 
     return entityClass.equals(Address.class); 
    } 

    @Override 
    public void validate(Object obj, Errors errors) { 
     ... 
    } 
} 

जब मैं निम्नलिखित की तरह एक नियंत्रक का उपयोग, सब कुछ काम करता है:

@RestController 
@RequestMapping("/addresses") 
public class AddressController { 

    @Autowired 
    private AddressValidator validator; 

    @InitBinder 
    protected void initBinder(WebDataBinder binder) { 
     binder.setValidator(validator); 
    } 

    @RequestMapping(method=POST) 
    public Long addNewAddress(@Valid @RequestBody Address address) { 
     ... 
    } 
} 

हालांकि, अगर मैं सत्यापनकर्ता पंजीकरण के भाग को छोड़ देते हैं (यानी के बाद), मान्यता नहीं है टी प्रदर्शन किया।

@Autowired 
private AddressValidator validator; 

@InitBinder 
protected void initBinder(WebDataBinder binder) { 
    binder.setValidator(validator); 
} 

वैधकर्ताओं को पंजीकृत करने के लिए मैन्युअल रूप से व्यर्थ लगता है। क्या मैं स्प्रिंग को स्वचालित रूप से सत्यापनकर्ताओं को देखने के लिए निर्देश दे सकता हूं (नियंत्रकों को कैसे देखा जाता है)?

यह एक वसंत बूट आधारित अनुप्रयोग है।

+0

आप स्वचालित रूप से वसंत प्रमाणीकरण फ्रेमवर्क के लिए 'Validator' संदर्भ सेम डालने का एक तरीका के लिए पूछ रहे हैं? – chrylis

+0

जब मैं एक @ वैलिड एनोटेशन के साथ पता पता जैसे बीन को चिह्नित करता हूं, तो मैं स्प्रिंग को वैलिडेटर इंटरफेस को लागू करने वाले बीन्स के बीच स्वचालित सत्यापनकर्ता को स्वचालित रूप से देखना चाहता हूं। क्या वसंत में ऐसी कार्यक्षमता है? लागू करने के लिए आसान लगता है। इस तरह मुझे initBinder विधि में मैन्युअल रूप से उचित सत्यापनकर्ता सेट करने की आवश्यकता नहीं होगी। –

+0

यह स्प्रिंग 'वैलिडेटर 'इंटरफेस है और' javax.validator.Validator' नहीं है? क्या कोई कारण है कि आप एक कस्टम JSR-303 सत्यापनकर्ता का उपयोग नहीं कर रहे हैं, शायद एक कस्टम '@ ValidAddress' एनोटेशन के साथ? – chrylis

उत्तर

1

आप वैश्विक सत्यापनकर्ता को कॉन्फ़िगर कर सकते हैं।

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#validation-mvc

आप WebMvcConfigurationSupport साथ जावा आधारित वसंत विन्यास का उपयोग कर रहे हैं, तो आप getValidator ओवरराइड कर सकते हैं()

/** 
* Override this method to provide a custom {@link Validator}. 
*/ 
protected Validator getValidator() { 
    return null; 
} 

आप वैश्विक WebBindingInitializer पर setValidator (सत्यापनकर्ता) कह सकते हैं। यह आपको सभी @ नियंत्रक कक्षाओं में एक वैलिडेटर उदाहरण कॉन्फ़िगर करने की अनुमति देता है। यह वसंत MVC नाम स्थान का उपयोग करके आसानी से प्राप्त किया जा सकता है:

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

    <mvc:annotation-driven validator="globalValidator"/> 

</beans> 
+2

आप केवल एक वैश्विक सत्यापनकर्ता को पंजीकृत कर सकते हैं? आप वसंत को एकाधिक मान्यताओं को लोड करने के लिए कैसे कहेंगे और पैरामीटर को @ वैलिड के साथ चिह्नित करते समय सही कार्यान्वयन का चयन कैसे करेंगे? – Blacktiger

0

मैं इस के लिए स्प्रिंग समाधान में निर्माण नहीं मिला है, लेकिन यहाँ मैं क्या कर रहा है। इसलिए जैसे एक आधार नियंत्रक

@Bean 
public Validator studentValidator(){ 
    return new StudentValidator(); 
} 

@Bean 
public Validator carValidator(){ 
    return new CarValidator(); 
} 

तब मैं सभी नियंत्रकों है लागू होता है::

मैं तो जैसे वसंत जावा विन्यास में मेरी सत्यापनकर्ता सेम की घोषणा

public abstract class BaseController <T> { 
    public BaseController(List<Validator> validators) { 
     super(); 
     this.validators = validators; 
     } 
    //Register all validators 
    @InitBinder 
    protected void initBinder(WebDataBinder binder) { 
    validators.stream().forEach(v->binder.addValidators(v)); 
    } 


} 

इस नियंत्रक के ठोस वर्ग हो जाता है सूची निर्भरता इंजेक्शन के माध्यम से इंजेक्शन, इसलिए जैसे:

@Controller 
public class StudentController extends BaseController<Student>{ 

    @Inject 
     public StudentController(List<Validator> validators) { 
     super(validators); 
     } 

} 

बस ई नियंत्रक सभी मान्यताओं को पंजीकृत करने के लिए @InitBinder कॉल-बैक विधि का उपयोग करता है।

मुझे आश्चर्य है कि वसंत स्वचालित रूप से वर्ग पथ में सभी वस्तुओं है कि सत्यापनकर्ता इंटरफ़ेस को लागू पंजीकृत नहीं करता हूँ।

2

आप gist या उससे नीचे के उदाहरण का उपयोग कर सकते हैं। विचार मुख्य कंपोजिट वैलिडेटेटर होना है जो आपके सभी वैलिडेटर या स्मार्टवैलिएटर उदाहरणों का धारक होगा।

यह संकेतों का समर्थन करता है और हाइबरनेट एनोटेशन वैलिडेटेटर (स्थानीय वैलिडेटेटर फैक्ट्रीबीन) के साथ एकीकृत भी किया जा सकता है। और यह भी संभव है कि प्रति विशिष्ट मॉडल एक वैधकर्ता हो।


CompositeValidator.java

@Component 
public class CompositeValidator implements SmartValidator { 
    @Autowired 
    private List<Validator> validators = Collections.emptyList(); 

    @PostConstruct 
    public void init() { 
     Collections.sort(validators, AnnotationAwareOrderComparator.INSTANCE); 
    } 

    @Override 
    public boolean supports(Class<?> clazz) { 
     for (Validator validator : validators) { 
      if (validator.supports(clazz)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     validate(target, errors, javax.validation.groups.Default.class); 
    } 

    @Override 
    public void validate(Object target, Errors errors, Object... validationHints) { 
     Class<?> clazz = target.getClass(); 

     for (Validator validator : validators) { 
      if (validator.supports(clazz)) { 
       if (validator instanceof SmartValidator) { 
        ((SmartValidator) validator).validate(target, errors, validationHints); 
       } else { 
        validator.validate(target, errors); 
       } 
      } 
     } 
    } 
} 

SomeController.java

@Controller 
@RequestMapping("/my/resources") 
public class SomeController { 

    @RequestMapping(method = RequestMethod.POST) 
    public Object save(
      @Validated(javax.validation.groups.Default.class) // this interface descriptor (class) is used by default 
      @RequestBody MyResource myResource 
    ) { return null; } 
} 

जावा कॉन्फ़िग

@Configuration 
    public class WebConfig { 
     /** used for Annotation based validation, it can be created by spring automaticaly and you don't do it manualy */ 
     // @Bean 
     // public Validator jsr303Validator() { 
     // LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); 
     // // validator.setValidationMessageSource(...); 
     // return validator; 
     // } 

     @Bean 
     public WebMvcConfigurerAdapter webMvcConfigurerAdapter() { 
      return new WebMvcConfigurerAdapter() { 
       @Autowired 
       private CompositeValidator validator; 

       @Override 
       public Validator getValidator() { 
        return validator; 
       } 
      } 
     } 

या एक्सएमएल कॉन्फ़िग

<!-- used for Annotation based validation, it can be created by spring automaticaly and you don't do it manualy --> 
<!--<bean id="jsr303Validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">--> 
<!-- <property name="validationMessageSource" ref="messageSource"/>--> 
<!--</bean>--> 

<mvc:annotation-driven validator="compositeValidator"> 
    //... 
</mvc:annotation-driven> 
संबंधित मुद्दे