나는이 봄 부트 다음에 응용 프로그램 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
그게 (또는 비슷한) 가능합니까? 분명히 yaml을 직접로드 할 수 있지만 이미 Spring에서 지원하는 것이 있는지 궁금합니다.
답변
다음을 사용하여지도를 삽입 할 수 있습니다 @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;
}
}
}
질문에서 yaml로 이것을 실행하면 다음이 생성됩니다.
{build={artifact=${project.artifactId}, version=${project.version}, name=${project.name}, description=${project.description}}}
접두사 설정, 누락 된 속성 처리 방법 제어 등에 대한 다양한 옵션이 있습니다. 자세한 내용은 javadoc 을 참조하십시오.
답변
아래 솔루션은 @Andy Wilkinson의 솔루션에 대한 속기입니다. 단, 별도의 클래스 나 @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에서 제공 한 멋진 솔루션에서이 아이디어를 시도했는데 누군가에게 유용 할 것이라고 생각했습니다.
답변
오늘도 같은 문제가 발생했지만 안타깝게도 Andy의 솔루션이 작동하지 않았습니다. Spring Boot 1.2.1.RELEASE에서는 훨씬 더 쉽지만 몇 가지 사항을 알고 있어야합니다.
내 흥미로운 부분은 다음과 같습니다 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() {
//....
}
}
응용 프로그램을 시작한 후 providers
맵 인 OAuth2ProvidersService
이 초기화되지 않았습니다. Andy가 제안한 솔루션을 시도했지만 제대로 작동하지 않았습니다. 나는 그 응용 프로그램에서 Groovy 를 사용 하기 때문에 private
Groovy가 getter와 setter를 생성 하도록 제거하기로 결정했습니다 . 그래서 내 코드는 다음과 같습니다.
@Service
@ConfigurationProperties(prefix = 'oauth')
class OAuth2ProvidersService implements InitializingBean {
Map<String, Map<String, String>> providers = [:]
@Override
void afterPropertiesSet() throws Exception {
initialize()
}
private void initialize() {
//....
}
}
그 작은 변화 후에 모든 것이 작동했습니다.
언급 할 가치가있는 한 가지가 있습니다. 내가 작동하게 한 후에 나는이 필드를 만들고 private
setter 메서드에서 setter에 직선 인수 유형을 제공 하기로 결정했습니다 . 불행히도 작동하지 않습니다. 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?
Spring Boot 애플리케이션에서 Groovy를 사용하는 경우이를 염두에 두십시오.
답변
구성에서 맵을 검색하려면 구성 클래스가 필요합니다. 불행히도 @Value 주석은 트릭을 수행하지 않습니다.
Application.yml
entries:
map:
key1: value1
key2: value2
구성 클래스 :
@Configuration
@ConfigurationProperties("entries")
@Getter
@Setter
public static class MyConfig {
private Map<String, String> map;
}
답변
당기위한 솔루션 맵 사용 @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
여기서 맵 속성 “my-map-property-name”의 값은 문자열 내부 에 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 문자열의”(따옴표)에 대한 이스케이프 문자입니다.
-
@Value에 의해 Map으로 변환 될 yaml의 {key : value} JSON
-
# {} SpEL 표현이며 @Value에서 json int Map 또는 Array / list Reference 를 변환하는 데 사용할 수 있습니다.
스프링 부트 프로젝트에서 테스트 됨
답변
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
답변
추가 구조를 피하려면 더 간단하게 만들 수 있습니다.
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;
}
}