2014-07-23 11 views
46

से नक्शा इंजेक्षन मैं निम्नलिखित application.yml के साथ एक Spring Boot अनुप्रयोग है - here से मूल रूप से लिया:स्प्रिंग बूट - application.yml

info: 
    build: 
     artifact: ${project.artifactId} 
     name: ${project.name} 
     description: ${project.description} 
     version: ${project.version} 

मैं विशेष मूल्यों इंजेक्षन कर सकते हैं, उदाहरण के लिए

@Value("${info.build.artifact}") String value 

मैं करूंगा चाहते हैं, हालांकि, पूरे नक्शा, इस तरह अर्थात कुछ सुई:

@Value("${info}") Map<String, Object> info 

कि (या कुछ इसी तरह) संभव है? जाहिर है, मैं सीधे यम लोड कर सकता हूं, लेकिन सोच रहा था कि वसंत द्वारा पहले से समर्थित कुछ है या नहीं।

import java.util.HashMap; 
import java.util.Map; 

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 
import org.springframework.boot.context.properties.ConfigurationProperties; 
import org.springframework.boot.context.properties.EnableConfigurationProperties; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 

@Configuration 
@EnableAutoConfiguration 
@EnableConfigurationProperties 
public class MapBindingSample { 

    public static void main(String[] args) throws Exception { 
     System.out.println(SpringApplication.run(MapBindingSample.class, args) 
       .getBean(Test.class).getInfo()); 
    } 

    @Bean 
    @ConfigurationProperties 
    public Test test() { 
     return new Test(); 
    } 

    public static class Test { 

     private Map<String, Object> info = new HashMap<String, Object>(); 

     public Map<String, Object> getInfo() { 
      return this.info; 
     } 
    } 
} 

प्रश्न में YAML के साथ इस रनिंग पैदा करता है:

उत्तर

34

आप एक नक्शे के हो सकता है @ConfigurationProperties का उपयोग कर इंजेक्शन

{build={artifact=${project.artifactId}, version=${project.version}, name=${project.name}, description=${project.description}}} 

वहाँ एक उपसर्ग की स्थापना कैसे लापता गुण को नियंत्रित करने के लिए विभिन्न विकल्प हैं संभाला जाता है, आदि। अधिक जानकारी के लिए javadoc देखें।

+0

धन्यवाद एंडी - इस उम्मीद के रूप में काम करता है। दिलचस्प है कि यह एक अतिरिक्त कक्षा के बिना काम नहीं करता है - यानी आप कुछ कारणों से 'MapBindingSample' के भीतर 'जानकारी' मानचित्र नहीं डाल सकते हैं (शायद क्योंकि इसका उपयोग 'SpringApplication.run' कॉल' में ऐप चलाने के लिए किया जा रहा है)। –

+0

क्या उप-मानचित्र इंजेक्ट करने का कोई तरीका है? जैसे उपर्युक्त मानचित्र से 'जानकारी' के बजाय 'info.build' इंजेक्ट करें? –

+0

हां। @ कॉन्फ़िगरेशनप्रॉपर्टीज पर उपसर्ग को जानकारी पर सेट करें और फिर getBuild() –

12

मैं आज भी एक ही समस्या में भाग गया, लेकिन दुर्भाग्य से एंडी का समाधान मेरे लिए काम नहीं करता था। वसंत बूट 1.2.1 में। कृपया यह भी आसान है, लेकिन आपको कुछ चीजों से अवगत होना चाहिए।

यहाँ मेरी application.yml से दिलचस्प हिस्सा है:

oauth: 
    providers: 
    google: 
    api: org.scribe.builder.api.Google2Api 
    key: api_key 
    secret: api_secret 
    callback: http://callback.your.host/oauth/google 

providers मानचित्र केवल एक नक्शा प्रवेश होता है, मेरा लक्ष्य अन्य OAuth प्रदाताओं के लिए गतिशील विन्यास प्रदान करना है। मैं इस मानचित्र को ऐसी सेवा में इंजेक्ट करना चाहता हूं जो इस yaml फ़ाइल में प्रदान की गई कॉन्फ़िगरेशन के आधार पर सेवाओं को प्रारंभ करे। मेरे प्रारंभिक कार्यान्वयन था:

@Service 
@ConfigurationProperties(prefix = 'oauth') 
class OAuth2ProvidersService implements InitializingBean { 

    private Map<String, Map<String, String>> providers = [:] 

    @Override 
    void afterPropertiesSet() throws Exception { 
     initialize() 
    } 

    private void initialize() { 
     //.... 
    } 
} 

आवेदन शुरू करने के बाद, OAuth2ProvidersService में providers नक्शा आरंभ नहीं किया गया था। मैंने एंडी द्वारा सुझाए गए समाधान की कोशिश की, लेकिन यह भी काम नहीं किया। मैं उस एप्लिकेशन में ग्रोवी का उपयोग करता हूं, इसलिए मैंने private को निकालने का निर्णय लिया और ग्रोवी गेटटर और सेटर उत्पन्न करने दिया। तो मेरा कोड इस तरह दिखता था:

@Service 
@ConfigurationProperties(prefix = 'oauth') 
class OAuth2ProvidersService implements InitializingBean { 

    Map<String, Map<String, String>> providers = [:] 

    @Override 
    void afterPropertiesSet() throws Exception { 
     initialize() 
    } 

    private void initialize() { 
     //.... 
    } 
} 

उस छोटे बदलाव के बाद सबकुछ काम करता था।

हालांकि एक ऐसी चीज है जो उल्लेखनीय हो सकती है। इसे काम करने के बाद मैंने इस क्षेत्र को private बनाने और सेटटर विधि में सीधे तर्क प्रकार के साथ सेटर प्रदान करने का निर्णय लिया। दुर्भाग्यवश यह काम नहीं करेगा। यह संदेश के साथ org.springframework.beans.NotWritablePropertyException कारण बनता है:

Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Cannot access indexed value in property referenced in indexed property path 'providers[google]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Bean property 'providers[google]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter? 

को ध्यान में रखें कि अगर आप अपने स्प्रिंग बूट आवेदन में ग्रूवी उपयोग कर रहे हैं।

53

नीचे समाधान @ एंडी विल्किन्सन के समाधान के लिए एक शॉर्टेंड है, सिवाय इसके कि इसे एक अलग वर्ग या @Bean एनोटेटेड विधि पर उपयोग करने की आवश्यकता नहीं है।

application.yml:

input: 
    name: raja 
    age: 12 
    somedata: 
    abcd: 1 
    bcbd: 2 
    cdbd: 3 

SomeComponent.java:

@Component 
@EnableConfigurationProperties 
@ConfigurationProperties(prefix = "input") 
class SomeComponent { 

    @Value("${input.name}") 
    private String name; 

    @Value("${input.age}") 
    private Integer age; 

    private HashMap<String, Integer> somedata; 

    public HashMap<String, Integer> getSomedata() { 
     return somedata; 
    } 

    public void setSomedata(HashMap<String, Integer> somedata) { 
     this.somedata = somedata; 
    } 

} 

हम कर सकते हैं क्लब दोनों @Value एनोटेशन और @ConfigurationProperties, कोई समस्या नहीं। लेकिन गेटर्स और सेटर्स महत्वपूर्ण हैं और @EnableConfigurationProperties को काम करने के लिए @ConfigurationProperties होना आवश्यक है।

मैंने @Szymon Stepniak द्वारा प्रदान किए गए ग्रोवी समाधान से इस विचार को आजमाया, सोचा कि यह किसी के लिए उपयोगी होगा।

+6

पूछने के लिए एक नया प्रश्न बेहतर स्थान होगा! मैंने वसंत बूट 1.3.1 का उपयोग किया, मेरे मामले में मुझे पाया गया कि '@ सक्षम कॉन्फ़िगरेशनप्रॉपर्टीज' – zhuguowei

+1

बहुत उपयोगी नहीं है। यह सबसे अच्छा जवाब है :) – sustainablepace

+0

मुझे इस उत्तर का उपयोग करते समय 'अमान्य वर्ण निरंतर' त्रुटि मिलती है। क्या आप बदल सकते हैं: @ कॉन्फ़िगरेशनप्रॉपर्टीज (उपसर्ग = 'इनपुट') इस त्रुटि को रोकने के लिए डबल कोट्स का उपयोग करने के लिए। –

3
foo.bars.one.counter=1 
foo.bars.one.active=false 
foo.bars[two].id=IdOfBarWithKeyTwo 

public class Foo { 

    private Map<String, Bar> bars = new HashMap<>(); 

    public Map<String, Bar> getBars() { .... } 
} 

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding

+3

स्टैक ओवरफ़्लो में आपका स्वागत कर सकते हैं! हालांकि यह कोड स्निपेट प्रश्न हल कर सकता है, [एक स्पष्टीकरण सहित] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है।याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और वे लोग आपके कोड सुझाव के कारणों को नहीं जानते हैं। –