From 72b4259712c1ec9725c869db82dad3dfd851eaa7 Mon Sep 17 00:00:00 2001 From: "Jonguk. Lim" Date: Wed, 22 May 2024 13:05:24 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20spring-boot=20profile=EB=B3=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=9D=BD=EC=9D=84=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xit/adds/nims/web/TestController.java | 5 +- .../xit/foundation/boot/CommonConfig.java | 111 +++++++++++++ .../java/cokr/xit/foundation/boot/Yml.java | 148 ++++++++++++++++++ 3 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 src/main/java/cokr/xit/foundation/boot/CommonConfig.java create mode 100644 src/main/java/cokr/xit/foundation/boot/Yml.java diff --git a/src/main/java/cokr/xit/adds/nims/web/TestController.java b/src/main/java/cokr/xit/adds/nims/web/TestController.java index 44e3ece..c2a6810 100644 --- a/src/main/java/cokr/xit/adds/nims/web/TestController.java +++ b/src/main/java/cokr/xit/adds/nims/web/TestController.java @@ -6,8 +6,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import cokr.xit.foundation.web.AbstractController; +import lombok.RequiredArgsConstructor; - +@RequiredArgsConstructor @Controller @RequestMapping( name = "Nims 관리", @@ -15,7 +16,7 @@ import cokr.xit.foundation.web.AbstractController; ) public class TestController extends AbstractController { // FIXME: property injection으로 변경?? - @Value("${app.api.host:http://localhost:9076}") + @Value("${app.api.host:}") private String apiHost; @RequestMapping( diff --git a/src/main/java/cokr/xit/foundation/boot/CommonConfig.java b/src/main/java/cokr/xit/foundation/boot/CommonConfig.java new file mode 100644 index 0000000..7432a10 --- /dev/null +++ b/src/main/java/cokr/xit/foundation/boot/CommonConfig.java @@ -0,0 +1,111 @@ +package cokr.xit.foundation.boot; + +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.egovframe.rte.fdl.cmmn.trace.LeaveaTrace; +import org.egovframe.rte.fdl.property.impl.EgovPropertyServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.core.env.Environment; +import org.springframework.util.AntPathMatcher; + +import com.fasterxml.jackson.core.JsonParser.Feature; +import com.fasterxml.jackson.databind.ObjectMapper; + +/**전자정부 프레임웤과 xit foundation을 사용하는 애플리케이션의 공통 Bean들을 설정한다. + * @author mjkhan + */ +@Configuration +@ComponentScan(basePackages = "cokr.xit") +public class CommonConfig { + @Autowired + Environment env; + + /**AntPathMatcher를 반환한다. + * @return AntPathMatcher + */ + @Bean + public AntPathMatcher antPathMatcher() { + return new AntPathMatcher(); + } + + /**ObjectMapper를 반환한다. + * @return ObjectMapper + */ + @Bean + public ObjectMapper objectMapper() { + ObjectMapper bean = new ObjectMapper(); + bean.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + bean.configure(Feature.ALLOW_COMMENTS, true); + return bean; + } + + /**LeaveaTrace를 반환한다. + * @return LeaveaTrace + */ + @Bean + public LeaveaTrace leaveaTrace() { + return new LeaveaTrace(); + } + + //private Yml yml = new Yml("application.yml", "application.yml", env); + @Bean + public Yml yml() { + return new Yml("application.yml", "application.yml", env); + } + + /**application.yml의 설정 내용을 읽어 MessageSource Bean을 설정하여 반환한다. + *
 messageSource:
+  	 *   basenames:
+     *     - classpath:message/message-common
+     *     - classpath:message/authentication-message
+     *     - classpath:org/egovframe/rte/fdl/property/messages/properties
+ * @return ReloadableResourceBundleMessageSource + */ + @Bean + public ReloadableResourceBundleMessageSource messageSource() { + ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource(); + bean.setDefaultEncoding("UTF-8"); + bean.setCacheSeconds(60); + + List basenames = yml().getValues("messageSource.basenames"); + if (!basenames.isEmpty()) + bean.setBasenames(basenames.toArray(new String[basenames.size()])); + + return bean; + } + + /**application.yml의 설정 내용을 읽어 EgovPropertyServiceImpl Bean을 설정하여 반환한다. + *
 propertyService:
+  	 *   properties: # 인라인 프로퍼티가 있을 경우
+     *     - property0: value0
+     *     - property1: value1
+     *   extFileName: #외부 프로퍼티 파일이 있을 경우
+     *     - encoding: UTF-8
+     *       filename: classpath*:properties/your-file-01.properties
+     *     - encoding: UTF-8
+     *       filename: classpath*:properties/your-file-02.properties
+ * @return EgovPropertyServiceImpl + */ + @Bean + public EgovPropertyServiceImpl propertyService() { + EgovPropertyServiceImpl bean = new EgovPropertyServiceImpl(); + + Map properties = yml().getMap("propertyService.properties"); + if (!properties.isEmpty()) + bean.setProperties(properties); + + Set filenames = yml().getMaps("propertyService.extFileName").stream().collect(Collectors.toSet()); + if (!filenames.isEmpty()) + bean.setExtFileName(filenames); + + return bean; + } +} diff --git a/src/main/java/cokr/xit/foundation/boot/Yml.java b/src/main/java/cokr/xit/foundation/boot/Yml.java new file mode 100644 index 0000000..478329b --- /dev/null +++ b/src/main/java/cokr/xit/foundation/boot/Yml.java @@ -0,0 +1,148 @@ +package cokr.xit.foundation.boot; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.boot.env.YamlPropertySourceLoader; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.ClassPathResource; + +import cokr.xit.foundation.Assert; + +/**yml 파일 내용을 프로퍼티 형식으로 읽기를 지원하는 유틸리티. + *

+ * @author mjkhan + */ +public class Yml { + private Map source; + private final Environment env; + + /**새 Yml을 생성한다. + * @param rootName 프로퍼티 소스의 루트 이름 + * @param path 클래스패스에서 yml 파일의 경로 + */ + public Yml(String rootName, String path, Environment environment) { + this.env = environment; + load(rootName, path); + } + + /**지정하는 yml 파일의 프로퍼티들을 읽어들인다. + * @param rootName 프로퍼티 소스의 루트 이름 + * @param path 클래스패스에서 yml 파일의 경로 + * @return 현재 Yml + */ + public Yml load(String rootName, String path) { + source = null; + try { + List> sources = new YamlPropertySourceLoader() + .load(rootName, new ClassPathResource(path)); + if (!sources.isEmpty()) { + source = (Map)sources.get(0).getSource(); + } + + // Spring-boot profile별 설정이 있는 경우 처리 + String[] activeProfiles = env.getActiveProfiles(); + for (String profile : activeProfiles) { + PropertySource profileSource = sources.stream() + .filter(ps -> ps.getName().equals(profile)) + .findFirst() + .orElse(null); // default to null if no matching profile is found + + if (profileSource != null) { + // Merge the properties of the profile into the source map + ((Map)source).putAll((Map)profileSource.getSource()); + } + } + return this; + } catch (Exception e) { + throw Assert.runtimeException(e); + } + } + + /**지정하는 프로퍼티(아래 참고)의 값을 반환한다. + * @param key 키. 프로퍼티 이름 + *

 spring:
+	 *   application:
+	 *     name: my-application
+	 * 
+ * @return 지정하는 키의 프로퍼티 값 + */ + public String getValue(String key) { + if (source == null) return ""; + + Object obj = source.get(key); + return obj != null ? obj.toString() : ""; + } + + /**지정하는 문자열로 시작하는 프로퍼티(아래 참고) 값들을 반환한다. + *
 list:
+	 *   - item-0
+	 *   - item-2
+	 *   - item-3
+ * @param prefix 프로퍼티 접두어 + * @return 지정하는 문자열로 시작하는 프로퍼티 값 + */ + public List getValues(String prefix) { + if (source == null) return Collections.emptyList(); + + return getPrefixed(prefix).stream() + .map(entry -> entry.getValue().toString()) + .collect(Collectors.toList()); + } + + private List> getPrefixed(String prefix) { + return source.entrySet().stream() + .filter(entry -> entry.getKey().startsWith(prefix)) + .collect(Collectors.toList()); + } + + /**지정하는 문자열로 시작하는 프로퍼티(아래 참고) 값들을 Map으로 반환한다. + *
 parent:
+	 *   - property-0: value-0
+	 *   - property-1: value-1
+	 *   - property-2: value-2
+ * @param prefix 프로퍼티 접두어 + * @return 지정하는 문자열로 시작하는 프로퍼티로 된 Map + */ + public Map getMap(String prefix) { + if (source == null) return Collections.emptyMap(); + + LinkedHashMap map = new LinkedHashMap<>(); + getPrefixed(prefix).stream().forEach(entry -> putTo(map, entry)); + + return map; + } + + private void putTo(LinkedHashMap map, Map.Entry entry) { + String key = entry.getKey(); + key = key.substring(key.lastIndexOf(".") + 1); + String val = entry.getValue().toString(); + map.put(key, val); + } + + /**지정하는 문자열로 시작하는 프로퍼티들(아래 참고)을 Map 목록으로 반환한다. + *
 parent:
+	 *   - property-0: value-0.0
+	 *     property-1: value-0.1
+	 *   - property-0: value-1.0
+	 *     property-1: value-1.1
+ * @param prefix 프로퍼티 접두어 + * @return 지정하는 문자열로 시작하는 프로퍼티들의 Map 목록 + */ + public List> getMaps(String prefix) { + if (source == null) return Collections.emptyList(); + + return getPrefixed(prefix).stream() + .map(entry -> { + String str = entry.getKey(); + return str.substring(0, str.lastIndexOf(".")); + }) + .collect(Collectors.toSet()).stream() + .map(this::getMap) + .collect(Collectors.toList()); + } +}