2012-09-22 12 views
120

मैं स्प्रिंग एमवीसी में डेटा को बांधने और परिवर्तित करने का सबसे आसान और सरल तरीका ढूंढ रहा हूं। यदि संभव हो, तो कोई एक्सएमएल विन्यास किए बिना।वसंत एमवीसी प्रकार रूपांतरण: संपत्ति संपादक या कनवर्टर?

अब तक मैं बहुत तरह PropertyEditors उपयोग कर रहे हैं:

public class CategoryEditor extends PropertyEditorSupport { 

    // Converts a String to a Category (when submitting form) 
    @Override 
    public void setAsText(String text) { 
     Category c = new Category(text); 
     this.setValue(c); 
    } 

    // Converts a Category to a String (when displaying form) 
    @Override 
    public String getAsText() { 
     Category c = (Category) this.getValue(); 
     return c.getName(); 
    } 

} 

और

... 
public class MyController { 

    @InitBinder 
    public void initBinder(WebDataBinder binder) { 
     binder.registerCustomEditor(Category.class, new CategoryEditor()); 
    } 

    ... 

} 

यह सरल है: दोनों रूपांतरण एक ही कक्षा में परिभाषित कर रहे हैं, और बाध्यकारी सरल है। अगर मैं अपने सभी नियंत्रकों में एक सामान्य बाध्यकारी करना चाहता था, तो भी मैं 3 lines in my xml config जोड़ सकता था।


लेकिन वसंत 3.x यह करने के लिए एक नया तरीका पेश किया, Converters का उपयोग कर:

एक स्प्रिंग कंटेनर के भीतर, इस प्रणाली PropertyEditors के लिए एक विकल्प के रूप में इस्तेमाल किया जा सकता

तो मान लें कि मैं कन्वर्टर्स का उपयोग करना चाहता हूं क्योंकि यह "नवीनतम विकल्प" है। मैं दो कन्वर्टर्स बनाना होगा:

public class StringToCategory implements Converter<String, Category> { 

    @Override 
    public Category convert(String source) { 
     Category c = new Category(source); 
     return c; 
    } 

} 

public class CategoryToString implements Converter<Category, String> { 

    @Override 
    public String convert(Category source) { 
     return source.getName(); 
    } 

} 

पहले खामी: मैं दो वर्गों बनाने के लिए किया है। लाभ: सामान्यता के लिए धन्यवाद डालने की कोई ज़रूरत नहीं है।

फिर, मैं बस कनवर्टर्स को डेटा कैसे बांधूं?

दूसरा दोष यह है: ऐसा कुछ नहीं: मैं किसी भी सरल तरीका (एनोटेशन या अन्य कार्यक्रम संबंधी सुविधाएं) एक नियंत्रक में यह करने के लिए नहीं मिला है।

केवल तरीके मैं, थकाऊ आसान नहीं है, और केवल के बारे में सामान्य पार नियंत्रक बाध्यकारी होगा मिल गया है:

  • XML config:

    <bean id="conversionService" 
        class="org.springframework.context.support.ConversionServiceFactoryBean"> 
        <property name="converters"> 
         <set> 
          <bean class="somepackage.StringToCategory"/> 
          <bean class="somepackage.CategoryToString"/> 
         </set> 
        </property> 
    </bean> 
    
  • Java config (केवल स्प्रिंग में 3.1+):

    @EnableWebMvc 
    @Configuration 
    public class WebConfig extends WebMvcConfigurerAdapter { 
    
        @Override 
        protected void addFormatters(FormatterRegistry registry) { 
         registry.addConverter(new StringToCategory()); 
         registry.addConverter(new CategoryToString()); 
        } 
    
    } 
    

इन सभी दोषों के साथ, कन्वर्टर्स का उपयोग क्यों करें? क्या मैं कुछ भूल रहा हूँ ? क्या ऐसी कोई चाल है जिसके बारे में मुझे पता नहीं है?

मैं PropertyEditors का उपयोग करने के लिए प्रेरित हूं ... बाध्यकारी बहुत आसान और तेज है।

+0

नोट (मैं वसंत 3.2.17 का उपयोग करके भी ठोकर खा रहा हूं): का उपयोग करते समय वास्तव में इस रूपांतरण को संदर्भित करने की आवश्यकता है सेवा बीन: mauhiz

उत्तर

50
इन सभी कमियां, क्यों कन्वर्टर्स का उपयोग कर के साथ

? क्या मुझे कुछ याद आ रहा है? क्या ऐसी कोई चाल है जिसके बारे में मुझे पता नहीं है?

नहीं, मुझे लगता है कि आपने संपत्ति एडिटर और कनवर्टर दोनों को बहुत व्यापक रूप से वर्णित किया है, प्रत्येक को कैसे घोषित और पंजीकृत किया जाता है।

मेरे दिमाग में, प्रॉपर्टी एडिटर स्कोप में सीमित हैं - वे स्ट्रिंग को एक प्रकार में परिवर्तित करने में मदद करते हैं, और यह स्ट्रिंग आम तौर पर यूआई से आती है, और इसलिए @InitBinder का उपयोग करके प्रॉपर्टी एडिटर को पंजीकृत करना और वेबडाटाइंडर का उपयोग करना समझ में आता है। न सिर्फ यूआई संबंधित रूपांतरण (प्रकार लक्षित करने के लिए स्ट्रिंग) के लिए - दूसरे हाथ पर

कनवर्टर अधिक सामान्य यह प्रणाली में किसी भी परिवर्तन के लिए बनाई गई है,,। उदाहरण के लिए, वसंत एकीकरण एक संदेश पेलोड को वांछित प्रकार में परिवर्तित करने के लिए बड़े पैमाने पर कनवर्टर का उपयोग करता है।

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

+5

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

+1

@ बोरीस क्लीनर हां, लेकिन विशेष रूप से शुरुआती के लिए आसान नहीं: आपको 2 कनवर्टर कक्षाएं लिखनी होंगी + xml कॉन्फ़िगरेशन या जावा कॉन्फ़िगरेशन में कई लाइनें जोड़ें। मैं सामान्य रूपांतरण (न केवल संस्थाओं) के साथ, स्प्रिंग एमवीसी फॉर्म जमा/प्रदर्शित करने के बारे में बात कर रहा हूं। –

7

सबसे सरल (यह मानते हुए कि आप एक दृढ़ता फ्रेमवर्क का उपयोग कर रहे हैं), लेकिन ConditionalGenericConverter इंटरफ़ेस के माध्यम से जेनेरिक इकाई कनवर्टर को कार्यान्वित करने का सही तरीका नहीं है जो उनके मेटाडेटा का उपयोग करके इकाइयों को परिवर्तित करेगा।

उदाहरण के लिए, यदि आप जेपीए उपयोग कर रहे हैं, इस कनवर्टर यदि निर्दिष्ट वर्ग @Entity एनोटेशन है देखो, और जानकारी निकालने और स्वचालित रूप से देखने के लिए एक आईडी के रूप में आपूर्ति की स्ट्रिंग मान का उपयोग कर देखने प्रदर्शन करने के लिए @Id एनोटेट क्षेत्र का उपयोग कर सकते हैं।

public interface ConditionalGenericConverter extends GenericConverter { 
    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType); 
} 

ConditionalGenericConverter स्प्रिंग रूपांतरण API का "अंतिम हथियार" है, लेकिन एक बार यह इकाई convertions के सबसे प्रोसेस करने में सक्षम हो जाएगा लागू किया जा रहा, डेवलपर समय की बचत - यह एक बड़ी राहत है जब आप केवल पैरामीटर के रूप में इकाई वर्गों को निर्दिष्ट अपने नियंत्रक का और कभी भी एक नया कनवर्टर लागू करने के बारे में सोचें (निश्चित रूप से कस्टम और गैर-इकाई प्रकारों को छोड़कर)।

+0

केवल इकाई रूपांतरण के साथ सौदा करने के लिए अच्छा समाधान, चाल के लिए धन्यवाद। शुरुआत में आसान नहीं है क्योंकि आपको एक और कक्षा लिखनी है, लेकिन लंबे समय तक सरल और समय बर्बाद है। –

+0

बीटीडब्ल्यू ऐसे कनवर्टर को किसी भी प्रकार के लिए लागू किया जा सकता है जो कुछ सामान्य अनुबंध का पालन करता है - एक और उदाहरण: यदि आपके enums कुछ सामान्य रिवर्स लुकअप इंटरफ़ेस को लागू करते हैं - तो आप भी एक सामान्य कनवर्टर को लागू करने में सक्षम होंगे (यह http के समान होगा: //stackoverflow.com/questions/5178622/spring-custom-converter-for-all-enums) –

+0

@ जेरोम डाल्बर्ट हां, शुरुआत करने वालों के लिए कुछ भारी वजन घटाने के लिए थोड़ा मुश्किल है, लेकिन यदि आपके पास डेवलपर्स की एक टीम है तो यह सरल हो) पीएस और यह वही संपत्ति संपादक को हर बार फॉर्म बाध्यकारी पर पंजीकृत करने के लिए उबाऊ हो जाएगा) –

14
  1. स्ट्रिंग रूपांतरण से/करने के लिए formatters (org.springframework.format.Formatter लागू) के बजाय कन्वर्टर्स का उपयोग करें। यह प्रिंट (...) और पार्स (...) तरीकों है, तो आप दो के बजाय सिर्फ एक ही वर्ग की जरूरत है। उन्हें रजिस्टर करने के लिए, का उपयोग करें FormattingConversionServiceFactoryBean, जो दोनों कन्वर्टर्स और formatters रजिस्टर कर सकते हैं, के बजाय ConversionServiceFactoryBean। ,
    • फ़ॉर्मेटर इंटरफेस इसके प्रिंट में लोकेल वस्तु की आपूर्ति (...) और पार्स (...) तरीकों तो अपने स्ट्रिंग रूपांतरण कर सकते हैं:
    • नई फ़ॉर्मेटर सामान अतिरिक्त लाभ के एक जोड़े है स्थान के प्रति संवेदनशील होना
    • preregistered formatters के अलावा, FormattingConversionServiceFactoryBean preregistered AnnotationFormatterFactory वस्तुओं काम की एक जोड़ी है, कि तुम अतिरिक्त स्वरूपण पी निर्दिष्ट कर सकते हैं के साथ आता है एनोटेशन के माध्यम से arameters। उदाहरण के लिए: @RequestParam @DateTimeFormat (पैटर्न = "MM-dd-yy") LOCALDATE baseDate ... यह अपनी खुद की AnnotationFormatterFactory कक्षाएं बनाने के लिए, स्प्रिंग के NumberFormatAnnotationFormatterFactory देखना बहुत मुश्किल नहीं है एक साधारण उदाहरण के लिए। मुझे लगता है कि यह नियंत्रक-विशिष्ट स्वरूपण/संपादकों की आवश्यकता को समाप्त करता है। सभी नियंत्रकों के लिए एक रूपांतरण सेवा का उपयोग करें और एनोटेशन के माध्यम से स्वरूपण को कस्टमाइज़ करें।
  2. मैं मानता हूं कि यदि आपको अभी भी कुछ नियंत्रक-विशिष्ट स्ट्रिंग रूपांतरण की आवश्यकता है, तो सबसे आसान तरीका अभी भी कस्टम प्रॉपर्टी एडिटर का उपयोग करना है। (मैंने binder.setConversionService (...) 'को @InitBinder विधि में कॉल करने का प्रयास किया, लेकिन यह विफल हो जाता है, क्योंकि बाइंडर ऑब्जेक्ट पहले से सेट' ग्लोबल 'रूपांतरण सेवा के साथ आता है। प्रति-नियंत्रक रूपांतरण की तरह लगता है स्प्रिंग 3 में वर्गों को हतोत्साहित किया जाता है)।
0

आप दो कनवर्टर्स को स्थैतिक आंतरिक कक्षाओं के रूप में कार्यान्वित करके दो अलग कनवर्टर कक्षाओं की आवश्यकता के आसपास काम को व्यवस्थित कर सकते हैं।

public class FooConverter { 
    public static class BarToBaz implements Converter<Bar, Baz> { 
     @Override public Baz convert(Bar bar) { ... } 
    } 
    public static class BazToBar implements Converter<Baz, Bar> { 
     @Override public Bar convert(Baz baz) { ... } 
    } 
} 

तुम अब भी उन दोनों को अलग से रजिस्टर करने की आवश्यकता है, लेकिन कम से कम इस फाइल को आप यदि आप कोई परिवर्तन करने के संशोधित करने की आवश्यकता की संख्या पर कटौती।