부트 개념과 활용-10.외부 설정 2부
외부 설정 2부
타입-세이프 프로퍼티 @ConfigurationProperties
여러 프로퍼티를 묶어서 읽어올 수 있음
- 빈으로 등록해서 다른 빈에 주입할 수 있음
- @EnableConfigurationProperties
- @Component
- @Bean
- 융통성 있는 바인딩
- context-path (케밥)
- context_path (언드스코어)
- contextPath (캐멀)
- CONTEXTPATH
- 프로퍼티 타입 컨버전
- @DurationUnit
- 프로퍼티 값 검증
- @Validated
- JSR-303 (@NotNull, …)
메타 정보 생성
- @Value
- SpEL 을 사용할 수 있지만…
- 위에 있는 기능들은 전부 사용 못합니다.
여러 프로퍼티가 많은 경우에 하나로 묶어서 가능
@Component
@ConfigurationProperties("people")
public class PeopleProperties {
String name;
int age;
String fullName;
... getter setter 구현 (자바 표준 스펙을 사용해 구현됨)
원래는 // @EnableConfigurationProperties(PeopleProperties.class)걸 해 줘야 하지만
전에 배운 자동설정 이해 파트에 정리된(@EnableAutoConfiguration)에 이미 들어 있는 상태이고
PeopleProperties 클래스에 컴포넌트만 선언해주면 주입 가능하다.
@ConfigurationProperties 사용하면 추가 의존성이 필요한데,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
프로퍼티를 설정할 때 메타정보 파일을 확인하는데 (자동완성 구현 등..)이 때 필요한 의존성이다.
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("=============== real application ===============");
System.out.println("people.name : " + peopleProperties.getName());
System.out.println("people.age : " + peopleProperties.getAge());
System.out.println("people.fullName : " + peopleProperties.fullName);
System.out.println("=============== real application ===============");
}
이전처럼 @value로 받지 않고 프로퍼티에서 꺼내서 사용 가능하다.
참고
프로퍼티 파일 랜덤 설정시
people.age = ${random.int(10,30)} -> 공백 없이 사용
공백있으면 에러남
people.age = ${random.int(10, 30)} -> 10, 30 사이에 공백 있어서 에러 발생
융통성 있는 바인딩
people.name = real-jaeuk 15
people.age = ${random.int(10,30)}
#people.fullName = ${people.name} choi
people.full_Name = ${people.name} choi
people.full_Name 이런 식으로 쓰더라도 바인딩을 해 주고,
100 이라쓰면 사실 문자열인데 int 로 받음. 기본적인 타입 컨버전은 제공한다.
추가로 PeopleProperties에 @DurationUnit(ChronoUnit.SECONDS) 로 선언을 해 주고
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
people.sessionTimeout = 25
로 선언해주면 자동으로 people.fullName : PT25S
이렇게 받는다 또는 저런 @DurationUnit을 쓰지 않고도
people.sessionTimeout = 25s
이런 서브픽스를 제공한다.
people.sessionTimeout : PT25S
동일하게 출력됨
또한 프로퍼티에 들어오는 값을 검증하는 방법도 있다..
(앞서 핵심기술에서 공부한 내용-이전포스트 참조, min, max 등..)
@Component
@ConfigurationProperties("people")
@Validated // 벨리데이테트 추가
public class PeopleProperties {
@NotEmpty
String name;
프로퍼티에 값을 지우면
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-12-15 14:20:44.237 ERROR 30679 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'people' to me.jaeuk.properties.PeopleProperties failed:
Property: people.name
Value:
Origin: class path resource [application.properties]:3:0
Reason: 반드시 값이 존재하고 길이 혹은 크기가 0보다 커야 합니다.
Action:
Update your application's configuration
이런 에러메세지가 발생한다.
참고
FailureAnalyzer
에러메세지를 이쁘게 이해히 쉽게 메세지를 보여준다. (부트 자동설정)
@value 보다는 이렇게 쓰는게 더 좋다.
얘는 키워드 그대로 정확하게만 받을, 메타정보도 제공 안하고 (자동완성)
매핑도 유연하고. 키멜케이스, 다 대문자로 써도 되고…
#people.fullName = ${people.name} choi
#people.full_Name = ${people.name} choi
#people.FULLNAME = ${people.name} choi
people.FULL_NAME = ${people.name} choi
다 잘받는다..
딱 하나 장점이 @vaule에서는 SPEL이 사용가능하다.