2010-10-08 3 views
14

मैं स्प्रिंग फ्रेमवर्क का उपयोग कर हमारे वेब आधारित एप्लिकेशन के लिए एक प्लगइन सिस्टम तैयार कर रहा हूं। प्लगइन्स क्लासपाथ पर जार हैं। तो मैं जेएसपी जैसे स्रोत प्राप्त करने में सक्षम हूं,क्या वसंत संदेश स्रोत एकाधिक कक्षा पथ का समर्थन करता है?

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 
Resource[] pages = resolver.getResources("classpath*:jsp/*jsp"); 

अब तक बहुत अच्छा है। लेकिन मुझे संदेश स्रोत के साथ एक समस्या है। मुझे लगता है कि ReloadableResourceBundleMessageSource#setBasename"क्लासपाथ *:" के माध्यम से एकाधिक वर्ग पथ का समर्थन नहीं करता है, अगर मैं सिर्फ "क्लासपाथ:" का उपयोग करता हूं, तो मुझे केवल एक प्लगइन से संदेश स्रोत मिलता है।

क्या किसी को यह पता है कि सभी प्लगइन से संदेश स्रोत कैसे पंजीकृत करें? संदेश स्रोत के ऐसे कार्यान्वयन मौजूद है?

उत्तर

8

यहां मुद्दा यह है कई classpaths या classloaders साथ नहीं है, लेकिन साथ कितने संसाधनों कोड किसी विशेष पथ के लिए कोशिश करते हैं और लोड होगा।

classpath* वाक्यविन्यास एक स्प्रिंग तंत्र है, जो कोड को किसी दिए गए पथ के लिए एकाधिक संसाधन लोड करने की अनुमति देता है। बेहद सुविधाजनक। हालांकि, संसाधनों को लोड करने के लिए ResourceBundleMessageSource मानक java.util.ResourceBundle का उपयोग करता है, और यह एक बहुत ही सरल, डम्बर तंत्र है, जो किसी दिए गए पथ के लिए पहला संसाधन लोड करेगा, और बाकी सब कुछ अनदेखा करेगा।

मेरे पास वास्तव में आपके लिए कोई आसान फ़िक्स नहीं है। मुझे लगता है कि आपको ResourceBundleMessageSource को डुबोना होगा और MessageSource (AbstractMessageSource उप-वर्गीकरण द्वारा संभवतः PathMatchingResourcePatternResolver का उपयोग करके विभिन्न संसाधनों का पता लगाने और MessageSource इंटरफेस के माध्यम से उन्हें बेनकाब करने के लिए PathMatchingResourcePatternResolver का एक कस्टम कार्यान्वयन लिखना होगा। ResourceBundle बहुत मदद नहीं करेगा।

+0

धन्यवाद! यह कुछ है जिसके बारे में मुझे चिंतित है। – banterCZ

+0

एक समाधान के लिए जो काम करता है [ajaristi का जवाब] (http://stackoverflow.com/a/27532814/606662) –

9

आप नीचे जैसा कुछ कर सकते हैं - अनिवार्य रूप से प्रत्येक प्रासंगिक बेसनाम को निर्दिष्ट करें।

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 
     <property name="basenames"> 
      <list> 
       <value>classpath:com/your/package/source1</value> 
       <value>classpath:com/your/second/package/source2</value> 
       <value>classpath:com/your/third/package/source3/value> 
       <value>classpath:com/your/fourth/package/source4</value> 
      </list> 
     </property> 
    </bean> 
+5

हाँ, यह सही है। लेकिन आपको पहले से सभी प्लगइन्स जानना होगा। आत्माओं को प्लगइन के लिए सार्वभौमिक होना चाहिए। – banterCZ

+4

आपने मुझे सिखाया कि मूल्यों में पैकेज पथ कैसे दर्ज करें। –

2

विकल्प के रूप में, आप उदाहरण नीचे की तरह refreshPropertiesReloadableResourceBundleMessageSource वर्ग से विधि रद्द कर सकते थे:

public class MultipleMessageSource extends ReloadableResourceBundleMessageSource { 
    private static final String PROPERTIES_SUFFIX = ".properties"; 
    private PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 

    @Override 
    protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) { 
    Properties properties = new Properties(); 
    long lastModified = -1; 
    try { 
     Resource[] resources = resolver.getResources(filename + PROPERTIES_SUFFIX); 
     for (Resource resource : resources) { 
     String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, ""); 
     PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder); 
     properties.putAll(holder.getProperties()); 
     if (lastModified < resource.lastModified()) 
      lastModified = resource.lastModified(); 
     } 
    } catch (IOException ignored) { } 
    return new PropertiesHolder(properties, lastModified); 
    } 
} 

और ReloadableResourceBundleMessageSource की तरह वसंत संदर्भ विन्यास के साथ इसका इस्तेमाल:

<bean id="messageSource" class="common.utils.MultipleMessageSource"> 
    <property name="basenames"> 
     <list> 
     <value>classpath:/messages/validation</value> 
     <value>classpath:/messages/messages</value> 
     </list> 
    </property> 
    <property name="fileEncodings" value="UTF-8"/> 
    <property name="defaultEncoding" value="UTF-8"/> 
    </bean> 

मुझे लगता है कि इस चाल करना चाहिए ।

10

@ seralex-vi basenames/WEB-INF/संदेशों के समाधान के साथ काम नहीं किया गया।

मैं कक्षा ReloadableResourceBundleMessageSource पर विधि refreshProperties overwrited जो basenames के दोनों प्रकार के प्रदर्शन: वसंत-context.xml पर (classpath * और/वेब-INF /)

public class SmReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource { 

private static final String PROPERTIES_SUFFIX = ".properties"; 

private PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 

@Override 
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) { 
    if (filename.startsWith(PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) { 
     return refreshClassPathProperties(filename, propHolder); 
    } else { 
     return super.refreshProperties(filename, propHolder); 
    } 
} 

private PropertiesHolder refreshClassPathProperties(String filename, PropertiesHolder propHolder) { 
    Properties properties = new Properties(); 
    long lastModified = -1; 
    try { 
     Resource[] resources = resolver.getResources(filename + PROPERTIES_SUFFIX); 
     for (Resource resource : resources) { 
     String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, ""); 
     PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder); 
     properties.putAll(holder.getProperties()); 
     if (lastModified < resource.lastModified()) 
      lastModified = resource.lastModified(); 
     } 
    } catch (IOException ignored) { 
    } 
    return new PropertiesHolder(properties, lastModified); 
} 

आप classpath होना आवश्यक है *: उपसर्ग

<bean id="messageSource" class="SmReloadableResourceBundleMessageSource"> 
    <property name="basenames"> 
     <list> 
      <value>/WEB-INF/i18n/enums</value> 
      <value>/WEB-INF/i18n/messages</value> 
      <value>classpath*:/META-INF/messages-common</value> 
      <value>classpath*:/META-INF/enums</value> 
     </list> 
    </property> 
</bean> 
+5

यह उत्तर होना चाहिए, यह एक समाधान देता है और यह काम करता है। धन्यवाद – Don

0

आप जावा विन्यास और श्रेणीबद्ध संदेश स्रोतों एक काफी सरल प्लगइन प्रणाली का निर्माण करने का लाभ ले सकते। प्रत्येक प्लगेबल जार में इस तरह एक वर्ग ड्रॉप:

@Configuration 
public class MyPluginConfig { 
    @Bean 
    @Qualifier("external") 
    public HierarchicalMessageSource mypluginMessageSource() { 
     ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
     messageSource.setBasenames("classpath:my-plugin-messages"); 
     return messageSource; 
    } 
} 

और इसी my-plugin-messages.properties फ़ाइलें।

मुख्य आवेदन जावा config कक्षा में कुछ इस तरह से रख:

@Configuration 
public class MainConfig { 
    @Autowired(required = false) 
    @Qualifier("external") 
    private List<HierarchicalMessageSource> externalMessageSources = Collections.emptyList(); 

    @Bean 
    public MessageSource messageSource() { 
     ReloadableResourceBundleMessageSource rootMessageSource = new ReloadableResourceBundleMessageSource(); 
     rootMessageSource.setBasenames("classpath:messages"); 

     if (externalMessageSources.isEmpty()) { 
      // No external message sources found, just main message source will be used 
      return rootMessageSource; 
     } 
     else { 
      // Wiring detected external message sources, putting main message source as "last resort" 
      int count = externalMessageSources.size(); 

      for (int i = 0; i < count; i++) { 
       HierarchicalMessageSource current = externalMessageSources.get(i); 
       current.setParentMessageSource(i == count - 1 ? rootMessageSource : externalMessageSources.get(i + 1)); 
      } 
      return externalMessageSources.get(0); 
     } 
    } 
} 

तो प्लगइन्स के आदेश प्रासंगिक है, बस प्रत्येक प्लगेबल संदेश स्रोत सेम में @Order एनोटेशन रखते हैं।

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