java로 프로그래밍을 하다가 보면 몇가지 설정값을 외부에서 받아야 하는 경우가 있는데 이때 사용하는 것이 property 파일이다.
jdk에도 이 프로퍼티 파일을 다룰 수 있는 클래스가 마련되어 있다. java.util.Properties 클래스가 그 용도이다.
이 클래스를 사용하려면 load라는 메소드를 통해서 프로퍼티 파일일 읽어 와야 하는데 이때 전달되는 인자는 InputStream이다.
문제는 이 InputStream을 전달하려면 FileInputStream을 만들어서 전달해야 하는데 이 FileInputStream을 생성하려면 그 프로퍼티 파일의 경로를 알아야 한다는 것이다.
프로퍼티 파일의 경로를 알아오는 방법에 대해서 몇가지 생각해 보자
1. 프로그램 코드에 상수로 프로터피 파일의 경로를 둔다.
예를들면,
public staitc final String PATH = "/app/myapp/myprop.properties";
라고 두는 것이다. 뭐 이건 말 안해도 알겠지만 별로 좋지 않은 방법이다. 경로나 이름이 바뀌면 새로 컴파일 해야 하고, 뭐 이래저래 좋지 않은거 같다.
2. java 실행 옵션으로 세팅해서 프로그램에서 사용한다.
java 프로그램을 실행시킬 때 실행 옵션으로 프로퍼티 파일의 경로를 줘서 그 옵션값을 읽어서 경로로 사용하도록 하는 것이다.
String path = System.getProperty( "path" );
라는 형태로 사용하면 실행시 준 옵션값을 가져올 수 있다.
이 방법도 많이 사용하는 방법으로 나름대로 쓸만하다. 그렇지만 실행시 옵션을 설정한다는 것이 별로 마음에 안든다.
3. ClassLoader를 사용하여 가져온다.
혹시 이거 신기하게 생각해 본 사람이 있을지 모르겠는데, log4j를 사용하다 보면 log4j.properties라는 파일을 생성해 두면 내가 특별히 경로를 세팅하지 않았는데도 log4j가 알아서 log4j.properties를 읽어서 사용한다. 나는 처음에 이게 무지 신기했다. log4j가 어떻게 알고 그 위치의 log4j.properties를 읽어 들이는 걸까?
해답은 ClassLoader 였다.
classloader의 주요 기능은 클래스를 로딩하는 것이다.(이름에서 알 수 있는 너무 당연한 이야긴가? ^^;)
하지만 기능이 한가지 더 있는데 바로 클래스 파일 뿐아니라 다른 리소스 파일도 읽어 주는 역할이다.
ClassLoader.getResource( String name )이 그 역할을 하는 메소드다(이 메소드 외에도 getResource... 메소드들이 몇가지 더 있다. 알아서 찾아 보시길...)
이 getResource는 클래스 패스내에서 해당 이름으로 된 파일을 찾아서 그 URL을 넘겨준다. 중요한 포인트는 바로 클래스 패스 내에 있는 파일이라는 것이다.
java를 실행시킬때 -classpath라고 주는 바로 그 클래스 패스 말이다. 즉 classpath에 설정한 클래스 패스내에 프로퍼티 파일을 두면 ClassLoader를 통해서 프로퍼티 파일을 가져올 수 있는 것이다. 별거 아닌 기능 같지만 쓰다보면 상당히 편리하다.
실제 구현 내용을 간단히 살펴보면 다음과 같다.
ClassLoader cl;
cl = Thread.currentThread().getContextClassLoader();
if( cl == null )
cl = ClassLoader.getSystemClassLoader();
URL url = cl.getResource( "myprop.properties" );
위 내용은 log4j의 소스에서 일부 참조한 것이다.
이때 그냥
ClassLoader cl = ClassLoader.getSystemClassLoader();
하지 않고
cl = Thread.getContextClassLoader();
를 통해서 먼저 ClassLoader를 구해오는 것은 나름대로 이유가 있다.
java 프로그래밍의 상당 부분은 독립실행되는 java application보다 web application의 형태로, 즉 container(tomcat, weblogic 등등) 안에서 실행되는 application으로 제작되는 경우가 많다.
container는 여러 application을 분리하기 위해 각 application마다 ClassLoader를 새로 생성해서 사용하며, 각 application을 구동시키기 위해 Thread를 생성한다. 이때 container는 application을 위해 생성한 Thread에 setContextClassLoader를 통하여 그 application을 위해 생성한 ClassLoader를 세팅해 준다.
따라서 container안에서 실행되는 application에서는 resource를 찾기 위해 system의 ClassLoader가 아니라 그 application을 로드하는 ClassLoader를 사용해야 한다. 그래서 위의 코드처럼 Thread의 ClassLoader를 먼저 체크해 봐야 하는 것이다.
예상했겠지만, 이때 그 application을 위해 생성된 ClassLoader에 세팅되는 Class Path는, 그 application에만 해당되는 path( ex)classes, lib 등등)만 추가되기 때문에 다른 위치에 있는 resource는 가져오지 않는, 아니 가져올 수 없게 되는 것이다.
물론 독립실행형 java application에서는 그냥 System.getSystemClassLoader()만 사용해도 된다.
위 소스를 참조해서 쉽게 프로퍼티 파일을 다룰 수 있는 클래스를 만들어 보는 것도 좋을 듯 하다.
[출처] Java에서 Property 파일 쉽게 찾기|작성자 쫌조
[ Property 사용하기2 ]
import java.util.*;
import java.io.*;
public class PropertyTest {
private String PROPERTIES_FILE = "C:\\test.properties";
/**
* 특정 키값을 반환한다.
*/
private String getProperty(String keyName) {
String value = null;
try {
Properties props = new Properties();
FileInputStream fis = new FileInputStream(PROPERTIES_FILE);
props.load(new java.io.BufferedInputStream(fis));
value = props.getProperty(keyName).trim();
fis.close();
} catch (java.lang.Exception e) {
System.out.println(e.toString());
}
return value;
}
/**
* 특정 키 이름으로 값을 설정한다.
*/
private void setProperty(String keyName, String value) {
try {
Properties props = new Properties();
FileInputStream fis = new FileInputStream(PROPERTIES_FILE);
props.load(new java.io.BufferedInputStream(fis));
props.setProperty(keyName, value);
props.store(new FileOutputStream(GLOBALS_PROPERTIES_FILE), "");
fis.close();
} catch(java.lang.Exception e) {
System.out.println(e.toString());
}
}
public static void main(String args[]) {
PropertyTest o = null;
if (args.length == 1) {
o = new PropertyTest();
System.out.println(args[0] + ":[" + o.getProperty(args[0]) + "]");
} else if (args.length == 2) {
o = new PropertyTest();
o.setProperty(args[0], args[1]);
System.out.println(args[0] + ":[" + o.getProperty(args[0]) + "]");
} else {
System.out.println("wrong argument");
}
}
}
-test.properties-
#test
test.one = 1234
test.two = 5678
출처 : http://umzzil.egloos.com/2175356
[ ClassLoader 사용 ]
test.Properties는 %WEBROOT%/WEB-INF/classes/ 에 위치 시킨다.
try {
ClassLoader cl;
cl = Thread.currentThread().getContextClassLoader();
if( cl == null ) {
cl = ClassLoader.getSystemClassLoader();
}
URL url = cl.getResource("");
//여기서 괄호 안에 url을 지정해 주면 지정한 폴더에 Properties파일을 복사해야 합니다.
FileInputStream fis = new FileInputStream(url.getPath()+"\\test.Properties");
env.load(new java.io.BufferedInputStream(fis));
String name=env.getProperty("name");
String color = env.getProperty("color");
클래스를 만들어보았다.
public static String getProperty(String keyName) {
String result = null;
Properties properties = new Properties();
ClassLoader cl;
cl = Thread.currentThread().getContextClassLoader();
if( cl == null ) {
cl = ClassLoader.getSystemClassLoader();
}
URL url = cl.getResource("");
String file_path = url.getPath()+"\\test.properties";
try {
//테스트결과 공백대신 "%20"이 들어가서 " "로 replace함
FileInputStream ins = new FileInputStream(file_path.replaceAll("%20", " "));
properties.load(new java.io.BufferedInputStream(ins));
result = properties.getProperty(keyName).trim();
ins.close();
}catch(Exception ex) {
ex.printStackTrace();
}
return result;
}
'Java' 카테고리의 다른 글
[Java] Ant, Eclipse에서 jar만들기 (0) | 2010.06.23 |
---|---|
[Java] 페이지 이동 (0) | 2010.06.22 |
[Java] Java Property(위치 지정) (0) | 2010.06.17 |
[Java] Java Reflection (0) | 2010.06.16 |
[Java] 오버로딩, 오버라이딩 (0) | 2010.06.16 |