Spring framework에서는 기본적으로 Properties를 Runtime시에 변경된 설정을 자동으로 반영하는 기능을 제공하고 있지 않다.
Runtime 시 Properites 파일이 변경된 경우 변경된 내용을 읽어서 반여이 필요한 경우 별도로 개발이 필요하다.
먼저 Properties를 읽어서 저장한 후 프로그램에서 사용하기 위해 static으로 ReloadPropertiesUtil을 생성한다.
■ ReloadPropertiesUtil.java
import java.io.InputStream; import java.util.List; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ReloadPropertiesUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ReloadPropertiesUtil.class);
private static Properties propertyMap = new Properties();
/** Properties file **/ private List<String> propertyFiles;
public void setPropertyFiles(List<String> propertyFiles) { this.propertyFiles = propertyFiles; } /** * *<pre> * 1.Description: Load Property file when the context is loaded * 2.Biz Logic: * 3.Author : LGCNS *</pre> * @throws Exception */ public void init() throws Exception { generateProperties(); }
/** * *<pre> * 1.Description: Reload Properties file * 2.Biz Logic: * 3.Author : LGCNS *</pre> * @throws Exception */ public void reload() throws Exception { synchronized(this) { propertyMap.clear(); generateProperties(); } }
private void generateProperties() throws Exception {
for (String fileName : propertyFiles) { InputStream fis = BeanUtil.getResoure(fileName); if (fis == null) { LOGGER.error("{} file does not exist", fileName); continue; } propertyMap.load(fis); }
if (LOGGER.isDebugEnabled()) { propertyMap.list(System.out); } }
public static Object get(String key) { return propertyMap.get(key); }
public static String getString(String key) { return propertyMap.get(key) != null ? String.valueOf(propertyMap.get(key)) : ""; }
public static int getInt(String key) { return propertyMap.get(key) != null ? Integer.parseInt(String.valueOf(propertyMap.get(key))) : 0; }
public static long getLong(String key) { return propertyMap.get(key) != null ? Long.parseLong(String.valueOf(propertyMap.get(key))) : 0L; } } |
ReloadProperties에서는 init과 reload 메소드에서 generateProperties 메소드를 호출하여 Propeties File을 읽어 load하는 기능을 수행한다.
init method는 Spring Framework의 Bean으로 설정하여 IoC Container에 로드될 때 호출되는 메소드이며, reload는 Properties 파일이 변경될 때 호출되는 메소드이다.
다음으로 FileAlterationObserver를 이용하여 Properties 파일의 디렉토리 내의 파일이 변경을 인식하여 서비스를 호출하는 Class를 생성한다.
■BaseFileObserver.java
import java.io.File; import java.util.ArrayList; import java.util.List; import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import org.apache.commons.io.monitor.FileAlterationMonitor; import org.apache.commons.io.monitor.FileAlterationObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import org.springframework.util.ResourceUtils; import BizException; import FileService; import PropertieFileServiceImpl; public class BaseFileObserver { private static final Logger LOGGER = LoggerFactory.getLogger(BaseFileObserver.class);
private List<String> directories;
/** File Check interval (unit : milliseconds**/ private int interval = 500;
/** Service when file or directory is modified **/ private FileService fileService;
@Required public void setDirectories(List<String> directories) { this.directories = directories; } public void setInterval(int interval) { this.interval = interval; } @Required public void setFileService(FileService fileService) { this.fileService = fileService; } public BaseFileObserver() {
} public BaseFileObserver(FileService fileService, List<String> directories) { this.fileService = fileService; this.directories = directories; } public void init() throws Exception { for (String dir : directories) { if (dir.startsWith( ResourceUtils.CLASSPATH_URL_PREFIX)) { dir = ResourceUtils.getFile(dir).getAbsolutePath(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("File Observe path :: {}", dir); } FileAlterationObserver observer = new FileAlterationObserver(dir); observer.addListener(new FileAlterationListenerAdaptor() { @Override public void onDirectoryCreate(File file) { LOGGER.info("Directory is created : {}", file.getAbsolutePath()); System.out.println("Directory is created : " + file.getAbsolutePath()); try { fileService.onDirectoryCreate(file); } catch(Exception ex) { throw new BizException(ex.getMessage()); } } @Override public void onDirectoryChange(File file) { LOGGER.info("Directory is changed : {}", file.getAbsolutePath()); System.out.println("Directory is changed : " + file.getAbsolutePath());
try { fileService.onDirectoryChange(file); } catch(Exception ex) { throw new BizException(ex.getMessage()); } } @Override public void onDirectoryDelete(File file) { LOGGER.info("Directory is deleted : {}", file.getAbsolutePath()); System.out.println("Directory is deleted : " + file.getAbsolutePath()); try { fileService.onDirectoryDelete(file); } catch(Exception ex) { throw new BizException(ex.getMessage()); } }
@Override public void onFileCreate(File file) { LOGGER.info("File is created : {}", file.getAbsolutePath()); System.out.println("File is created : " + file.getAbsolutePath()); try { fileService.onFileCreate(file); } catch(Exception ex) { throw new BizException(ex.getMessage()); } }
@Override public void onFileChange(File file) { LOGGER.info("File is modified : {}", file.getAbsolutePath()); System.out.println("File is modified : " + file.getAbsolutePath()); try { fileService.onFileChange(file); } catch(Exception ex) { throw new BizException(ex.getMessage()); } }
@Override public void onFileDelete(File file) { LOGGER.info("File is deleted : {}", file.getAbsolutePath()); System.out.println("File is deleted : " + file.getAbsolutePath()); try { fileService.onFileDelete(file); } catch(Exception ex) { throw new BizException(ex.getMessage()); } } });
/** Create monitor to check file is changed **/ FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer);
try { monitor.start(); } catch(InterruptedException ie) { monitor.stop(); } } } |
BaseFileObserver는 Properties 파일이 생성, 변경, 삭제되었을 때 FileService의 해당 메소드를 호출한다.
■ PropertieFileServiceImpl.java
import java.io.File; import org.springframework.beans.factory.annotation.Required; import ReloadPropertiesUtil; import FileService; public class PropertieFileServiceImpl implements FileService { private ReloadPropertiesUtil propertiesUtil;
@Required public void setPropertiesUtil(ReloadPropertiesUtil propertiesUtil) { this.propertiesUtil = propertiesUtil; } @Override public void onDirectoryCreate(File file) throws Exception { } @Override public void onDirectoryChange(File file) throws Exception { } @Override public void onDirectoryDelete(File file) throws Exception {
} @Override public void onFileCreate(File file) throws Exception { propertiesUtil.reload(); } @Override public void onFileChange(File file) throws Exception { propertiesUtil.reload(); } @Override public void onFileDelete(File file) throws Exception { propertiesUtil.reload(); } }
|
PropertieFileServiceImpl Service는 파일 생성, 삭제, 변경이 발생하는 경우에 ReloadPropertiesUtil의 reload 메소드를 호출한다.
■ Spring Bean 설정
<bean id="propertiesUtil" class="stis.framework.spring.ReloadPropertiesUtil" init-method="init"> <property name="propertyFiles"> <list> <value>properties/app.properties</value> <value>properties/system.properties</value> </list> </property> </bean>
<bean id="propertyFileObserver" class="stis.framework.file.BaseFileObserver"> <property name="directories"> <list> <value>classpath:properties</value> </list> </property> <property name="interval" value="500" /> <property name="fileService" ref="propertyFileService" /> </bean>
<bean id="propertyFileService" class="stis.framework.spring.service.impl.PropertieFileServiceImpl"> <property name="propertiesUtil" ref="propertiesUtil" /> </bean> |
propertiesUtil Bean에서는 properties 파일을 propertyFiles에 주입하여 Context가 로드될 때 init method를 호출하여 해당 파일을 읽도록 설정한다.
propertyFileObserver는 Property 파일이 있는 디렉토리를 directories 속성에 정의하였으며, 파일의 변경 체크 주기를 0.5초 간격으로 수행하도록 설정한다.
또한 propertyFileService에 propertiesUtil을 정의하여 해당 bean에 있는 reload 기능을 수행하도록 한다.
'Spring Framrwork' 카테고리의 다른 글
Spring framework Future와 AsyncResult 를 이용한 Async 서비스 호출 (0) | 2018.04.23 |
---|---|
Mybatis ResultHandler를 이용한 ExcelDownload (3) | 2018.04.19 |
Mybatis include sql (0) | 2018.03.23 |
Spring Framework File Upload with Drag and Drop (0) | 2018.03.16 |
Spring framework XML Marshaller( Jaxb2Marshaller ) (0) | 2018.03.09 |