Digester解析xmlから話します.


struts 1はどのようにstruts-config.xmlファイルを解析しますか?ソースコードにはapacheのDigesterライブラリが使われています.これは初めてなので、よく調べてみました.
下のコードは、http://soft901.iteye.com/blog/335452の上から取ってきたものです.自分で改造して、自分のためだけに分かりやすいようにします.
読み込むXMLファイルdatasource.xml: 
 
<?xml version="1.0"?>
<datasources>
	<datasource>
		<name>mysqldatasource</name>
		<driver>com.jdbc.mysql.Driver</driver>
		<url>jdbc:mysql://localhost:3306/test</url>
		<username>root</username>
		<password>1234</password>
	</datasource>
	<datasource>
		<name>oracledatasource</name>
		<driver>oracle.jdbc.driver.oracledriver</driver>
		<url>jdbc:oracle:thin:@localhost:1521:orcl</url>
		<username>scott</username>
		<password>tiger</password>
	</datasource>
</datasources>
 このxmlファイルは2層構造に分けられています.それぞれ: 
 
<datasources>ノードの下には2つの<datasource>ノードが含まれている. クラスのDatasourceConfig.javaを設定します.その内容は以下の通りです. 
 
package xmlParse.digester;

public class DataSourceConfig {
	private String name;
	private String driver;
	private String url;
	private String username;
	private String password;

	public String getName() {
		return name;
	}

	public String getDriver() {
		return driver;
	}

	public String getUrl() {
		return url;
	}

	public String getUsername() {
		return username;
	}

	public String getPassword() {
		return password;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	 public String toString() {  
	        return "DataSource : " + "name : " + name + " Driver : " + driver  
	                + " URL : " + url + " Username : " + username + " Password : "  
	                + password;  
	 }  
}
 
解析するruleルールを設定する方法は4つあります.コードを一覧表示します.
 
最初にaddCallMethod方法を使用して、XMLに対応するノードとこのCall methodのパラメータをマッピングすればよく、このcall methodは読み取った一つのラベル内のすべての値を対象に預けて、もう一つのセットに保存します.
 
 
package xmlParse.digester;
/**
 *   digester   xml.
 */
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

public class DigesterParseTest {
	private List<DataSourceConfig> dataSources;

	public static void main(String[] args) {
		DigesterParseTest sd = new DigesterParseTest();
		sd.digester();
		System.out.println(sd.toString());
	}

	void digester() {
		Digester digester = new Digester();
		setDataSources(new ArrayList<DataSourceConfig>());
		//         digester  。
		digester.push(this);
		/*      xml      */
		//  XML          .this.addDataSource();     5 .
		digester.addCallMethod("datasources/datasource", "addDataSource", 5);
		digester.addCallParam("datasources/datasource/name", 0);
		digester.addCallParam("datasources/datasource/driver", 1);
		digester.addCallParam("datasources/datasource/url", 2);
		digester.addCallParam("datasources/datasource/username", 3);
		digester.addCallParam("datasources/datasource/password", 4);

		try {
			digester.parse("config/datasource.xml");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
	
	public void addDataSource(final String name, final String driver,
			final String url, final String username, final String password) {
		DataSourceConfig dataSource = new DataSourceConfig();
		dataSource.setName(name);
		dataSource.setDriver(driver);
		dataSource.setUrl(url);
		dataSource.setUsername(username);
		dataSource.setPassword(password);
		getDataSources().add(dataSource);
	}
	
	public List<DataSourceConfig> getDataSources() {
		return dataSources;
	}

	public void setDataSources(List<DataSourceConfig> dataSources) {
		this.dataSources = dataSources;
	}

	public String toString() {
		String newline = System.getProperty("line.separator");
		StringBuffer buff = new StringBuffer();
		if (getDataSources() != null) {
			for (DataSourceConfig ds : getDataSources()) {
				buff.append(newline).append(ds);
			}
			return buff.toString();
		}
		return "";
	}
}
 
 
第二の方法は、addObject Createを使用して、オブジェクトマッピングXMLファイルの属性対java Beanを作成します.一つのオブジェクトを読み取り終わったら、一つのセットにオブジェクトを追加して、XMLファイルの次のタブを読みます. 
 
package xmlParse.digester;
/**
 *   digester   xml.
 */
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

public class DigesterParseTest2 {
	private List<DataSourceConfig> dataSources;

	public static void main(String[] args) {
		DigesterParseTest sd = new DigesterParseTest();
		sd.digester();
		System.out.println(sd.toString());
	}
	private void digester() {
		Digester digester = new Digester();
		setDataSources(new ArrayList<DataSourceConfig>());
		//         digester  。
		digester.push(this);
		
		/*      xml      */
		digester.addObjectCreate("datasources/datasource", DataSourceConfig.class);
		
		//   addSetProperties  
//		digester.addBeanPropertySetter("datasources/datasource/name","name");
//		digester.addBeanPropertySetter("datasources/datasource/driver", "driver");
//		digester.addBeanPropertySetter("datasources/datasource/url", "url");
//		digester.addBeanPropertySetter("datasources/datasource/username", "username");
//		digester.addBeanPropertySetter("datasources/datasource/password", "password");
		digester.addSetProperties("datasources/datasource/name");
		digester.addSetProperties("datasources/datasource/driver");
		digester.addSetProperties("datasources/datasource/url");
		digester.addSetProperties("datasources/datasource/username");
		digester.addSetProperties("datasources/datasource/password");
		digester.addSetNext("datasources/datasource", "addDataSource");
		try {
			digester.parse("config/datasource.xml");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
	
	public void addDataSource(final DataSourceConfig datasource){
		getDataSources().add(datasource);
	}
	public List<DataSourceConfig> getDataSources() {
		return dataSources;
	}

	public void setDataSources(List<DataSourceConfig> dataSources) {
		this.dataSources = dataSources;
	}

	public String toString() {
		String newline = System.getProperty("line.separator");
		StringBuffer buff = new StringBuffer();
		if (getDataSources() != null) {
			for (DataSourceConfig ds : getDataSources()) {
				buff.append(newline).append(ds);
			}
			return buff.toString();
		}
		return "";
	}
}
 
 
第三の方法:addRuleを使用してdatasource.xmlを解析する. 
 
private void digester() {
	Digester digester = new Digester();

	setDataSources(new Vector<DataSource>());
	//         digester  。
	digester.push(this);

	Rule objectCreate = new ObjectCreateRule(DataSource.class);
	digester.addRule("datasources/datasource", objectCreate);

	digester.addRule("datasources/datasource", new SetNextRule(
			"addDataSource"));

	digester.addRule("datasources/datasource/name", new CallMethodRule(
			"setName", 0, new Class[] { String.class }));
	digester.addRule("datasources/datasource/driver", new CallMethodRule(
			"setDriver", 0, new Class[] { String.class }));
	digester.addRule("datasources/datasource/url", new CallMethodRule(
			"setUrl", 0, new Class[] { String.class }));
	digester.addRule("datasources/datasource/username", new CallMethodRule(
			"setUsername", 0, new Class[] { String.class }));
	digester.addRule("datasources/datasource/password", new CallMethodRule(
			"setPassword", 0, new Class[] { String.class }));
	try {
		digester.parse("datasource.xml");
	} catch (IOException e) {
		e.printStackTrace();
	} catch (SAXException e) {
		e.printStackTrace();
	}
}
 
 
第四種類:規則をxmlファイルに書きます.新しいrules.xml
 
<? xml version = " 1.0 " ?>
<digester-rules>
	<object-create-rule pattern=" datasources "
		classname=" datasources " />
	<pattern value=" datasources/datasource ">
		<object-create-rule classname=" datasource " />
		<call-method-rule pattern=" name " methodname=" setName "
			paramcount=" 0 " />
		<call-method-rule pattern=" driver " methodname=" setDriver "
			paramcount=" 0 " />
		<call-method-rule pattern=" url " methodname=" setUrl "
			paramcount=" 0 " />
		<call-method-rule pattern=" username " methodname=" setUsername "
			paramcount=" 0 " />
		<call-method-rule pattern=" password " methodname=" setPassword "
			paramcount=" 0 " />
		<set-next-rule methodname=" addDatasource " />
	</pattern>
	
</digester-rules>
 
digesterの方法は以下の通りです.
 
private void digester() {
		setDataSources(new ArrayList<DataSourceConfig>());
		try {
			File rules = new File("config/rules.xml");
			//  digester         
			Digester digester = DigesterLoader.createDigester(rules.toURL());
			digester.parse("config/datasource.xml");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}
 
以上がdigesterの四つの解析方法です.これらの例はただ直観的な説明にすぎない.竹の子の肉炒めの三編はdigesterのメモに関してもっと深く説明しました.リンク先:
digester学習ノート1
digester学習ノート2
digester学習ノート3
common-digester-2.0 API公式サイトを添付します.
 
文章の冒頭に戻って言ったのですが、digesterはstrutsがどのように配置ファイルを解析しているかを知るためです.自分で整理したいですが、struts学習--Moude Configを初期化するを発見しました. ちょうどよく説明されています.DataSourceConfigラベルを解析するだけの例で、RuleSet配置説明を少し補足します.
  ActionServlet     configDigester         struts-config.xml     ,          org.apache.struts.config.impl.ModuleConfigImpl   。 

configDigester    RuleSet  ConfigRuleSet,        public void addRuleInstances(Digester digester)  digester  Rule,      : 

1.  ModuleConfigImpl       DataSourceConfig  : 
/* 1.1   struts-config/data-sources/data-source           className        ,    className  ,   org.apache.struts.config.DataSourceConfig  ,   ;           。*/ 

digester.addObjectCreate 
("struts-config/data-sources/data-source", "org.apache.struts.config.DataSourceConfig", "className"); 
/*1.2    struts-config/data-sources/data-source       data-source                 */ 
digester.addSetProperties 
("struts-config/data-sources/data-source"); 

/*1.3   struts-config/data-sources/data-source             ModuleConfigImpl   addDataSourceConfig  ,       DataSourceConfig    ,struts-config/data-sources/data-source   key       ModuleConfigImpl HashMap      dataSources 。*/ 
digester.addSetNext 
("struts-config/data-sources/data-source", "addDataSourceConfig", "org.apache.struts.config.DataSourceConfig"); 

/*1.4     set-property   property    key,value          DataSourceConfig   HashMap      properties 。*/ digester.addRule 
("struts-config/data-sources/data-source/set-property", new AddDataSourcePropertyRule());