स्प्रिंग बूट और कई बाहरी विन्यास फाइल


125

मेरे पास कई संपत्ति फाइलें हैं जिन्हें मैं क्लासपाथ से लोड करना चाहता हूं। एक डिफ़ॉल्ट सेट है /src/main/resourcesजिसके तहत हिस्सा है myapp.jar। मेरी springcontextउम्मीद है कि फाइलें क्लासपाथ पर होंगी। अर्थात

<util:properties id="Job1Props"
    location="classpath:job1.properties"></util:properties>

<util:properties id="Job2Props"
    location="classpath:job2.properties"></util:properties>

मुझे बाहरी सेट के साथ इन गुणों को ओवरराइड करने के विकल्प की भी आवश्यकता है। मेरे पास एक बाहरी कॉन्फ़िगरेशन फ़ोल्डर है cwd। स्प्रिंग बूट के अनुसार डॉच कॉन्फिग फोल्डर क्लासपाथ पर होना चाहिए। लेकिन इसकी डॉक्टर से स्पष्ट नहीं है अगर यह केवल applicaiton.propertiesवहाँ से या सभी संपत्तियों को ओवरराइड करेगा ।

जब मैंने इसका परीक्षण किया, तो केवल application.propertiesउठाया जाता है और बाकी संपत्तियों को अभी भी उठाया जाता है /src/main/resources। मैंने उन्हें अल्पविराम से अलग की गई सूची के रूप में आपूर्ति करने की कोशिश की है, spring.config.locationलेकिन डिफ़ॉल्ट सेट अभी भी ओवरराइड नहीं हो रहा है।

मैं मूल संरचना बाहरी डिफ़ॉल्ट फ़ाइलों को ओवरराइड कैसे करूँ?

वर्कअराउंड के रूप में मैंने वर्तमान में app.config.location(ऐप विशिष्ट प्रॉपर्टी) का उपयोग किया है, जिसे मैं कमांड लाइन के माध्यम से आपूर्ति करता हूं। अर्थात

java -jar myapp.jar app.config.location=file:./config

और मैंने अपने applicationcontextको बदल दिया

<util:properties id="Job2Props"
    location="{app.config.location}/job2.properties"></util:properties>

और यह है कि कैसे मैं आवेदन लोड करते समय फ़ाइल और क्लासपैथ के बीच अलगाव करता हूं।
संपादन:

//psuedo code

if (StringUtils.isBlank(app.config.location)) {
            System.setProperty(APP_CONFIG_LOCATION, "classpath:");
}

मैं वास्तव में उपरोक्त वर्कअराउंड का उपयोग नहीं करना चाहता हूं और क्लासपाथ पर सभी बाहरी कॉन्फ़िगरेशन फ़ाइलों को स्प्रिंग ओवरराइड करता हूं जैसे यह application.propertiesफ़ाइल के लिए करता है ।


4
application.propertiesहमेशा की तरह, लोड किया जाएगा के साथ spring.config.locationआप अतिरिक्त विन्यास स्थानों है कि फ़ाइलों के लिए जाँच कर रहे हैं जोड़ सकते हैं (जो है, जब यह एक साथ समाप्त होता है /) लेकिन अगर आप उन लोड किया जाएगा फ़ाइलों के लिए वहाँ जो अंक में की अल्पविराम द्वारा अलग सूची डाल दिया। इसे यहां
एम। डाइनम

जवाबों:


155

स्प्रिंग बूट का उपयोग करते समय गुणों को निम्न क्रम में लोड किया जाता है ( स्प्रिंग बूट संदर्भ गाइड में बाहरी कॉन्फ़िगरेशन देखें )।

  1. कमांड लाइन तर्क।
  2. जावा सिस्टम गुण (System.getProperties ())।
  3. ओएस पर्यावरण चर।
  4. JNDI जावा से गुण: COMP / env
  5. एक randomValuePropertySource जिसमें केवल यादृच्छिक में गुण हैं। *।
  6. आपके पैक किए गए जार के बाहर आवेदन गुण (YAML और प्रोफाइल वेरिएंट सहित application.properties)।
  7. आपके जार के अंदर पैक किए गए अनुप्रयोग गुण (YAML और प्रोफाइल वेरिएंट सहित application.properties)।
  8. आपके @Configuration कक्षाओं पर @PropertySource एनोटेशन।
  9. डिफ़ॉल्ट गुण (SpringApplication.setDefaultProperties का उपयोग करके निर्दिष्ट)।

जब गुणों को हल करना (अर्थात @Value("${myprop}")निराकरण रिवर्स ऑर्डर में किया जाता है (इसलिए 9 से शुरू होता है)।

विभिन्न फ़ाइलों को जोड़ने के लिए आप उन spring.config.locationसंपत्तियों का उपयोग कर सकते हैं जो संपत्ति फ़ाइलों या फ़ाइल स्थान (निर्देशिका) की अल्पविराम से अलग सूची लेती हैं।

-Dspring.config.location=your/config/dir/

ऊपर एक निर्देशिका शामिल होगी जो application.propertiesफ़ाइलों के लिए परामर्श की जाएगी ।

-Dspring.config.location=classpath:job1.properties,classpath:job2.properties

यह लोड की गई फ़ाइलों में 2 गुण फ़ाइल जोड़ देगा।

डिफ़ॉल्ट कॉन्फ़िगरेशन फ़ाइलें और स्थान एडिटोनॉली निर्दिष्ट spring.config.locationलोगों से पहले लोड किए गए हैं, जिसका अर्थ है कि उत्तरार्द्ध हमेशा पहले वाले गुणों को ओवरराइड करेगा। ( स्प्रिंग बूट संदर्भ गाइड का यह खंड भी देखें )।

यदि spring.config.locationनिर्देशिकाएं (फ़ाइलों के विपरीत) हैं, तो उन्हें / में समाप्त होना चाहिए (और spring.config.nameलोड किए जाने से पहले उत्पन्न नामों के साथ जोड़ा जाएगा )। डिफ़ॉल्ट खोज पथ classpath:,classpath:/config,file:,file:config/हमेशा उपयोग किया जाता है, भले ही के मूल्य के बावजूद spring.config.location। इस तरह आप अपने एप्लिकेशन के लिए डिफ़ॉल्ट मान सेट कर सकते हैं application.properties(या आपके द्वारा चुना गया कोई भी अन्य बेसनेम spring.config.name) और डिफॉल्ट को ध्यान में रखते हुए इसे एक अलग फाइल के साथ रनटाइम पर ओवरराइड कर सकते हैं।

अद्यतन: वसंत के व्यवहार के रूप में .config.location अब इसे जोड़ने के बजाय डिफ़ॉल्ट ओवरराइड करता है। आपको डिफ़ॉल्ट रखने के लिए spring.config.additional-location का उपयोग करने की आवश्यकता है। यह व्यवहार में 1.x से 2.x तक का परिवर्तन है


2
धन्यवाद, लेकिन मैंने इस रेफ डॉ को पहले ही पढ़ा है और निम्नलिखित मुझे भ्रमित कर रहा है "-Dspring.config.location = आपका / config / dir / ऊपर जो एक निर्देशिका को जोड़ देगा, जिसे application.properties फ़ाइलों के लिए परामर्श दिया जाएगा।" इसका क्या मतलब है application.properties फाइलें। वह केवल एक फ़ाइल है। किसी भी स्थिति में यदि यह पूरी निर्देशिका को अंत में "/" के साथ लेने में सक्षम है तो मुझे कॉमा से अलग सूची के रूप में प्रत्येक को निर्दिष्ट करने की आवश्यकता नहीं है। मुझे लगता है कि मैंने अपनी पोस्ट में वर्णित दोनों दृष्टिकोण की कोशिश की है, लेकिन मैं इसे एक और कोशिश दूंगा
nir

के रूप में दस्तावेज़ में कहा गया है इसके लिए अन्य स्थानों की तरह डिफ़ॉल्ट से परामर्श किया जाना ले जाएगा application.propertiesऔर application-[env].properties। यह अन्य संपत्तियों की फाइलों को ध्यान में नहीं रखता है। यह संदर्भ गाइड में भी कहा गया है (अनुभाग में लिंक की ओर जाता है और संदर्भ गाइड से उद्धरण)।
एम। डाइनम

1
हां, लेकिन यह वही है जो मेरे लिए मायने नहीं रखता है .. क्यों पूरी निर्देशिका के बजाय क्लासपाथ पर एक निर्देशिका से केवल एक प्रकार की फ़ाइल पर विचार करें। यह आपको केवल एक संपत्ति फ़ाइल का उपयोग करने के लिए मजबूर करता है जो कि अच्छा नहीं है। टॉमकट में जैसे मैं classpath पर विशेष निर्देशिका (और यह सब कुछ जोर दिया) डालने के लिए common.loader को कॉन्फ़िगर कर सकता हूं क्यों क्लास लोडर बूट नहीं कर सकता है।
nir

3
प्रलेखन उद्धृत करना मददगार नहीं है। यदि दस्तावेज स्पष्ट था (विशेष रूप से आवश्यक तरीके से?) तो प्रश्न आवश्यक नहीं होगा। उदाहरण के लिए, इस मामले में, यह वास्तव में स्पष्ट नहीं है कि कैसे config.locationऔर config.namesबातचीत करें, हालांकि यह संभवतः उन लोगों को स्पष्ट प्रतीत होता है जो पहले से जानते हैं कि वे कैसे बातचीत करते हैं। क्या आप प्रलेखन में कुछ जोड़ने के लिए अपने उत्तर को अपडेट कर सकते हैं ?
Narfanator

13
इसे अपडेट किया जाना चाहिए, क्योंकि spring.config.locationअब का व्यवहार इसे जोड़ने के बजाय डिफ़ॉल्ट को ओवरराइड करता है। आपको spring.config.additional-locationचूक को बनाए रखने के लिए उपयोग करने की आवश्यकता है । यह व्यवहार में 1.x से 2.x तक का परिवर्तन है।
रॉबिन

32

स्प्रिंग बूट के साथ, spring.config.location काम करता है, बस अल्पविराम से अलग की गई संपत्तियाँ प्रदान करता है।

नीचे दिए गए कोड को देखें

@PropertySource(ignoreResourceNotFound=true,value="classpath:jdbc-${spring.profiles.active}.properties")
public class DBConfig{

     @Value("${jdbc.host}")
        private String jdbcHostName;
     }
}

एक आवेदन के अंदर jdbc.properties के डिफ़ॉल्ट संस्करण डाल सकते हैं। बाहरी संस्करणों को झूठ कहा जा सकता है।

java -jar target/myapp.jar --spring.config.location=classpath:file:///C:/Apps/springtest/jdbc.properties,classpath:file:///C:/Apps/springtest/jdbc-dev.properties

स्प्रिंग.प्रोफाइल.सक्रिय प्रॉपर्टी के उपयोग से निर्धारित प्रोफाइल वैल्यू के आधार पर, jdbc.host का मूल्य उठाया जाएगा। तो जब (खिड़कियों पर)

set spring.profiles.active=dev

jdbc.host jdbc-dev.properties से मूल्य लेगा।

के लिये

set spring.profiles.active=default

jdbc.properties से jdbc.host मान लेगा।


मुझे विश्वास नहीं है कि पहले कोड ब्लॉक काम करेंगे। मुझे पता है कि मैंने इस पर खुद को ठोकर मार दी, और इस जवाब का पालन ​​किया । सभ्य अन्वेषण के जवाब में संदर्भित jira.springsource.org/browse/SPR-8539 देखें ।
सोवाका

27

स्प्रिंग बूट 1.X और स्प्रिंग बूट 2.X के बारे में समान विकल्प और व्यवहार प्रदान नहीं करते हैं Externalized Configuration

एम। डीनम का बहुत अच्छा उत्तर स्प्रिंग बूट 1 विशिष्टताओं को संदर्भित करता है।
मैं यहां स्प्रिंग बूट 2 के लिए अपडेट करूंगा।

पर्यावरण गुण स्रोत और आदेश

स्प्रिंग बूट 2 एक बहुत ही विशेष PropertySourceक्रम का उपयोग करता है जिसे समझदार विचारों को मानने की अनुमति देने के लिए डिज़ाइन किया गया है। गुणों को निम्नलिखित क्रम में माना जाता है:

  • जब आपके घर की निर्देशिका (~ / .spring-boot-devtools.properties पर devtools सक्रिय है) पर देवताओल्स वैश्विक सेटिंग्स गुण।

  • @TestPropertySource आपके परीक्षणों पर टिप्पणी।

  • @SpringBootTest#propertiesएनोटेशन विशेषता आपके परीक्षणों पर। कमांड लाइन तर्क।

  • गुण SPRING_APPLICATION_JSON(इनलाइन JSON वातावरण चर या सिस्टम गुण में एम्बेडेड) से।

  • ServletConfig init पैरामीटर।

  • ServletContext init पैरामीटर।

  • JNDI की विशेषताएँ java:comp/env

  • जावा सिस्टम गुण ( System.getProperties())।

  • ओएस पर्यावरण चर।

  • A RandomValuePropertySourceमें केवल यादृच्छिक गुण हैं। *

  • आपके पैक किए गए जार ( application-{profile}.propertiesऔर YAML वेरिएंट) के बाहर प्रोफ़ाइल-विशिष्ट अनुप्रयोग गुण ।

  • प्रोफ़ाइल-विशिष्ट एप्लिकेशन गुण आपके जार ( application-{profile}.propertiesऔर YAML वेरिएंट) के अंदर पैक किए गए हैं ।

  • आपके पैक किए गए जार ( application.propertiesऔर YAML वेरिएंट) के बाहर आवेदन गुण ।

  • आपके जार ( application.propertiesऔर YAML वेरिएंट) के अंदर पैक किए गए आवेदन गुण ।

  • @PropertySourceआपकी @Configurationकक्षाओं पर टिप्पणी । डिफ़ॉल्ट गुण (सेटिंग द्वारा निर्दिष्ट SpringApplication.setDefaultProperties)।

बाहरी गुणों की फाइलें निर्दिष्ट करने के लिए इन विकल्पों में आपकी रुचि होनी चाहिए:

  • आपके पैक किए गए जार ( application-{profile}.propertiesऔर YAML वेरिएंट) के बाहर प्रोफ़ाइल-विशिष्ट अनुप्रयोग गुण ।

  • आपके पैक किए गए जार ( application.propertiesऔर YAML वेरिएंट) के बाहर आवेदन गुण ।

  • @PropertySourceआपकी @Configurationकक्षाओं पर टिप्पणी । डिफ़ॉल्ट गुण (सेटिंग द्वारा निर्दिष्ट SpringApplication.setDefaultProperties)।

आप इन 3 विकल्पों में से केवल एक का उपयोग कर सकते हैं या उन्हें अपनी आवश्यकताओं के अनुसार जोड़ सकते हैं।
उदाहरण के लिए केवल प्रोफ़ाइल-विशिष्ट गुणों का उपयोग करने वाले बहुत सरल मामलों के लिए पर्याप्त है लेकिन अन्य मामलों में आप प्रोफ़ाइल-विशिष्ट गुणों, डिफ़ॉल्ट गुणों और दोनों का उपयोग करना चाह सकते हैं @PropertySource

Application.properties फ़ाइलों के लिए डिफ़ॉल्ट स्थान

application.propertiesफ़ाइलों के बारे में (और संस्करण), डिफ़ॉल्ट रूप से स्प्रिंग उन्हें लोड करता है और निम्नलिखित क्रम में इन में से उनके गुणों को जोड़ता है:

  • वर्तमान निर्देशिका का एक / config उपनिर्देशिका

  • वर्तमान निर्देशिका

  • एक क्लासपैथ / कॉन्फिग पैकेज

  • क्लासपाथ की जड़

उच्च प्राथमिकताओं का शाब्दिक अर्थ है
classpath:/,classpath:/config/,file:./,file:./config/:।

विशिष्ट नामों वाली संपत्तियों की फ़ाइलों का उपयोग कैसे करें?

डिफ़ॉल्ट स्थान हमेशा पर्याप्त नहीं होते हैं: डिफ़ॉल्ट फ़ाइल नाम (जैसे application.properties) डिफ़ॉल्ट स्थान सूट नहीं कर सकते हैं। इसके अलावा, ओपी सवाल के रूप में आपको application.properties(और संस्करण) के अलावा कई कॉन्फ़िगरेशन फ़ाइलों को निर्दिष्ट करने की आवश्यकता हो सकती है ।
तो spring.config.nameपर्याप्त नहीं होगा।

इस मामले में आपको spring.config.locationपर्यावरण संपत्ति (जो निर्देशिका स्थानों या फ़ाइल पथों की अल्पविराम से अलग की गई सूची है) का उपयोग करके एक स्पष्ट स्थान प्रदान करना चाहिए ।
फ़ाइल नाम पैटर्न के बारे में मुक्त होने के लिए निर्देशिकाओं की सूची में फ़ाइल पथों की सूची का पक्ष लें।
उदाहरण के लिए ऐसा करें:

java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

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

spring.config.location अब उन्हें जोड़ने के बजाय डिफ़ॉल्ट स्थानों को बदल देता है

स्प्रिंग बूट 1 के साथ, spring.config.locationतर्क स्प्रिंग वातावरण में निर्दिष्ट स्थान जोड़ता है।
लेकिन स्प्रिंग बूट 2 से, spring.config.locationस्प्रिंग द्वारा उपयोग किए गए डिफ़ॉल्ट स्थानों को वसंत वातावरण में निर्दिष्ट स्थानों द्वारा प्रतिस्थापित किया जाता है जैसा कि प्रलेखन में कहा गया है

जब कस्टम कॉन्फ़िगरेशन स्थानों का उपयोग करके कॉन्फ़िगर किया जाता है spring.config.location, तो वे डिफ़ॉल्ट स्थानों को बदल देते हैं। उदाहरण के लिए, यदि spring.config.locationमान के साथ कॉन्फ़िगर किया गया है classpath:/custom-config/, file:./custom-config/, खोज क्रम निम्नलिखित हो जाता है:

  1. file:./custom-config/

  2. classpath:custom-config/

spring.config.locationअब यह सुनिश्चित करने का एक तरीका है कि किसी भी application.propertiesफ़ाइल को स्पष्ट रूप से निर्दिष्ट किया जाना चाहिए।
Uber JAR के लिए जो application.propertiesफाइलों को पैकेज करने के लिए नहीं हैं , बल्कि यह अच्छा है।

spring.config.locationस्प्रिंग बूट 2 का उपयोग करते समय पुराने व्यवहार को बनाए रखने के लिए आप spring.config.additional-locationइसके बजाय नई संपत्ति का उपयोग कर सकते हैं, फिर spring.config.locationभी प्रलेखन द्वारा बताए गए स्थानों को जोड़ता है :

वैकल्पिक रूप से, जब कस्टम कॉन्फ़िगरेशन स्थानों का उपयोग करके कॉन्फ़िगर किया जाता है spring.config.additional-location, तो उन्हें डिफ़ॉल्ट स्थानों के अतिरिक्त उपयोग किया जाता है।


प्रयोग में

इसलिए यह मानते हुए कि ओपी प्रश्न में, आपके पास निर्दिष्ट करने के लिए 2 बाहरी गुण फ़ाइल हैं और 1 गुण फ़ाइल uber जार में शामिल हैं।

आपके द्वारा निर्दिष्ट केवल कॉन्फ़िगरेशन फ़ाइलों का उपयोग करने के लिए:

-Dspring.config.location=classpath:/job1.properties,classpath:/job2.properties,classpath:/applications.properties   

डिफ़ॉल्ट स्थानों में इनसे विन्यास फाइल जोड़ने के लिए:

-Dspring.config.additional-location=classpath:/job1.properties,classpath:/job2.properties

classpath:/applications.properties अंतिम उदाहरण में आवश्यक नहीं है क्योंकि डिफ़ॉल्ट स्थानों में वह है और वह डिफ़ॉल्ट स्थान यहां अधिलेखित नहीं हैं बल्कि विस्तारित हैं।


आपका जवाब वास्तव में एक बात को छोड़कर पूरा हो गया है: यदि आपको बस निर्दिष्ट किया जाएगा तो स्प्रिंग बाहरी कॉन्फ़िगरेशन job1.properties को कहां मिलेगा: "classpath: /job1.properties"? आपने क्लासपैथ में अपनी निर्देशिका को बाहरी गुणों से कैसे जोड़ा?
ट्रिस्टन

@ ट्रिस्टन, मूल रूप से, वसंत application.propertiesसभी मापदंडों के साथ एक और ${file_name}.propertiesगुणों के आंशिक परिभाषित सेटों के साथ कई पढ़ सकता है । इसलिए, यदि आप @PropertySourceफ़ाइलों के लिए या अन्य मजबूत लिंक का उपयोग करते हैं, तो आप अन्य बाहरी फ़ाइल बना सकते हैं और उस गुण को ओवरराइड कर सकते हैं (उदाहरण के लिए: से classpath:file.properties)।
मिस्टर_जेस 15

23

प्रॉपर्टीहोल्डरकॉन्फिगिज़र पर एक नज़र डालें, मुझे एनोटेशन की तुलना में उपयोग करने के लिए स्पष्ट है।

जैसे

@Configuration
public class PropertiesConfiguration {


    @Bean
    public PropertyPlaceholderConfigurer properties() {
        final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
//        ppc.setIgnoreUnresolvablePlaceholders(true);
        ppc.setIgnoreResourceNotFound(true);

        final List<Resource> resourceLst = new ArrayList<Resource>();

        resourceLst.add(new ClassPathResource("myapp_base.properties"));
        resourceLst.add(new FileSystemResource("/etc/myapp/overriding.propertie"));
        resourceLst.add(new ClassPathResource("myapp_test.properties"));
        resourceLst.add(new ClassPathResource("myapp_developer_overrides.properties")); // for Developer debugging.

        ppc.setLocations(resourceLst.toArray(new Resource[]{}));

        return ppc;
    }

इस उत्तर के लिए आपका बहुत-बहुत धन्यवाद। क्या आप कृपया मुझे बता सकते हैं कि जिस परियोजना में बिना आधार XML फ़ाइल के अलग-अलग चीज़ों के लिए XML कॉन्फ़िगरेशन जैसी है, मैं उसे कैसे प्राप्त कर सकता हूँ? ऊपर दिए गए आपके उत्तर ने मुझे अन्य प्रोजेक्ट में मदद की जो एनोटेशन आधारित था। उसके लिए फिर से धन्यवाद।
चेतन

8

स्प्रिंग बूट का उपयोग करके यह एक सरल तरीका है

TestClass.java

@Configuration
@Profile("one")
@PropertySource("file:/{selected location}/app.properties")
public class TestClass {

    @Autowired
    Environment env;

    @Bean
    public boolean test() {
        System.out.println(env.getProperty("test.one"));
        return true;
    }
}

app.properties संदर्भ, अपने में चयनित स्थान

test.one = 1234

अपने वसंत बूट आवेदन

@SpringBootApplication

public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(testApplication.class, args);
    }
}

और पूर्वनिर्धारित application.properties संदर्भ

spring.profiles.active = one

आप जितने चाहें उतने कॉन्फ़िगरेशन क्लास लिख सकते हैं और बस स्प्रिंग.प्रोफ़ाइल.सक्रिय करके उन्हें निष्क्रिय / निष्क्रिय कर सकते हैं। प्रोफ़ाइल का नाम / नाम {अल्पविराम द्वारा अलग किया गया}

जैसा कि आप देख सकते हैं कि वसंत बूट बहुत अच्छा है, बस कुछ समय के लिए परिचित होना आवश्यक है, यह ध्यान देने योग्य है कि आप अपने खेतों पर भी @Value का उपयोग कर सकते हैं

@Value("${test.one}")
String str;

7

मुझे भी यही समस्या थी। मैं स्प्रिंग बूट application.properties का पता लगाने के समान बाहरी फ़ाइल के साथ स्टार्टअप पर आंतरिक कॉन्फ़िगरेशन फ़ाइल को अधिलेखित करने की क्षमता चाहता था। मेरे मामले में यह एक user.properties फ़ाइल है जहाँ मेरे अनुप्रयोग उपयोगकर्ता संग्रहीत हैं।

मेरी आवश्यकताएं:

फ़ाइल को निम्न स्थानों से लोड करें (इस क्रम में)

  1. वर्गपथ
  2. वर्तमान निर्देशिका का ए / कॉन्फिगर उपखंड।
  3. वर्तमान निर्देशिका
  4. स्टार्टअप पर कमांड लाइन पैरामीटर द्वारा दी गई निर्देशिका या फ़ाइल स्थान से

मैं निम्नलिखित समाधान के साथ आया:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Properties;

import static java.util.Arrays.stream;

@Configuration
public class PropertiesConfig {

    private static final Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);

    private final static String PROPERTIES_FILENAME = "user.properties";

    @Value("${properties.location:}")
    private String propertiesLocation;

    @Bean
    Properties userProperties() throws IOException {
        final Resource[] possiblePropertiesResources = {
                new ClassPathResource(PROPERTIES_FILENAME),
                new PathResource("config/" + PROPERTIES_FILENAME),
                new PathResource(PROPERTIES_FILENAME),
                new PathResource(getCustomPath())
        };
        // Find the last existing properties location to emulate spring boot application.properties discovery
        final Resource propertiesResource = stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .reduce((previous, current) -> current)
                .get();
        final Properties userProperties = new Properties();

        userProperties.load(propertiesResource.getInputStream());

        LOG.info("Using {} as user resource", propertiesResource);

        return userProperties;
    }

    private String getCustomPath() {
        return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + PROPERTIES_FILENAME;
    }

}

अब एप्लिकेशन क्लासपथ संसाधन का उपयोग करता है, लेकिन अन्य दिए गए स्थानों पर भी संसाधन की जांच करता है। जो अंतिम संसाधन मौजूद है, उसे उठाया और इस्तेमाल किया जाएगा। मैं अपने ऐप को java -jar myapp.jar --properties.location = / निर्देशिका / myproperties.properties के साथ शुरू करने में सक्षम हूं जो एक गुण स्थान का उपयोग करता है जो मेरी नाव को तैरता है।

यहां एक महत्वपूर्ण विवरण: गुण सेट नहीं होने पर त्रुटियों से बचने के लिए @Value एनोटेशन में properties.location के लिए डिफ़ॉल्ट मान के रूप में एक खाली स्ट्रिंग का उपयोग करें।

Properties.location के लिए कन्वेंशन है: Properties.location के रूप में किसी निर्देशिका फ़ाइल के लिए निर्देशिका या पथ का उपयोग करें।

यदि आप केवल विशिष्ट गुणों को ओवरराइड करना चाहते हैं, तो PropertiesIactoryBean के साथ setIgnoreResourceNotFound (सही) का उपयोग संसाधन सरणी के साथ स्थानों के रूप में सेट किया जा सकता है।

मुझे यकीन है कि यह समाधान कई फ़ाइलों को संभालने के लिए बढ़ाया जा सकता है ...

संपादित करें

यहाँ कई फ़ाइलों के लिए मेरा समाधान :) पहले की तरह, यह एक PropertiesFactoryBean के साथ जोड़ा जा सकता है।

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;

@Configuration
class PropertiesConfig {

    private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);
    private final static String[] PROPERTIES_FILENAMES = {"job1.properties", "job2.properties", "job3.properties"};

    @Value("${properties.location:}")
    private String propertiesLocation;

    @Bean
    Map<String, Properties> myProperties() {
        return stream(PROPERTIES_FILENAMES)
                .collect(toMap(filename -> filename, this::loadProperties));
    }

    private Properties loadProperties(final String filename) {
        final Resource[] possiblePropertiesResources = {
                new ClassPathResource(filename),
                new PathResource("config/" + filename),
                new PathResource(filename),
                new PathResource(getCustomPath(filename))
        };
        final Resource resource = stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .reduce((previous, current) -> current)
                .get();
        final Properties properties = new Properties();

        try {
            properties.load(resource.getInputStream());
        } catch(final IOException exception) {
            throw new RuntimeException(exception);
        }

        LOG.info("Using {} as user resource", resource);

        return properties;
    }

    private String getCustomPath(final String filename) {
        return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + filename;
    }

}

अच्छा काम है। जैसे कि java8 का निर्माण! किसी भी तरह मैं का उपयोग नहीं कर सकते हैं कि मैं एक ही नहीं कई गुण सेम की जरूरत है। यदि आप मेरे ईडीआईटीएस को देखते हैं तो मेरा वर्कअराउंड मेरे उपयोग के मामले के समान और साफ-सुथरा है।
निर

मैंने कई फाइलों के लिए एक संस्करण पोस्ट किया, सिर्फ पूर्णता के लिए;)
mxsb

6

वसंत बूट हमें विभिन्न वातावरणों के लिए लिखने के लिए अलग-अलग प्रोफाइल लिखने की अनुमति देता है, उदाहरण के लिए हमारे पास उत्पादन, क्यूए और स्थानीय वातावरण के लिए अलग-अलग गुण फाइलें हो सकती हैं।

Application-local.properties मेरे स्थानीय मशीन के अनुसार विन्यास के साथ फ़ाइल है

spring.profiles.active=local

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=users
spring.data.mongodb.username=humble_freak
spring.data.mongodb.password=freakone

spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672

rabbitmq.publish=true

इसी तरह, हम application-prod.properties और application-qa.properties को जितनी चाहें उतनी प्रॉपर्टी फाइल में लिख सकते हैं

फिर विभिन्न वातावरणों के लिए आवेदन शुरू करने के लिए कुछ स्क्रिप्ट लिखें, उदाहरण के लिए

mvn spring-boot:run -Drun.profiles=local
mvn spring-boot:run -Drun.profiles=qa
mvn spring-boot:run -Drun.profiles=prod

5

मैं सिर्फ इस के लिए एक समान समस्या थी और अंत में कारण का पता लगाया: application.properties फ़ाइल में गलत स्वामित्व और rwx विशेषताएँ थीं। इसलिए जब टॉमकैट ने अप्लिकेशन शुरू किया। प्रोपराइटीज़ फ़ाइल सही स्थान पर थी, लेकिन किसी अन्य उपयोगकर्ता के स्वामित्व में थी:

$ chmod 766 application.properties

$ chown tomcat application.properties

मुझे लगता है कि मुझे भी ऐसी ही समस्या है। मैंने ऑप्ट फ़ोल्डर में टॉमकैट स्थापित किया है। आपने अपनी एप्लिकेशन फ़ाइल कहां रखी है? क्या मुझे फ़ोल्डर विशेषताओं को भी बदलना चाहिए?
आकिन ५

3

@Mxsb समाधान का एक संशोधित संस्करण जो हमें कई फ़ाइलों को परिभाषित करने की अनुमति देता है और मेरे मामले में ये yml फाइलें हैं।

अपने एप्लिकेशन- dev.yml में, मैंने यह कॉन्फिगर जोड़ा है जो मुझे उन सभी yml को इंजेक्ट करने की अनुमति देता है जिनमें -dev.yml है। यह विशिष्ट फ़ाइलों की एक सूची भी हो सकती है। "Classpath: /test/test.yml,classpath: /test2/test.yml"

application:
  properties:
    locations: "classpath*:/**/*-dev.yml"

यह गुण मानचित्र प्राप्त करने में मदद करता है।

@Configuration

public class PropertiesConfig {

private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);

@Value("${application.properties.locations}")
private String[] locations;

@Autowired
private ResourceLoader rl;

@Bean
Map<String, Properties> myProperties() {
    return stream(locations)
            .collect(toMap(filename -> filename, this::loadProperties));
}

private Properties loadProperties(final String filename) {

    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    try {
        final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename);
        final Properties properties = new Properties();
        stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .map(resource1 -> {
                    try {
                        return loader.load(resource1.getFilename(), resource1);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }).flatMap(l -> l.stream())
                .forEach(propertySource -> {
                    Map source = ((MapPropertySource) propertySource).getSource();
                    properties.putAll(source);
                });

        return properties;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
}

हालांकि, अगर मेरे मामले में पसंद है, तो मैं प्रत्येक प्रोफाइल के लिए yml फ़ाइलों को विभाजित करना और उन्हें लोड करना और सेम इनिशियलाइज़ेशन से पहले सीधे वसंत कॉन्फ़िगरेशन में इंजेक्ट करना चाहता था।

config
    - application.yml
    - application-dev.yml
    - application-prod.yml
management
    - management-dev.yml
    - management-prod.yml

... तुम्हें नया तरीका मिल गया है

घटक थोड़ा अलग है

@Component
public class PropertiesConfigurer extends     PropertySourcesPlaceholderConfigurer
    implements EnvironmentAware, InitializingBean {

private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfigurer.class);

private String[] locations;

@Autowired
private ResourceLoader rl;
private Environment environment;

@Override
public void setEnvironment(Environment environment) {
    // save off Environment for later use
    this.environment = environment;
    super.setEnvironment(environment);
}

@Override
public void afterPropertiesSet() throws Exception {
    // Copy property sources to Environment
    MutablePropertySources envPropSources = ((ConfigurableEnvironment) environment).getPropertySources();
    envPropSources.forEach(propertySource -> {
        if (propertySource.containsProperty("application.properties.locations")) {
            locations = ((String) propertySource.getProperty("application.properties.locations")).split(",");
            stream(locations).forEach(filename -> loadProperties(filename).forEach(source ->{
                envPropSources.addFirst(source);
            }));
        }
    });
}


private List<PropertySource> loadProperties(final String filename) {
    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    try {
        final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename);
        final Properties properties = new Properties();
        return stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .map(resource1 -> {
                    try {
                        return loader.load(resource1.getFilename(), resource1);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }).flatMap(l -> l.stream())
                .collect(Collectors.toList());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

}


3

यदि आप अपनी एप्लिकेशन में निर्दिष्ट मानों को ओवरराइड करना चाहते हैं। फाइल में आप अपना एप्लिकेशन चलाते समय अपनी सक्रिय प्रोफ़ाइल को बदल सकते हैं और प्रोफ़ाइल के लिए एप्लिकेशन गुण फ़ाइल बना सकते हैं। इसलिए, उदाहरण के लिए, चलिए सक्रिय प्रोफ़ाइल "ओवरराइड" को निर्दिष्ट करते हैं और फिर, मान लेते हैं कि आपने अपनी नई एप्लिकेशन प्रॉपर्टीज़ फ़ाइल बनाई है, जिसका नाम "application-override.properties" / tmp है, तो आप चला सकते हैं।

java -jar yourApp.jar --spring.profiles.active="override" --spring.config.location="file:/tmp/,classpath:/" 

स्प्रिंग.कॉन्फिग.लोकेशन के तहत निष्ठित मूल्यों का मूल्यांकन रिवर्स ऑर्डर में किया जाता है। इसलिए, मेरे उदाहरण में, क्लासपेट का मूल्यांकन पहले किया जाता है, फिर फ़ाइल मान।

यदि जार फ़ाइल और "application-override.properties" फ़ाइल वर्तमान निर्देशिका में हैं तो आप वास्तव में बस उपयोग कर सकते हैं

java -jar yourApp.jar --spring.profiles.active="override"

चूंकि स्प्रिंग बूट में आपके लिए गुण फ़ाइल मिल जाएगी


1
यह वसंत को आपकी सक्रिय प्रोफ़ाइल के रूप में "ओवरराइड" प्रोफ़ाइल का उपयोग करने के लिए बताएगा; यह वास्तव में application.yml या application.properties फ़ाइल में निर्दिष्ट मूल्य को पार कर जाएगा
acaruci

यह किसी भी कॉन्फ़िगर फ़ाइल के लिए फ़ोल्डर के अंदर दिखेगा। मेरे मामले में .ymal या .properties में मैं केवल एप्लिकेशन-प्रोफाइल डाल देता हूं। फिर यह सही ढंग से लेता है, धन्यवाद @acaruci यह एक अच्छी यात्रा थी
अहमद सलेम

0

मैंने इसका अनुसरण करने के लिए एक उपयोगी पैटर्न पाया है:

@RunWith(SpringRunner)
@SpringBootTest(classes = [ TestConfiguration, MyApplication ],
        properties = [
                "spring.config.name=application-MyTest_LowerImportance,application-MyTest_MostImportant"
                ,"debug=true", "trace=true"
        ]
)

यहाँ हम "application-MyTest_LowerImportance.yml" का उपयोग करने के लिए "application.yml" के उपयोग को ओवरराइड करते हैं और "Application-MyTest_MostImportant.yml"
(स्प्रिंग भी .properties फ़ाइलों की तलाश करेंगे)।

अतिरिक्त बोनस के रूप में शामिल डिबग और ट्रेस सेटिंग्स एक अलग लाइन पर हैं ताकि आप आवश्यकता पड़ने पर उन्हें टिप्पणी कर सकें;]

डीबग / ट्रेस अविश्वसनीय रूप से उपयोगी होते हैं क्योंकि स्प्रिंग उन सभी फ़ाइलों के नामों को डंप कर देगा जो इसे लोड करती हैं और जिन्हें वे लोड करने की कोशिश करते हैं।
आप रनटाइम में कंसोल में इस तरह की लाइनें देखेंगे:

TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.properties' (file:./config/application-MyTest_MostImportant.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.xml' (file:./config/application-MyTest_MostImportant.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.yml' (file:./config/application-MyTest_MostImportant.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.yaml' (file:./config/application-MyTest_MostImportant.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.properties' (file:./config/application-MyTest_LowerImportance.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.xml' (file:./config/application-MyTest_LowerImportance.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.yml' (file:./config/application-MyTest_LowerImportance.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.yaml' (file:./config/application-MyTest_LowerImportance.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.properties' (file:./application-MyTest_MostImportant.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.xml' (file:./application-MyTest_MostImportant.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.yml' (file:./application-MyTest_MostImportant.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.yaml' (file:./application-MyTest_MostImportant.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.properties' (file:./application-MyTest_LowerImportance.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.xml' (file:./application-MyTest_LowerImportance.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.yml' (file:./application-MyTest_LowerImportance.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.yaml' (file:./application-MyTest_LowerImportance.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.xml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.xml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.xml' resource not found
DEBUG 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_MostImportant.yml' (classpath:/application-MyTest_MostImportant.yml)
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.xml' resource not found
DEBUG 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_LowerImportance.yml' (classpath:/application-MyTest_LowerImportance.yml)
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant-test.properties' (file:./config/application-MyTest_MostImportant-test.properties) resource not found

-1

जब मैंने यह पता लगाने की कोशिश की तो मैं बहुत सारे मुद्दों में भाग गया। यहाँ मेरा सेटअप है,

देव एनव: विंडोज 10, जावा: १._.०_२५, स्प्रिंग बूट: २.०.३. कृपया, वसंत: ५.०. 10।

मैंने पाया कि वसंत "अवधारणा के लिए संवेदनशील चूक" अवधारणा के साथ चिपका हुआ है। यह आपके लिए क्या है, आपको अपनी सभी संपत्ति फाइलों को अपनी युद्ध फाइल के हिस्से के रूप में रखना है। एक बार वहाँ जाने के बाद, आप बाहरी संपत्ति फ़ाइलों को इंगित करने के लिए "--spring.config.additional-location" कमांड लाइन संपत्ति का उपयोग करके उन्हें ओवरराइड कर सकते हैं। लेकिन यह काम नहीं करेगा अगर संपत्ति फाइलें मूल युद्ध फ़ाइल का हिस्सा नहीं हैं।

डेमो कोड: https://github.com/gselvara/spring-boot-property-demo/tree/master

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.