1. 왜 이걸 썼을까?
bean에서 하드코딩된 값을 property 파일에 넣고 쓸려면 "key=value" 형태 밖에 안됩니다.
좀더 복잡한 구조를 효율적으로 관리하고자 한다면 xml을 이용해야 하는데
xml를 쉽게 처리할 수 있는게 뭐 없을까 찾아보니 digester라는 아파치 오픈소스가
눈에 띄었습니다.
그냥 따라하기 식으로 환경구성하고 테스트 만들어 보니 한 30분 즘...
정말 쉽게 구현이 되었습니다.
2. 필요한건 뭘까?
url : http://jakarta.apache.org/commons/digester/
아래 보면 digester를 이용하기 위해 관련된걸 보면 commons의 logging 1.1.x, BeanUtils 1.x, Collections 2.x/3.x 등이 필요합니다.
다 다운받으세요^^
digester : http://jakarta.apache.org/site/downloads/downloads_commons-digester.cgi
logging : http://jakarta.apache.org/site/downloads/downloads_commons-logging.cgi
BeanUtils : http://jakarta.apache.org/site/downloads/downloads_commons-beanutils.cgi
Collections : http://jakarta.apache.org/site/downloads/downloads_commons-collections.cgi
3. 만들어 보기
일단 간단한 형태로 구조를 잡았습니다.
[code]
<?xml version="1.0"?>
<config description="kkaok">
<database part="oracle">
<driverclassname>oracle.jdbc.driver.OracleDriver</driverclassname>
<url>oracle ......</url>
<maxactive>10</maxactive>
<maxwait>100</maxwait>
<defaultautocommit>true</defaultautocommit>
<defaultreadonly>false</defaultreadonly>
<defaulttransactionisolation>2</defaulttransactionisolation>
<username>oid</username>
<password>opwd</password>
</database>
<database part="cubrid">
<driverclassname>cubrid.jdbc.driver.CUBRIDDriver</driverclassname>
<url>jdbc:CUBRID:localhost:33000:demodb:::</url>
<maxactive>10</maxactive>
<maxwait>100</maxwait>
<defaultautocommit>true</defaultautocommit>
<defaultreadonly>false</defaultreadonly>
<defaulttransactionisolation>2</defaulttransactionisolation>
<username>cid</username>
<password>cpwd</password>
</database>
</config>
[/code]
config 라는 거 아래 database라는 노드가 반복이 되고
database 아래에는 part, driverclassname,url,maxactive ... 등이 있습니다.
xml을 매핑할 객체를 만들어 보겠습니다.
[code]
public class ConfigInfo {
private List databaseinfo; // database가 반복되는 bean
public ConfigInfo(){
databaseinfo = new ArrayList();
}
public void AddDatavaseInfo(DatabaseInfo dbinfo){ // database 빈에 추가하는 메소드
databaseinfo.add(dbinfo);
}
}
[/code]
반복이 되는 패턴 등은 따로 클래스로 뽑고 그냥 값은 property로 만드시면 됩니다.
[code]
public class DatabaseInfo {
private String part;
private String driverclassname;
private String url;
private int maxactive;
private long maxwait;
private boolean defaultautocommit;
private boolean defaultreadonly;
private String username;
private String password;
private int defaulttransactionisolation;
public int getDefaulttransactionisolation() {
return defaulttransactionisolation;
}
public void setDefaulttransactionisolation(int defaulttransactionisolation) {
this.defaulttransactionisolation = defaulttransactionisolation;
}
public boolean isDefaultautocommit() {
return defaultautocommit;
}
public void setDefaultautocommit(boolean defaultautocommit) {
this.defaultautocommit = defaultautocommit;
}
public boolean isDefaultreadonly() {
return defaultreadonly;
}
public void setDefaultreadonly(boolean defaultreadonly) {
this.defaultreadonly = defaultreadonly;
}
public String getDriverclassname() {
return driverclassname;
}
public void setDriverclassname(String driverclassname) {
this.driverclassname = driverclassname;
}
public int getMaxactive() {
return maxactive;
}
public void setMaxactive(int maxactive) {
this.maxactive = maxactive;
}
public long getMaxwait() {
return maxwait;
}
public void setMaxwait(long maxwait) {
this.maxwait = maxwait;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPart() {
return part;
}
public void setPart(String part) {
this.part = part;
}
}
[/code]
[code]
public class ReadConfig {
public static void main(String[] args){
try {
Digester digester = new Digester();
digester.setValidating(false);
// 최상위 노드를 생성합니다. 객체는 addObjectCreate
// addObjectCreate(xml 경로와노드명, 객체 타입)
digester.addObjectCreate("config", ConfigInfo.class);
// DatabaseInfo를 생성합니다.
digester.addObjectCreate("config/database", DatabaseInfo.class);
// DatabaseInfo의 part 지정
//attributes는 addSetProperties(경로, attribute name, bean 매핑할 property) 메소드로 등록합니다.
digester.addSetProperties("config/database", "part", "part");
// node 추가, addBeanPropertySetter(경로와이름, 객체필드명)
digester.addBeanPropertySetter("config/database/driverclassname",
"driverclassname");
digester.addBeanPropertySetter("config/database/url", "url");
digester.addBeanPropertySetter("config/database/maxactive",
"maxactive");
digester
.addBeanPropertySetter("config/database/maxwait", "maxwait");
digester.addBeanPropertySetter("config/database/defaultautocommit",
"defaultautocommit");
digester.addBeanPropertySetter("config/database/defaultreadonly",
"defaultreadonly");
digester.addBeanPropertySetter("config/database/defaulttransactionisolation",
"defaulttransactionisolation");
digester.addBeanPropertySetter("config/database/username",
"username");
digester.addBeanPropertySetter("config/database/password",
"password");
// set하기
// addSetNext(경로와이름, 추가할 메소드명);
digester.addSetNext("config/database", "AddDatavaseInfo");
File input = new File(xml파일);
config = (ConfigInfo) digester.parse(input);
// config에 xml값이 이제 다 담겼습니다. 이제 입맛대로 사용하시면 됩니다.
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
[/code]
4. 결과
work flow
1. xml 구조 및 파일 생성
2. 매핑할 객체 생성
3. digester로 매핑하기
4. 사용
xml로 만들걸 객체로 생성하거나 객체로 구조 잡고 xml로 만들 수 있다면 나머진 digester가 알아서 해줍니다.
약간의 규칙을 알아야 하는데 해당 사이트에 가보시면 문서가 잘 만들어 져 있으니 사용하는데 크게 어렵진 않을거 같습니다.
소스를 보시면 알겠지만 기존 xml을 다루는 거와 비교해보면 월등히 간결합니다.
기존 xml과 관련된 많은 것들이 보이지도 않습니다.
한 30분 노력해서 앞으로 몇년을 써먹을 수 있다면 충분히 가치가 있다고 생각합니다.
try it~~~~