SpringBoot Properties
-
jasypt 를 이용해 비밀번호 계통은 암호화 해서 저장해야 한다.
-
보통 yml
을 이용해서 application.yml
로 지정한다.
YamlPropertiesFactoryBean
PropertiesFactoryBean
YamlPropertySourceLoader
PropertiesPropertySourceLoader
기본값 설정
이미 지정된 property 이면, 해당 값을 사용하고, 그게 아니면 기본값을 사용하는 구조로
EXTERNAL_USERNAME/EXTERNAL_PASSWORD
환경 변수 혹은 external.username/external.password
프라퍼티가 존재하면 그 값을 사용하고 그게 아니면 :
뒤에 지정된 값을 사용한다.
testing:
my:
username: ${external.username:system}
password: ${external.password:test}
SpEL로 기본값 지정. SpEL은
@Value
로 값을 읽는 경우에만 지정 가능하며,
@ConfigurationProperties
를 사용할 때는 안 된다. 혼란스럽기 때문에 안 사용하는게 나을듯 하다.
testing:
my:
username: ${external.username:user}
password: ${external.password:#{' test'}}
@Value("${testing.my.username}")
private String username;
@Value("${testing.my.password}")
private String password;
profile 별 설정
프로필 별로 application-profilename.yml
로 파일을 만들 수도 있고,
하나의 파일에서 ---
로 구분해서 프로필을 지정할 수도 있다.
application.yml
에서 profile을 지정하지 않은 프라퍼티는 공통 디폴트 값 역할을 한다. 각 프로필에서 오버라이드하면 변경되고 아니면 디폴트 값이 사용된다.
a:
b:
c: default value
---
spring.profiles: local
# 기본값 그대로 사용
---
spring.profiles: develop
a:
b:
c: develop-value
---
spring.profiles: production
a:
b:
c: production-value
profile include
프로필을 자동 활성화 한다.
Spring Boot 2.3 이전에서 사용하는 방식.
-
application.yml
spring.profiles: production
spring.profiles.include: a,b
# 혹은
spring.profiles: production
spring:
profiles:
include:
- a
- b
- c
위 설정은 production
profile 에서 자동으로 a
, b
, c
프로필도 활성화 시키는 역할을 한다.
그러면서 각 프로필의 설정파일을 application-a.yml
, application-b.yml
형태로 만들어서 resources
에 두면 이를 읽게 된다.
위 설정을 특정 프로필이 아닌 전역으로 지정하면, 마치 그냥 설정 파일을 include 하는 것 처럼 된다. 하지만 a
,b
,c
라는 프로필이 모르는 사이에 활성화 된다.
각 프로필에서 또 나눠서 spring.profiles: local
이런식으로 특정 프로파일을 지정하고 설정해도 먹지 않고 무시된다. a-develop
이런식으로 별도 프로필을 만들고 active: a-develop
처럼 더 추가해줘야만 한다.
즉, 최초 시작 설정 파일은 application.yml
이어야만 include 된 설정 안에서의 Profile 구분이 올바로 작동한다. 애초에 최초 시작 설정 파일을 application-prod.yml
로 한 상태에서 include는 그 안의 Profile 구분이 무시된다.
별도 Yaml로 PropertySource 적재 방식
// 일반 Bean으로 만들어 주입
@Autowired
private ConfigurableEnvironment env;
@Bean
@Order(-1)
PropertySource consumerPropertySource() throws IOException {
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource propertySource =
loader.load("consumers", new ClassPathResource("consumer.yml"), "develop");
env.getPropertySources().addLast(propertySource);
return propertySource;
}
// ApplicationContextInitializerApplicationContextInitializer 구현
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
try {
Resource resource = applicationContext.getResource("classpath:application.yml");
YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
PropertySource<?> yamlTestProperties = sourceLoader.load("yamlTestProperties", resource, null);
applicationContext.getEnvironment().getPropertySources().addLast(yamlTestProperties);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
YAML을 Property 객체로 변환하기
YAML을 ''@PropertySource''로 사용하기
@PropertySource(
value = "classpath:foo.yml",
factory = YamlPropertySourceFactory.class
)
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource)
throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(encodedResource.getResource());
Properties properties = factory.getObject();
return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
}
}
@ConfigurationProperties
@EnableConfigurationProperties
가 설정돼 있어야 한다.
-
-
아래 의존성을 추가하면 yml IDE 자동 완성이 지원되는 듯
compile "org.springframework.boot:spring-boot-configuration-processor"
@ConfigurationProperties
애노테이션이 붙은 클래스에 직접 @Configuration
을 붙여서 생성하거나, 별도로 @Bean
으로 생성하면 자동으로 값이 차서 Bean 으로 생성된다.
javax.validation
애노테이션을 걸어주면 자동 validation이 작동한다.
PropertySource과 properties 로그로 남기기
@Component
public class LoadedConfigFileListener implements ApplicationListener<ApplicationReadyEvent>, Ordered {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
MutablePropertySources propertySources = event.getApplicationContext().getEnvironment().getPropertySources();
Iterator<PropertySource<?>> propertySourceIterator = propertySources.iterator();
propertySourceIterator.forEachRemaining(propertySource -> log.info("Successfully loaded: \"{}\" ({}) into application context", propertySource.getName(), propertySource.getSource()));
}
@Override
public int getOrder() {
return ConfigFileApplicationListener.DEFAULT_ORDER + 1;
}
}
모든 properties 로그로 남기기
@Component
public class PropertyLogger {
private static final Logger LOGGER = LoggerFactory.getLogger(PropertyLogger.class);
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
final Environment env = event.getApplicationContext().getEnvironment();
LOGGER.info("====== Environment and configuration ======");
LOGGER.info("Active profiles: {}", Arrays.toString(env.getActiveProfiles()));
final MutablePropertySources sources = ((AbstractEnvironment) env).getPropertySources();
StreamSupport.stream(sources.spliterator(), false)
.filter(ps -> ps instanceof EnumerablePropertySource)
.map(ps -> ((EnumerablePropertySource) ps).getPropertyNames())
.flatMap(Arrays::stream)
.distinct()
.filter(prop -> !(prop.contains("credentials") || prop.contains("password")))
.forEach(prop -> LOGGER.info("{}: {}", prop, env.getProperty(prop)));
LOGGER.info("===========================================");
}
}
addional property 파일지정
spring.config.additional-location=classpath:/custom-config,file:./custom-config
JSON을 통한 Override
JSON 으로 명령행에서 properties를 override할 수 있다. JSON 으로 여러 프라퍼티를 지정할 수 있다.
시스템 프라퍼티로 : spring.application.json={“keyname”:“value”}
환경 변수로 : SPRING_APPLICATION_JSON={“keyname”:“value”}
EnvironmentPostProcessor 를 통한 프라퍼티 값 후처리
YAML Duration
참고