2012-04-04 19 views
5

फ्रीमार्कर का उपयोग कर नवीनतम वसंत एमवीसी।वसंत एमवीसी फॉर्म को सत्यापित करने के तरीके के रूप में उलझन में, मेरे विकल्प क्या हैं?

किसी को उम्मीद है कि कोई मुझे बता सकता है कि मेरे विकल्प वसंत एमवीसी के साथ एक फॉर्म को मान्य करने के मामले में क्या हैं, और यह करने का सुझाव क्या होगा।

मेरे पास एक ऐसा फॉर्म है जो सीधे मॉडल पर मैप नहीं करता है, इसमें इनपुट फ़ील्ड्स हैं जो पोस्ट किए जाने पर 2 मॉडल ऑब्जेक्ट्स को प्रारंभ करने के लिए उपयोग किए जाएंगे जिन्हें मुझे सत्यापित करने की आवश्यकता होगी, और यदि वे पास करेंगे तो मैं उन्हें सहेज दूंगा ।

यदि वे असफल होते हैं, तो मैं फॉर्म पर वापस लौटना चाहता हूं, उपयोगकर्ता द्वारा दर्ज किए गए मानों को पूर्व-भरना और त्रुटि संदेशों को प्रदर्शित करना चाहता हूं।

मैं यहाँ पढ़ लिया है और वहाँ के बारे में 2 तरीकों, जिनमें से एक बार मैंने किया है और समझते हैं कि यह कैसे काम करता है:

@RequestMapping(...., method = RequestMethod.POST) 
public ModelAndView myMethod(@Valid MyModel, BindingResult bindingResult) { 
    ModelAndView mav = new ModelAndView("some/view"); 
    mav.addObject("mymodel", myModel); 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

} 

अब इस काम अगर मेरे फ़ॉर्म को सीधे मैप किया गया, लेकिन मेरी स्थिति में मैं है:

  1. प्रपत्र फ़ील्ड्स है कि किसी भी विशिष्ट मॉडल पर मैप नहीं करते हैं, वे 2 मॉडल से कुछ गुण होते हैं।

  2. से पहले सत्यापन occurrs, मैं मैन्युअल रूप से 2 मॉडल बनाने के लिए, फार्म से मूल्यों को निर्धारित की जरूरत है, और मैन्युअल रूप से भी कुछ गुण सेट:

    दोनों मॉडल (MODEL1, MODEL2) पर
  3. कॉल सत्यापित करें, और संलग्न इन त्रुटि संदेशों को त्रुटियों के संग्रह में जो मुझे एक ही दृश्य पृष्ठ पर वापस जाने की आवश्यकता है यदि चीजें काम नहीं करती हैं।

  4. जब फॉर्म पोस्ट करते हैं, तो मुझे कुछ डेटाबेस कॉल करना पड़ता है, और उन परिणामों के आधार पर त्रुटियों के संग्रह में अतिरिक्त संदेश जोड़ने की आवश्यकता हो सकती है।

क्या कोई मुझे बता सकता है कि इस तरह के सत्यापन कैसे करें?

छद्म नीचे कोड:

Model1 model1 = new Model1(); 
    Model2 model2 = new Model2(); 

    // manually or somehow automatically set the posted form values to model1 and model2. 

    // set some fields manually, not from posted form 
    model1.setProperty10(GlobalSettings.getDefaultProperty10()); 
    model2.setProperty11(GlobalSettings.getDefaultProperty11()); 

    // db calls, if they fail, add to errors collection 

    if(bindingResult.hasErrors()) { 
    return mav; 
    } 

    // validation passed, save 
    Model1Service.save(model1); 
    Model2Service.save(model2); 

    redirect to another view 

अद्यतन

मैं अपने मॉडल पर JSR 303 एनोटेशन का उपयोग किया है अभी, और यह बहुत अच्छा है कि अगर मैं अभी भी उन का उपयोग कर सकते हैं।

अद्यतन द्वितीय

कृपया मैं के लिए क्या देख रहा हूँ की एक सारांश के लिए नीचे इनाम विवरण पढ़ें।

उत्तर

8

इसी तरह के अनुभव के आधार पर, मैं निम्नलिखित प्रस्तावों का प्रस्ताव दूंगा और मेरे पास जिस दृष्टिकोण को आप लेना चाहते हैं उस पर अंतिम चरण पर एक टिप्पणी है। मैं चरणों की आपकी क्रमांकित सूची का उपयोग करता हूं।

चरण 1: फार्म बीन

इस के लिए दो तरीके हैं।

class MyModel { 
    private Model1 model1; 
    private Model2 model2; 
    // standard Java bean stuff 
} 

एक और अधिक सटीक तरीका वास्तव में MyModel परिभाषित करने के लिए है ऐसा है कि मैं केवल फ़ील्ड Model1 और Model2 लेकिन से की आवश्यकता है उधार लेता है: सरल दृष्टिकोण (मुझे लगता है कि आप पहले से ही किया है) एक रूप सेम परिभाषित करने के लिए है मुझे यकीन नहीं है कि यह आपके रास्ते से फिट बैठता है।

चरण 2: डेटा बाइंडिंग

वसंत आप के लिए यह करता है अगर आप अपने ध्यान में रखते हुए इस तरह के form संरचना है:

<form:form modelAttribute="myModel"> 
    <form:input path="model1.somePropertyToBeSet" /> 
</form:form> 

चरण 3: मान्यता

Spring custom validations का उपयोग करके, आप ग्राहक को परिभाषित कर सकते हैं ओम की कमी:

कस्टम की कमी के लिए अपने कस्टम प्रमाणकों
@interface Model1Constraint {} 
@interface Model2Constraint {} 

class MyModel1 { 

    @Model1Constraint 
    private Model1 model1; 

    @Model2Constraint 
    private Model2 model2; 

    // ... 

} 

तो रजिस्टर:

class Model1ConstraintValidator implements ConstraintValidator<Model1Constraint, Model1> { 
// implementation of isValid and initalize 
} 

और Model2Constraint के लिए एक ही। कस्टम सत्यापनकर्ताओं का उपयोग करके, आप यह जांच सकते हैं कि MyModel अनुरोध प्रक्रिया विधि में पारित होने से पहले आपको यह सुनिश्चित करने के लिए आवश्यक तर्क क्या है। मैं यह भी मानता हूं कि आपने <mvc:annotation-driven /> का उपयोग स्प्रिंग रजिस्टर करने वालों के लिए किया है; अन्यथा, आपको उन्हें कॉन्फ़िगर करना चाहिए।

चरण 4: कस्टम मॉडल प्रसंस्करण अनुरोध प्रसंस्करण से पहले

आपका मूल विचार इस काम के लिए कुछ डेटा बांधने की मशीन उपयोग करने के लिए है। आपके विवरण में, आप यह भी उल्लेख करते हैं कि यह डेटा प्रोसेसिंग फ़ॉर्म डेटा से आने वाले डेटा पर निर्भर नहीं है।

डिज़ाइन और मॉड्यूलरिटी के संबंध में, मुझे विश्वास नहीं है कि डेटा बाइंडर इस उद्देश्य के लिए एक अच्छी जगह है। दूसरा, क्योंकि फॉर्म के लिए कोई डेटा निर्भरता नहीं है, इसलिए आपके लिए मुख्य कारण डेटा बाध्यकारी त्रुटि प्रसंस्करण की अनुमति देना है।

तो, मेरा सुझाव यह है कि मान लें कि अब आप public ModelAndView myMethod(@Valid MyModel model, BindingResult bindingResult) में हैं। संभवतः, आपके पास अन्य सेवा बीन्स तक पहुंच है। तो, आपके पास कुछ सेवा बीन में एक विधि हो सकती है जो refine या prepare (केवल नाम) model कर सकती है जिसे आपने इस बिंदु में पॉप्युलेट किया है। अपवाद या आपके अनुरूप उपयुक्त किसी भी अन्य तंत्र के आधार पर, आप त्रुटियों को फिर से वापस करने के लिए bindingResult का उपयोग कर सकते हैं।

एक और सुझाव के रूप में, यदि आप इसे करने के लिए अधिक DI/IoC तरीका चाहते हैं तो आप Spring interceptors का लाभ भी ले सकते हैं। लेकिन इस तरह, आपको MyModelModelAndView से अवरोध में निकालना चाहिए और आगे बढ़ना चाहिए।

मुझे उम्मीद है कि इससे मदद मिलती है।

0

हाइबरनेट वैलिडेटर 4.2 विधि स्तर सत्यापन का समर्थन करता है। आप विधि में दो मॉडलों को पारित करने के लिए अपने कोड को थोड़ा सा कर सकते हैं, और उन्हें सत्यापित कर सकते हैं।

http://java.dzone.com/articles/method-validation-spring-31

आप के रूप में यह आमतौर पर उपयोगकर्ता इनपुट को मान्य करने के सबसे समझ में आता है यह एक असामान्य समस्या है इस

public void persistUser(@NotNull @Valid Model1 model1, @NotNull @Valid Model2 model2) { 

     //continue ... 
} 
0

की तरह कुछ हो सकता है, के रूप में है कि डेटा है हम नहीं कर सकते नियंत्रण। इसके साथ कहा जा रहा है, और चूंकि मुझे यकीन है कि आप पहले से ही जानते थे ...

एक विकल्प जेएसआर 303 सत्यापन एपीआई का उपयोग सीधे आपके मॉडल ऑब्जेक्ट्स को सत्यापित करने के लिए होगा ताकि वे उपयोगकर्ता इनपुट, डेटाबेस से पॉप्युलेट हो जाएं

@RequestMapping(value=...) 
public String myMethod(MyForm form, Model m) { 

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
    Validator validator = factory.getValidator(); 

    Model1 model1 = createModel1FromUserInput(form); 
    Model2 model2 = createModel2FromUserInput(form); 

    Set<ConstraintViolation<?>> modelViolations = validator.validate(model1); 
    modelViolations.add(validator.validate(model2)); 
    if(modelViolations.size() != 0) { 
     m.addAttribute("violations", modelViolations); 
     m.addAttribute("form", myForm); // add the form back to the model so it is populated 
     return "formPage"; 
    } 
    return "successPage"; 
} 

आप एक स्प्रिंग BindingResult या त्रुटियों का संग्रह करने के लिए बाध्य करने के लिए पसंद कर सकते हैं:, आदि ..

यहाँ एक उदाहरण है। मैं निम्नलिखित कोड का परीक्षण किया है नहीं, और BindingResult के साथ सीधे काम कर बहुत आराम नहीं कर रहा हूँ, तो यह सुधार करने की आवश्यकता होगी:

BindingResult result = ... // not sure about the constructor 
for(ConstraintViolation<?> violation : modelViolations) { 
     result.addError(new ObjectError(violation.getPropertyPath().toString(),violation.getMessage())); 
} 

तुम सिर्फ फिर एक Set<ConstraintViolation> का उपयोग कर, JSP पर त्रुटियों थूक से बाहर करने की कोशिश कर रहे हैं, तो अपनी आवश्यकताओं के लिए काफी अच्छी तरह से काम कर सकते हैं:

<c:forEach items="${violations}" var="violation"> 
    ${violation.propertyPath}: ${violation.message} <br/> 
</c:forEach> 

आप वसंत के <form:errors> टैग का उपयोग करने की कोशिश कर रहे हैं, तो आप बाध्यकारी परिणाम का उपयोग करना होगा।

एचटीएच! यदि आपको और प्रश्न पूछने हों तो मुझे बता दें। या अगर मैं इस जवाब पर पूरी तरह से निशान चूक गया, तो मैं स्पष्टीकरण देने की कोशिश करूंगा।