স্প্রিং বুট - প্রয়োগ.মিল থেকে মানচিত্র ইনজেক্ট করুন in


103

আমি একটি আছে স্প্রিং বুট নিম্নলিখিত সঙ্গে আবেদন 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

এটি কি (বা অনুরূপ কিছু) সম্ভব? স্পষ্টতই, আমি সরাসরি ইয়ামালটি লোড করতে পারি, তবে ভাবছিলাম যে স্প্রিংয়ের দ্বারা ইতিমধ্যে কিছু সমর্থিত আছে কিনা।

উত্তর:


71

আপনি ব্যবহার করে একটি মানচিত্র ইনজেকশনে রাখতে পারেন @ConfigurationProperties:

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;
        }
    }
}

প্রশ্নটিতে ইয়ামল দিয়ে এটিকে চালানো:

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

একটি উপসর্গ সেট করার জন্য, কীভাবে নিখোঁজ সম্পত্তি পরিচালনা করা হয় তা নিয়ন্ত্রণ করার জন্য বিভিন্ন বিকল্প রয়েছে etc. আরও তথ্যের জন্য জাভাদোকটি দেখুন ।


ধন্যবাদ অ্যান্ডি - এটি প্রত্যাশার মতো কাজ করে। আকর্ষণীয় বিষয় এটি অতিরিক্ত শ্রেণি ব্যতীত কাজ করে না - যেমন আপনি কোনও কারণে infoমানচিত্রটি ভিতরে রাখতে পারবেন না MapBindingSample(সম্ভবত এটি অ্যাপটিতে SpringApplication.runকল চালানোর জন্য ব্যবহৃত হচ্ছে )।
লিভান্ট

4
একটি উপ-মানচিত্র ইনজেকশন উপায় আছে? উদাহরণস্বরূপ উপরের মানচিত্রের info.buildপরিবর্তে ইনজেকশন info?
লিভান্ট 21

4
হ্যাঁ. তথ্যের জন্য @ কনফিগারেশনপ্রাপ্তির উপসর্গটি সেট করুন এবং তারপরে getBuild () নামে একটি পদ্ধতি দিয়ে getInfo () প্রতিস্থাপনের পরীক্ষাটি আপডেট করুন
অ্যান্ডি উইলকিনসন

সুন্দর, ধন্যবাদ অ্যান্ডি, কবজির মতো কাজ করেছে! আরও একটি জিনিস - সেট করার সময় locations( ymlডিফল্ট পরিবর্তে অন্য ফাইল থেকে বৈশিষ্ট্যগুলি পেতে application.yml) @ConfigurationPropertiesএটি কাজ করে , এটির পরিবর্তে স্থানধারকগুলি প্রতিস্থাপনের ফলস্বরূপ ঘটে। উদাহরণস্বরূপ, যদি আপনার কোনও সিস্টেমের সম্পত্তি project.version=123সেট থাকে তবে আপনি উত্তরে যে উদাহরণটি দিয়েছেন তা ফিরে আসবে version=123, যখন locationsসেটি সেট করার পরে ফিরে আসবে project.version=${project.version}। আপনি কি জানেন যে এখানে কিছু ধরণের সীমাবদ্ধতা রয়েছে কিনা?
লিভান্ট

এটি একটি সীমাবদ্ধতা। আপনি যখন কোনও কাস্টম অবস্থান ব্যবহার করেন তখন স্থানধারক প্রতিস্থাপন সম্পাদনের জন্য আমি একটি সমস্যা ( github.com/spring-projects/spring-boot/issues/1301 ) খুলেছি
অ্যান্ডি উইলকিনসন

113

সমাধানের নীচে @ অ্যান্ডি উইলকিনসনের সমাধানের জন্য একটি শর্টহ্যান্ড রয়েছে, এ ছাড়া এটি পৃথক শ্রেণি ব্যবহার করতে হবে না বা কোনও @Beanটীকাগত পদ্ধতিতে নেই।

প্রয়োগ.আইএমএল:

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

সামকোম্পোনেন্ট.জভা:

@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

আমি @ সায়মন স্টেপনিয়াক দ্বারা সরবরাহিত গ্রোভি সলিউশন থেকে এই ধারণাটি চেষ্টা করেছিলাম, ভেবেছিলাম এটি কারও পক্ষে কার্যকর হবে।


11
ধন্যবাদ! আমি স্প্রিং বুট 1.3.1 ব্যবহার করেছি, আমার ক্ষেত্রে আমার পাওয়া দরকার নেই@EnableConfigurationProperties
zhuguowei

এই উত্তরটি ব্যবহার করার সময় আমি একটি 'অবৈধ চরিত্র ধ্রুবক' ত্রুটি পেয়েছি। আপনি কি পরিবর্তন করতে পারবেন: @ কনফিগারেশনপ্রোপার্টি (উপসর্গ = 'ইনপুট') এই ত্রুটি রোধ করতে ডাবল উদ্ধৃতি ব্যবহার করতে।
অ্যান্টন র‌্যান্ড

10
ভাল উত্তর, কিন্তু @ ভ্যালু টিকা প্রয়োজন নেই।
রবিন

4
ডামি গেটর এবং সেটার লেখার পরিবর্তে আপনি লম্বোক টীকা @ সেটার (অ্যাক্সেসলিভেল.পাবলিক) এবং @ গেটার (অ্যাক্সেসলিভেল পাবলিক) ব্যবহার করতে পারেন
রিজকিট

জেনিয়াস নোট করুন যে কনফিগারেশনটিও নেস্ট করা যেতে পারে: মানচিত্র <স্ট্রিং, মানচিত্র <স্ট্রিং, স্ট্রিং >>
ম্যাথ এন্ড্রে-বটন্ড

16

আমি আজ একই সমস্যায় পড়েছি, তবে দুর্ভাগ্যক্রমে অ্যান্ডির সমাধান আমার পক্ষে কার্যকর হয়নি। স্প্রিং বুটে 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 সরবরাহকারীদের জন্য ডায়নামিক কনফিগারেশন সরবরাহ করা। আমি এই মানচিত্রটিকে এমন পরিষেবাতে ইনজেকশন করতে চাই যা এই ইয়ামল ফাইলে প্রদত্ত কনফিগারেশনের উপর ভিত্তি করে পরিষেবাগুলি সূচনা করবে। আমার প্রাথমিক বাস্তবায়নটি ছিল:

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

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

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

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

অ্যাপ্লিকেশন শুরু করার পরে, providersমানচিত্রটি OAuth2ProvidersServiceআরম্ভ করা হয়নি। আমি অ্যান্ডির প্রস্তাবিত সমাধানটি চেষ্টা করেছিলাম, তবে এটি কার্যকর হয়নি। আমি সেই অ্যাপ্লিকেশনটিতে গ্রোভিকে ব্যবহার করি , তাই আমি 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?

আপনি যদি আপনার স্প্রিং বুট অ্যাপ্লিকেশনটিতে গ্রোভি ব্যবহার করছেন তবে এটি মনে রাখবেন।


15

কনফিগারেশন থেকে মানচিত্র পুনরুদ্ধার করতে আপনার কনফিগারেশন ক্লাসের প্রয়োজন হবে। দুর্ভাগ্যক্রমে, ভ্যালু টীকাটি কৌশলটি করবে না।

প্রয়োগ.আইএমএল

entries:
  map:
     key1: value1
     key2: value2

কনফিগারেশন ক্লাস:

@Configuration
@ConfigurationProperties("entries")
@Getter
@Setter
 public static class MyConfig {
     private Map<String, String> map;
 }

উপরের সমাধানটি পরীক্ষিত সংস্করণটি ২.১.০ সংস্করণের বিপরীতে কাজ করে
তুগ্রুল ASLAN

6

টানার জন্য সমাধান ম্যাপ ব্যবহার @value থেকে application.yml সম্পত্তি হিসেবে কোডেড একাধিক লাইন

application.yml

other-prop: just for demo 

my-map-property-name: "{\
         key1: \"ANY String Value here\", \  
         key2: \"any number of items\" , \ 
         key3: \"Note the Last item does not have comma\" \
         }"

other-prop2: just for demo 2 

এখানে আমাদের মানচিত্রের সম্পত্তি "আমার-মানচিত্র-সম্পত্তি-নাম" এর মান JSON ফর্ম্যাটে একটি স্ট্রিংয়ের মধ্যে সংরক্ষণ করা হয়েছে এবং আমরা লাইনটির শেষে \ ব্যবহার করে মাল্টলাইন অর্জন করেছি

myJavaClass.java

import org.springframework.beans.factory.annotation.Value;

public class myJavaClass {

@Value("#{${my-map-property-name}}") 
private Map<String,String> myMap;

public void someRandomMethod (){
    if(myMap.containsKey("key1")) {
            //todo...
    } }

}

আরও ব্যাখ্যা

  • \ Yaml এটা একাধিক লাইন মধ্যে স্ট্রিং ভঙ্গ করতে ব্যবহৃত হয়

  • \ " Yaml স্ট্রিং (Quote) পলায়নের charater হয়"

  • {কী: মান y ইয়ামলে জেএসএন যা @ ভ্যালু দ্বারা মানচিত্রে রূপান্তরিত হবে

  • # {} এটি স্পেল এক্সপ্রেশন এবং @ ভ্যালুতে জসন ইন মানচিত্র বা অ্যারে / তালিকা রেফারেন্স রূপান্তর করতে ব্যবহার করা যেতে পারে

একটি বসন্ত বুট প্রকল্পে পরীক্ষিত


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- বুট- কনফিগারেশন- বাইন্ডিং


7
স্ট্যাক ওভারফ্লোতে স্বাগতম! এই কোড স্নিপেট একটি ব্যাখ্যা সহ প্রশ্নটি সমাধান করতে পারে, যদিও সত্যিই আপনার পোস্টের মান উন্নত করতে সহায়তা করে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, এবং সেই লোকেরা আপনার কোড পরামর্শের কারণগুলি জানেন না।
স্কট ওয়েলডন

যদিও উইকের লিঙ্কটি মূল্যবান। ব্যাখ্যাটি github.com/spring-projects/spring-boot/wiki/…
dschulten

0

আপনি অতিরিক্ত কাঠামো এড়াতে চাইলে আপনি এটিকে আরও সহজ করে তুলতে পারেন।

service:
  mappings:
    key1: value1
    key2: value2
@Configuration
@EnableConfigurationProperties
public class ServiceConfigurationProperties {

  @Bean
  @ConfigurationProperties(prefix = "service.mappings")
  public Map<String, String> serviceMappings() {
    return new HashMap<>();
  }

}

এবং তারপরে এটি যথারীতি ব্যবহার করুন, উদাহরণস্বরূপ কোনও কনস্ট্রাক্টরের সাথে:

public class Foo {

  private final Map<String, String> serviceMappings;

  public Foo(Map<String, String> serviceMappings) {
    this.serviceMappings = serviceMappings;
  }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.