Spring Boot-вставить карту из приложения.в формате YML
у меня есть Spring Boot приложения 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 напрямую, но мне было интересно, есть ли что-то уже поддержанное весной.
5 ответов:
вы можете иметь карту вводится с помощью
@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}}}существуют различные варианты установки префикса, управления обработкой отсутствующих свойств и т. д. Смотрите документация для получения дополнительной информации.
ниже решение является сокращением для решения @Andy Wilkinson, за исключением того, что он не должен использовать отдельный класс или на
@Beanаннотированный метод.приложение.yml:
input: name: raja age: 12 somedata: abcd: 1 bcbd: 2 cdbd: 3SomeComponent.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, подумал, что это будет полезно для кого-то.
сегодня я столкнулся с той же проблемой, но, к сожалению, решение Энди не сработало для меня. В Весенней Загрузке 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() { //.... } }после запуска приложения
providersкартаOAuth2ProvidersServiceне был инициализирован. Я попробовал решение, предложенное Энди, но оно не сработало. Я использую в Groovy в этом приложении, поэтому я решил удалитьprivateи пусть Groovy генерирует геттер и сеттер. Так что мой код выглядел так:@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?имейте это в виду, если вы используете Groovy в своем приложении Spring Boot.
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
для получения карты из конфигурации вам понадобится класс конфигурации. @ Value аннотация не будет делать трюк, к сожалению.
приложение.в формате YML
entries: map: key1: value1 key2: value2класса конфигурации:
@Component @ConfigurationProperties("entries") @Getter @Setter public static class MyConfig { private Map<String, String> map; }
Comments