programing

java 속성 파일의 HashMap을 Spring @Value로 채우는 방법

subpage 2023. 10. 26. 21:04
반응형

java 속성 파일의 HashMap을 Spring @Value로 채우는 방법

Spring @Value를 사용하여 속성 파일의 값을 HashMap에 매핑할 수 있습니까?

현재 제가 가지고 있는 것은 이런 것이고, 하나의 값을 매핑하는 것은 문제가 되지 않습니다.하지만 해시맵 만료 시 사용자 지정 값을 매핑해야 합니다.이런 일이 가능한가요?

@Service
@PropertySource(value = "classpath:my_service.properties")
public class SomeServiceImpl implements SomeService {


    @Value("#{conf['service.cache']}")
    private final boolean useCache = false;

    @Value("#{conf['service.expiration.[<custom name>]']}")
    private final HashMap<String, String> expirations = new HashMap<String, String>();

속성 파일: 'my_service.properties'

service.cache=true
service.expiration.name1=100
service.expiration.name2=20

이 키와 같이 매핑 가능한가요: value set

  • name1 = 100

  • name2 = 20

SPEL json과 같은 구문을 사용하여 속성 파일에 간단한 맵이나 목록의 맵을 작성할 수 있습니다.

simple.map={'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}

map.of.list={\
  'KEY1': {'value1','value2'}, \
  'KEY2': {'value3','value4'}, \
  'KEY3': {'value5'} \
 }

사용했습니다.\가독성을 높이기 위해 다중 줄 속성을 사용합니다.

그런 다음 자바에서는 다음과 같이 자동으로 액세스하고 파싱할 수 있습니다.@Value이것처럼.

@Value("#{${simple.map}}")
Map<String, String> simpleMap;

@Value("#{${map.of.list}}")
Map<String, List<String>> mapOfList;

여기에${simple.map},@Value속성 파일에서 다음 String을 가져옵니다.

"{'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}"

그다음에 마치 안감이 들어간 것처럼 평가가 됩니다.

@Value("#{{'KEY1': 'value1', 'KEY2': 'value3', 'KEY3': 'value5'}}")

자세한 내용은 공식 문서에서 확인하실 수 있습니다.

Spring @Value를 사용하여 속성 파일의 값을 HashMap에 매핑할 수 있습니까?

네.코드와 스펠의 도움을 조금 받았죠

먼저 스프링 빈에 대한 싱글을 생각해 보십시오. (스캔해야 합니다.)

@Component("PropertySplitter")
public class PropertySplitter {

    /**
     * Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2
     */
    public Map<String, String> map(String property) {
        return this.map(property, ",");
    }

    /**
     * Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2
     */
    public Map<String, List<String>> mapOfList(String property) {
        Map<String, String> map = this.map(property, ";");

        Map<String, List<String>> mapOfList = new HashMap<>();
        for (Entry<String, String> entry : map.entrySet()) {
            mapOfList.put(entry.getKey(), this.list(entry.getValue()));
        }

        return mapOfList;
    }

    /**
     * Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4
     */
    public List<String> list(String property) {
        return this.list(property, ",");
    }

    /**
     * Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2
     */
    public List<List<String>> groupedList(String property) {
        List<String> unGroupedList = this.list(property, ";");

        List<List<String>> groupedList = new ArrayList<>();
        for (String group : unGroupedList) {
            groupedList.add(this.list(group));
        }

        return groupedList;

    }

    private List<String> list(String property, String splitter) {
        return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property);
    }

    private Map<String, String> map(String property, String splitter) {
        return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property);
    }

}

: PropertySplitter계급적 용법Splitter구아바의 효용자세한 사항은 그 문서를 참고하시기 바랍니다.

그럼, 당신 콩에.

@Component
public class MyBean {

    @Value("#{PropertySplitter.map('${service.expiration}')}")
    Map<String, String> propertyAsMap;

}

그리고 마지막으로, 재산은:

service.expiration = name1:100,name2:20

그건 당신이 요청한 것과는 달라요 왜냐면 이건PropertySplitter하나의 속성으로 작업을 수행합니다.Map, 내 생각에 당신은 이런 방식으로 속성을 지정하거나 수정할 수 있을 것 같습니다.PropertySplitter원하는 계층적 방식과 일치하도록 코드를 지정합니다.

Spring 4.1.x (구체적인 버전은 기억나지 않지만) 부터는 다음과 같은 작업을 할 수 있습니다.

@Value("#{${your.properties.key.name}}")
private Map<String, String> myMap;

당신의 속성을 입력합니다.당신의 속성 파일에 있는 key.name 은 다음과 같습니다.

your.properties.key.name={\
    name1 : 100, \
    name2 : 200 \
}

PropertySourcesPlaceholderConfigurebean을 만들어 앱에서 모두 작동하고 코드를 테스트할 단위 테스트 코드를 작성하는 경우 ${...} 자산 가치에 대한 자리 표시자가 예상대로 작동하지 않고 이상한 SpringEL 오류가 발생합니다.

내가 생각할 수 있는 가장 빠른 Spring Boot 기반 솔루션은 다음과 같습니다.특정 예에서는 한 시스템에서 다른 시스템으로 데이터를 마이그레이션하고 있습니다.그래서 우선순위라는 분야에 대한 매핑이 필요합니다.

먼저 다음과 같은 속성 파일(priority-migration.properties)을 만들었습니다.

my.prefix.priority.0:0
my.prefix.priority.10:1
my.prefix.priority.15:2
my.prefix.priority.20:2
another.prefix.foo:bar

수업길에 올려놓기도 하고요

스프링 관리 콩/구성요소에서 지도를 사용하고자 할 경우 클래스에 다음과 같은 주석을 달아야 합니다.

@Component
@PropertySource("classpath:/priority-migration.properties")

지도에서 실제로 원하는 것은 물론 my.prefix 앞에 붙는 키/값 쌍, 즉 이 부분입니다.

{
    0:0
    10:1
    15:2
    20:2
}

구성요소에 주석을 달려면 다음을 사용해야 합니다.

@ConfigurationProperties("my.prefix")

수정 우선 순위에 대한 게터를 만듭니다.후자는 제 경우에 의무적인 것으로 증명되었습니다(Sring Doc에서는 재산 우선권을 가지고 변동 가능한 값으로 초기화하는 것으로 충분하다고 하지만).

private final Map<Integer, Integer> priorityMap = new HashMap<>();

public Map<Integer, Integer> getPriority() {
    return priorityMap;
}

마침내.

다음과 같습니다.

@Component
@ConfigurationProperties("my.prefix")
@PropertySource("classpath:/priority-migration.properties")
class PriorityProcessor {

    private final Map<Integer, Integer> priorityMap = new HashMap<>();

    public Map<Integer, Integer> getPriority() {
        return priorityMap;
    }

    public void process() {

        Integer myPriority = priorityMap.get(10)
        // use it here
    }
}

이전 게시물에서 영감을 얻어 하나의 해결책을 만듭니다.

Spring 구성에 속성 파일을 등록합니다.

<util:properties id="myProp" location="classpath:my.properties"/>

그리고 구성요소를 만듭니다.

@Component("PropertyMapper")
public class PropertyMapper {

    @Autowired
    ApplicationContext applicationContext;

    public HashMap<String, Object> startWith(String qualifier, String startWith) {
        return startWith(qualifier, startWith, false);
    }

    public HashMap<String, Object> startWith(String qualifier, String startWith, boolean removeStartWith) {
        HashMap<String, Object> result = new HashMap<String, Object>();

        Object obj = applicationContext.getBean(qualifier);
        if (obj instanceof Properties) {
            Properties mobileProperties = (Properties)obj;

            if (mobileProperties != null) {
                for (Entry<Object, Object> e : mobileProperties.entrySet()) {
                    Object oKey = e.getKey();
                    if (oKey instanceof String) {
                        String key = (String)oKey;
                        if (((String) oKey).startsWith(startWith)) {
                            if (removeStartWith) 
                                key = key.substring(startWith.length());
                            result.put(key, e.getValue());
                        }
                    }
                }
            }
        }

        return result;
    }
}

그리고 specifix 값으로 시작하는 모든 속성을 @Value 주석으로 해시맵에 매핑하려면 다음과 같이 하십시오.

@Service
public class MyServiceImpl implements MyService {

    @Value("#{PropertyMapper.startWith('myProp', 'service.expiration.', true)}")
    private HashMap<String, Object> portalExpirations;

다중선으로 부호화된 application.yml 속성 @Value from 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 

여기서 맵 속성 "my-map-property-name" 값은 문자열 내에 JSON 형식으로 저장되며 줄의 끝에 \를 사용하는 아카이브된 다중 행이 있습니다.

나의 자바 클래스 .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...
    } }

}

자세한 설명

  • \yamlit에서 줄을 여러 줄로 쪼개는 데 사용됩니다.

  • \"yaml 문자열의 "(quote)"에 대한 탈출 문자입니다.

  • @Value에 의해 맵으로 변환되는 yaml의 {key:value} JSON

  • #{ }이(가) SpEL 식이며 @Value에서 맵 또는 배열/목록 참조 json 변환에 사용할 수 있습니다.

스프링 부트 프로젝트에서 테스트됨

Yaml 이름과 동일한 변수 이름 사용

예:

private final HashMap<String, String> expiration 

대신에

private final HashMap<String, String> expirations 

또는 이와 유사한 in properties file이

org.code=0009,0008,0010
org.code.0009.channel=30,40
org.code.0008.channel=30,40
org.code.0010.channel=30,40

자바에서 org.code를 읽고 org.code를 읽고 각각의 org.code를 통과하여 build org.code..채널을 돌려 그것을 지도에 집어넣습니다.

언급URL : https://stackoverflow.com/questions/28369458/how-to-fill-hashmap-from-java-property-file-with-spring-value

반응형