2010-12-03 9 views
25

में रूपांतरण सेवा सेवा मैं स्प्रिंग एप्लिकेशन में इस योजना का पालन कर रहा हूं।वसंत

  1. अनुरोध वस्तु की आईडी और कुछ अन्य पैरामीटर वाला सर्वर को भेजा जाता इस वस्तु
  2. इस आईडी के साथ वस्तु में भर जाएगी करने के लिए डेटाबेस से भरी हुई है
  3. getters और setters में लागू कर रहे हैं इस वस्तु मान
  4. वस्तु तो संग्रहीत किया जाता है

मैं this other question में पूछा से पहले वस्तु तैयार करने के लिए अनुरोध के पैरामीटर पॉप्युलेट सबसे अच्छा तरीका था क्या पॉप्युलेट करने के लिए। जवाब यह था कि @ModelAtribute एनोटेटेड विधि में या initBinder में एक संपादक के साथ conversion service का उपयोग करने का सबसे अच्छा तरीका था।

तो मैंने कनवर्टर का उपयोग करने की कोशिश की है, लेकिन मुझे एक समान उदाहरण नहीं मिला है और मैं थोड़ा फंस गया हूं। मैंने नीचे दिए गए कोड की तरह एक कोड लिखा है: इनिट बाइंडर में मैं रूपांतरण सेवा पंजीकृत करता हूं। तो उपयोगकर्ता ऑब्जेक्ट कन्वर्ट() विधि पर मान को पॉप्युलेट करने से पहले ऑब्जेक्ट को डेटाबेस से लोड करने के लिए बुलाया जाता है। समस्या यह है कि यह कॉन्फ़िगरेशन काम नहीं करता है क्योंकि यह किसी ऑब्जेक्ट उपयोगकर्ता के ऑब्जेक्ट उपयोगकर्ता के आईडी (उपयोगकर्ता नाम फ़ील्ड) को परिवर्तित कर रहा है, लेकिन फिर यह ऑब्जेक्ट के साथ setUsername() बनाने की कोशिश करता है, इसलिए मुझे "java.lang" मिलता है IleglegArgumentException: तर्क प्रकार मेल नहीं खाता "।

क्या कोई मुझे इच्छित व्यवहार प्राप्त करने के लिए रूपांतरण सेवा का उपयोग करने के तरीके का एक सुराग या उदाहरण दे सकता है?

धन्यवाद।

@Autowired 
private ConversionService conversionService; 

@InitBinder("user") 
public void initBinder(@RequestParam("username")String username, WebDataBinder binder){ 
    binder.setConversionService(conversionService); 
} 

@RequestMapping(value="/user/save", method=RequestMethod.POST) 
public String save(@ModelAttribute("user") User user, Model model) {   
    ... 
} 

की तरह कुछ के साथ:

@Component 
public class UserConversionService implements ConversionService{ 
    ...   
    @Override 
    public Object convert(Object name, TypeDescriptor arg1, TypeDescriptor arg2) { 
     return userService.find((String)name); 
    } 
} 
+0

यह भी देखें: http://stackoverflow.com/a/10240927/59087 –

उत्तर

39

आप एक ConversionService लागू करने के लिए तार और उपयोगकर्ता वस्तुओं के बीच रूपांतरण करने के लिए कोशिश कर रहे हैं। हालांकि, यह Converter कार्यान्वयन है जो इस भाग को करता है। आप क्या करना चाहते हैं:

  1. एक कनवर्टर
  2. लिखें ConversionService के ConversionService
  3. उपयोग करें के साथ पंजीकरण कि कनवर्टर।

आपका कनवर्टर होगा कुछ की तरह:

final class UserConverter implements Converter<String, User> { 
    ... 
    public User convert(String username) { 
     return userService.find(username); 
    } 

} 

तब आप उस कनवर्टर रजिस्टर करने के लिए की जरूरत है। आप या तो अपने स्वयं के ConversionServiceFactoryBean लिख सकते हैं या डिफ़ॉल्ट ओवरराइड कर सकते हैं:

<bean id="conversionService" 
     class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name="converters"> 
     <list> 
      <bean class="example.UserConverter"/> 
     </list> 
    </property> 
</bean> 

आप, स्पष्ट रूप से ConversionService का उपयोग आप के रूप में, बस यह कुछ है कि autowired किया जा सकता है के रूप में छोड़ने के लिए चाहते हैं। वसंत और फैक्ट्रीबीन परिभाषा बाकी की देखभाल करेगी।

यदि, हालांकि, आप पहले से ही अपने संदर्भ में <mvc:annotation-driven> टैग का उपयोग कर रहे हैं, तो आप अपने रूपांतरण सेवा FactoryBean को संदर्भित करने के लिए विशेषता का उपयोग कर सकते हैं।इसके बाद आपको अपनी कक्षा में इनिटबिंडर या कनवर्ज़न सेवा की आवश्यकता नहीं है: केवल @RequestMapping का पैरामीटर होने पर आपका लक्ष्य प्रकार, उपयोगकर्ता, रूपांतरण हस्तक्षेप किए बिना होगा।

+0

मैं रूपांतरण सेवा को पंजीकृत करने में सफल रहा हूं जैसा आपने कहा है , और मैं binder.convertIfNecessary को कॉल कर सकता हूं (उपयोगकर्ता नाम, User.class) और अभियंता का आह्वान किया जाता है। लेकिन उपयोगकर्ता को पॉप्युलेट करने से पहले इसे नहीं कहा जा रहा है। मै मैप किए गए विधि से पहले इसे नहीं बुलाता हूं। आपके पास क्या मतलब है "केवल @RequestMapping का पैरामीटर होने पर आपका लक्ष्य प्रकार, उपयोगकर्ता, रूपांतरण होगा"। मैंने इस पैरा को इस विधि में जोड़ने की कोशिश की है: (@RequestParam ("username") स्ट्रिंग उपयोगकर्ता नाम, @ModelAttribute ("userTest") उपयोगकर्ता उपयोगकर्ता) लेकिन ऐसा लगता है कि यह काम नहीं कर रहा है। – Javi

+0

कोशिश कर रहा है कि मुझे एहसास हुआ है कि यदि मैं अपनी विधि में सार्वजनिक स्ट्रिंग सेव (@RequestParam ("username") उपयोगकर्ता उपयोगकर्ता करता हूं तो यह कनवर्टर को आमंत्रित करता है, लेकिन मैं @ModelAttribute एनोटेशन को हटाना नहीं चाहता क्योंकि मैं मूल्यों को पॉप्युलेट करना चाहता हूं (और मैं @ModelAttribute और @RequestParam एनोटेशन दोनों के साथ समान पैरामीटर को एनोटेट नहीं कर सकता)। कोई उपाय? – Javi

+0

@Javi - हम्म, यह दिलचस्प व्यवहार है। मैं दोनों काम करने की उम्मीद करता। अस्थायी उपाय के रूप में, आप अपनी विधि को मॉडल पैरामीटर दे सकते हैं और स्पष्ट रूप से परिवर्तित उपयोगकर्ता को मॉडल में जोड़ सकते हैं। यह निश्चित रूप से साफ नहीं है, लेकिन यह निश्चित रूप से काम करेगा। – GaryF

4

मैंने किया था कि वास्तव में क्या गैरी ऊपर कह रहा है और यह काम किया:

मैं समाधान के लिए कुछ और जानकारी जोड़ना चाहते हैं। स्प्रिंग प्रलेखन here के अनुसार एक यूआरआई टेम्पलेट चर कनवर्टर/रूपांतरण सेवा का उपयोग कर लक्षित ऑब्जेक्ट में अनुवादित हो जाता है। मैंने @RequestParam("id") @ModelAttribute("contact") Contact contact का उपयोग करने की कोशिश की, लेकिन मुझे अपने दृश्य edit.jsp में मॉडल ऑब्जेक्ट contact नहीं होने के लिए IllegalStateException: Neither BindingResult nor plain target object for bean name 'contact' available as request attribute मिल रहा था। इसे Model model और model.addAttribute(contact); घोषित करके आसानी से हल किया जा सकता है। हालांकि, एक बेहतर तरीका भी है; यूआरआई टेम्पलेट चर का उपयोग कर। यह अजीब बात है कि @RequestParam काम नहीं किया।

काम नहीं किया

@RequestMapping("edit") //Passing id as .. edit?id=1 
public String editWithConverter(@RequestParam("id") @ModelAttribute("contact") Contact contact){ 
    logger.info("edit with converter"); 
    return "contact/edit"; 
} 

कि क्या सफल

@RequestMapping("edit/{contact}") //Passing id as .. edit/1 
public String editWithConverter(@PathVariable("contact") @ModelAttribute("contact") Contact contact){ // STS gave a warning for using {contact} without @PathVariable 
    logger.info("edit with converter"); 
    return "contact/edit"; 
} 

तो क्या करता है यह काम करते हैं .. ...edit/1 की तरह एक लिंक परोक्ष स्ट्रिंग '1' आईडी के संपर्क करने के लिए 'के लिए कनवर्टर का आह्वान 1 'रूपांतरण, और इस संपर्क वस्तु को देखने के लिए लाता है। @InitBinder के लिए कोई आवश्यकता नहीं है और इसके बाद ConverterConversionService के साथ पंजीकृत है, इसलिए मैं कहीं भी का उपयोग कर सकता हूं - स्पष्ट रूप से या स्पष्ट रूप से

+2

क्या कार्य अनुभाग में कोड सही है? – oneworld