2013-05-10 8 views
6

जावा स्प्रिंग एमवीसी वेब ऐप है, और मैं एक jquery AJAX पोस्ट अनुरोध कर रहा हूं। मेरा नियंत्रक जेसन डेटा प्राप्त करने और भेजने के लिए सेटअप है। सब कुछ काम करता है, जेएसओएन स्ट्रिंग अच्छी तरह से स्वरूपित है, और नियंत्रक कमांड ऑब्जेक्ट बना और बना सकता है और जेएसओएन अनुरोध डेटा की सामग्री के साथ इसे पॉप्युलेट कर सकता है। हालांकि, मैं एक संपर्क ऑब्जेक्ट के लिए डेटा अपडेट कर रहा हूं, और मेरे जेएसपी फॉर्म तत्व में केवल डीबी अपडेट के लिए आवश्यक सभी डेटा का एक सबसेट शामिल है। जेएसपी पेज के लिए मेरे शुरुआती जीईटी अनुरोध में फॉर्म के साथ मैं डीबी से सभी आवश्यक डेटा पुनर्प्राप्त करता हूं, एक संपर्क कमांड ऑब्जेक्ट को पॉप्युलेट करता हूं, और उसके बाद उस कमांड ऑब्जेक्ट को मॉडल पर बांधता हूं।वसंत 3 AJAX POST अनुरोध @RequestBody और @ModelAttribute और @SessionAttribute के साथ एक साथ उपयोग किया जाता है?

अगर मैं सामान्य पोस्ट सबमिट फॉर्म सबमिशन कर रहा था, तो मेरा मानना ​​है कि मेरी कमांड ऑब्जेक्ट को @ सत्र एट्रिब्यूट के रूप में घोषित करना है, और मेरे ऑनसमिट() POST विधि में @ModelAttribute का उपयोग करके कमांड ऑब्जेक्ट का संदर्भ देना पर्याप्त होगा। वसंत मेरे सत्र से पहले से ही आबादी वाले कमांड ऑब्जेक्ट को पुनर्प्राप्त करेगा और फिर उन अनुरोधों को बाध्य (ओवरराइट) करेगा जो POST अनुरोध के परिणामस्वरूप बदल गए हैं। यह अद्यतन कमांड ऑब्जेक्ट तब डीबी अपडेट के पैरामीटर के रूप में उपयोग किया जा सकता है।

हालांकि, मैं स्प्रिंग 3 का उपयोग कर रहा हूं और @RequestBody paramater प्रकार का लाभ उठा रहा हूं। मैं स्प्रिंग नहीं प्राप्त कर सकता हूं, दोनों मुझे सत्र ऑब्जेक्ट देते हैं और अनुरोध से नए मानों को स्वचालित रूप से बांधते हैं। यह या तो मुझे केवल पुराने सत्र कमांड ऑब्जेक्ट (परिवर्तनों को लागू किए बिना) या POST अनुरोध से केवल मानों के साथ एक नया कमांड ऑब्जेक्ट देता है।

यहाँ एक छोटे से कोड है - काम नहीं करता:

@SessionAttributes("contactCommand") 
@Controller 
public class ContactController { 


    @RequestMapping(value = "/editContact", method=RequestMethod.GET) 
public String init(ModelMap model, Locale locale, HttpServletRequest request, HttpServletResponse response) throws GeneralException { 
    final ContactCommand cmd = new ContactCommand(); 
    // populate with data from DB etc 
    model.addAttribute("contactCommand", cmd); 
    // etc 
} 

@RequestMapping(value="/editContact",method=RequestMethod.POST, consumes = "application/json", produces = "application/json") 
public @ResponseBody Map<String, ? extends Object> editContactInfo(@RequestBody @ModelAttribute("contactCommand") ContactCommand cmd, HttpServletRequest request, HttpServletResponse response) throws GeneralException { 

// do business logic with command object here 

} 

किसी को भी मुझे बता सकते हैं JSON अनुरोध डेटा के साथ @RequestBody उपयोग करने के लिए "मानक" या "सबसे आसान" तरीका है क्या और है कि बाँध बनाने किसी मौजूदा/@ModelAttribute को कमांड ऑब्जेक्ट को पॉप्युलेट किया गया ताकि कमांड ऑब्जेक्ट पूरी तरह पुराने और नए डेटा दोनों के साथ गठित हो (उसी तरह इसे पूर्ण पोस्ट http सबमिट करके आसानी से हासिल किया जा सके)।

संबंधित प्रश्न यह है कि उपर्युक्त कोड में क्या गलत है? क्या JSON सामग्री के साथ @ सत्र एट्रिब्यूट और @RequestBody सभी का एक साथ उपयोग किया जा सकता है? यदि हां, तो कृपया समझाएं कि कैसे! किसी भी इनपुट के लिए बहुत बहुत धन्यवाद।

मेरा काम आसपास स्प्रिंग को नई कमांड ऑब्जेक्ट बनाने और फॉर्म डेटा के साथ स्वत: पॉप्युलेट करने देना है। फिर पुरानी कमांड ऑब्जेक्ट सत्र से मैन्युअल रूप से एक अलग कॉल/पुनर्प्राप्त करें, आखिर में उन सभी विशेषताओं को मैन्युअल रूप से कॉपी करें जो नए कमांड ऑब्जेक्ट में फॉर्म सबमिशन में मौजूद नहीं थे। अब मेरे पास एक एसक्यूएल ऑब्जेक्ट में एक साथ सभी आवश्यक डेटा हैं जो मेरे एसक्यूएल अपडेट को लागू करने के लिए हैं। वहाँ एक आसान तरीका होना चाहिए ....;)

अद्यतन:

मिले इस SOF पद आज जबकि आगे इस समस्या पर शोध:

Spring Partial Update Object Data Binding

ऐसा प्रतीत होता है कोई ज्ञात वसंत समाधान है बॉक्स से बाहर लेकिन इसे संभालने का सबसे अच्छा तरीका जानने की बहुत मांग है। मेरे मामले में, हाँ, मैं नेस्टेड डोमेन ऑब्जेक्ट्स का उपयोग कर रहा हूं ताकि पोस्ट में दी गई वर्कअराउंड कोई अच्छा न हो। क्या किसी के पास कोई दूसरा विचार है? स्पष्ट होने के लिए, मैं नियंत्रक को JSON प्रारूप डेटा पोस्ट करना चाहता हूं (केवल http फॉर्म पोस्ट डेटा नहीं)।

ठीक है, मैं इस एक के लिए एक स्प्रिंग स्रोत JIRA अनुरोध खोल दिया है, शायद यह एक ज्यादा जरूरत सुधार है:

https://jira.springsource.org/browse/SPR-10552

वरना, उस में जैक्सन रूपांतरण क्षमताओं का लाभ का एक मामला है चालाक तरीके जो बहुत सारी नलसाजी की तरह लगता है।

उत्तर

0

आप @RequestBody के साथ मॉडल एट्रिब्यूट को एनोटेट करना क्यों चाहते हैं, बस @ सत्र एट्रिब्यूट होने और जेएसओएन के मामले में @ModelAttribute का उपयोग करके कमांड ऑब्जेक्ट पर्याप्त है।

@RequestBody

का उपयोग कर के पीछे अपने मकसद क्या है

देखें http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html और

http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/RequestBody.html

+0

आपके उत्तर के लिए धन्यवाद। सोचा कि जैक्सन द्वारा क्लासपाथ पर प्रदान किए गए रूपांतरण को ऑब्जेक्ट करने के लिए ऑटो जेसन का लाभ उठाने के लिए अनुरोधबॉडी का उपयोग करने के लिए मानक अभ्यास था। क्या आप मुझे किसी भी दस्तावेज पर इंगित कर सकते हैं जो कहता है कि मॉडल एट्रिब्यूट जेएसओएन को संभालने के लिए भी पर्याप्त है? मैंने एक और एसओएफ पोस्ट पर निम्नलिखित पढ़ा: "मॉडल एट्रिब्यूट फॉर्म पोस्ट पैरामीटर से बंधे हैं और RequestBody शरीर को सीधे जेसन कनवर्टर से पास करता है": http://stackoverflow.com/questions/13229584/requestbody-or-modelattribute-with-springrest -वेब सेवाएं – arcseldon

1

यह एक पूरा जवाब नहीं है, लेकिन मुझे आशा है कि यह सही दिशा में इंगित करेंगे।

निम्नलिखित एक वर्ग है जिसे हम जेएसओएन से जैक्सन का उपयोग करके मौजूदा ऑब्जेक्ट में गहरी बाध्यकारी करने के लिए उपयोग करते हैं। यह जैक्सन यहाँ एक बग रिपोर्ट से रूपांतरित किया जाता है: https://jira.springsource.org/browse/SPR-10552

public class JsonBinder 
{ 
    private ObjectMapper objectMapper; 

    public JsonBinder(ObjectMapper objectMapper) 
    { 
     super(); 
     this.objectMapper = checkNotNull(objectMapper); 
    } 

    public void bind(Object objToBindInto, InputStream jsonStream) throws JsonProcessingException, IOException 
    { 
     JsonNode root = objectMapper.readTree(checkNotNull(jsonStream)); 
     applyRecursively(checkNotNull(objToBindInto), root); 
    } 

    private void applyRecursively(Object objToBindInto, JsonNode node) throws JsonProcessingException, IOException 
    { 
     PropertyAccessor propAccessor = null; 

     for(Iterator<Entry<String, JsonNode>> i = node.fields(); i.hasNext();) 
     { 
      Entry<String, JsonNode> fieldEntry = i.next(); 
      JsonNode child = fieldEntry.getValue(); 
      if(child.isArray()) 
      { 
       // We ignore arrays so they get instantiated fresh every time 
       // root.remove(fieldEntry.getKey()); 
      } 
      else 
      { 
       if(child.isObject()) 
       { 
        if(propAccessor == null) 
        { 
         propAccessor = PropertyAccessorFactory.forDirectFieldAccess(objToBindInto); 
        } 
        Object o2 = propAccessor.getPropertyValue(fieldEntry.getKey()); 
        if(o2 != null) 
        { 

         // Only remove the JsonNode if the object already exists 
         // Otherwise it will be instantiated when the parent gets 
         // deserialized 
         i.remove(); 
         applyRecursively(o2, child); 
        } 
       } 
      } 
     } 
     ObjectReader jsonReader = objectMapper.readerForUpdating(objToBindInto); 
     jsonReader.readValue(node); 
    } 
} 

हम वसंत के HandlerMethodArgumentResolver के एक कार्यान्वयन के साथ इस का उपयोग करें।

हम बहुत सारे वसंत के एमवीसी ढांचे का उपयोग नहीं करते हैं। हम बस वसंत के कई अलग-अलग हिस्सों का उपयोग करके एक JSON एपीआई बैकएंड बना रहे हैं। यह सब काम करने के लिए नलसाजी की एक बहुत अच्छी मात्रा है, लेकिन अब हमारे नियंत्रक बहुत ही सरल हैं।

दुर्भाग्य से मैं अपने सभी कोड नहीं दिखा सकता, यह वैसे भी काफी लंबा है। मुझे आशा है कि यह समस्या का कम से कम हिस्सा हल करेगी।

संबंधित मुद्दे