xml読み込み用digester-rules
来源:互联网 发布:阿里巴巴域名 编辑:程序博客网 时间:2024/04/30 08:41
設定ファイルをXMLで書く事って多いんだけど、javaでXML使う時って型安全や妥当性に拘りすぎて仰々しいと時々思う。かといってPropertiesだと階層的なデータは表現し辛い。JSONやYAMLやObjective-Cのplistみたいに手軽に階層的なデータが使えると嬉しいと思う。
ということでCommonsDigester(初めて使った)でそれっぽいものを書いてみた。解説などは後ろで。
使用例
読み込むXMLファイル。レポートメールの設定ファイルのイメージで。
<?xml version = "1.0" encoding = "UTF-8" ?><map><string key="smtpHost">mx010</string><integer key="smtpPort">25</integer><string key="fromAddress">terazzo@example.com</string><string key="subject">Report Mail</string><list key="bccAddresses"><string>admin1@example.com</string><string>admin2@example.com</string><string>admin3@example.com</string></list><string key="templatePath">mail_template/ReportMail.html</string></map>
読み込みプログラム
String configPath = "config/sample.ReportMailer"; Map map = new Configuration(new File(configPath).toURL()); System.out.println("" + map);
出力結果(途中で適宜改行している)
{ templatePath=mail_template/ReportMail.html, smtpHost=mx010, smtpPort=25, fromAddress=terazzo@example.com, bccAddresses=[admin1@example.com, admin2@example.com, admin3@example.com], subject=Report Mail}
ソースコード
ルールファイル。もう少し簡単にかけそうだけど……
src/sample/config/collections-rule.xml:
<?xml version = "1.0" encoding = "UTF-8" ?> <digester-rules> <object-create-rule pattern="map" classname="java.util.HashMap"/> <pattern value="*/map/string"> <call-method-rule methodname="put" paramcount="2" paramtypes="java.lang.String,java.lang.String"/> <call-param-rule paramnumber="0" attrname="key"/> <call-param-rule paramnumber="1"/> </pattern> <pattern value="*/map/integer"> <call-method-rule methodname="put" paramcount="2" paramtypes="java.lang.String,java.lang.Integer"/> <call-param-rule paramnumber="0" attrname="key"/> <call-param-rule paramnumber="1"/> </pattern> <pattern value="*/map/map"> <object-create-rule classname="java.util.HashMap"/> <call-method-rule targetoffset="1" methodname="put" paramcount="2" /> <call-param-rule paramnumber="0" attrname="key"/> <call-param-rule paramnumber="1" from-stack="true"/> </pattern> <pattern value="*/map/list"> <object-create-rule classname="java.util.ArrayList"/> <call-method-rule targetoffset="1" methodname="put" paramcount="2" /> <call-param-rule paramnumber="0" attrname="key"/> <call-param-rule paramnumber="1" from-stack="true"/> </pattern> <pattern value="*/list/string"> <call-method-rule methodname="add" paramcount="1" paramtypes="java.lang.String"/> <call-param-rule paramnumber="0" /> </pattern> <pattern value="*/list/integer"> <call-method-rule methodname="add" paramcount="1" paramtypes="java.lang.Integer"/> <call-param-rule paramnumber="0" /> </pattern> <pattern value="*/list/map"> <object-create-rule classname="java.util.HashMap"/> <call-method-rule targetoffset="1" methodname="add" paramcount="1"/> <call-param-rule paramnumber="0" from-stack="true" /> </pattern> <pattern value="*/list/list"> <object-create-rule classname="java.util.ArrayList"/> <call-method-rule targetoffset="1" methodname="add" paramcount="1"/> <call-param-rule paramnumber="0" from-stack="true" /> </pattern></digester-rules>
読み込み用クラス
package sample.config;import java.net.URL;import java.util.Collection;import java.util.Map;import java.util.Set;import org.apache.commons.digester.Digester;import org.apache.commons.digester.xmlrules.DigesterLoader;/** * collections-rule.xmlを使ったDigesterによって設定ファイルを読み込むクラス */public class Configuration implements Map { private static final String RULE_XML_NAME = "collections-rule.xml"; /** * 設定ファイル読み込み用のDigester */ private static Digester digester = DigesterLoader.createDigester(Configuration.class.getResource(RULE_XML_NAME)); private URL url; private Map map; public Configuration(URL url) { super(); this.url = url; } private synchronized Map getMap() { if (needsReloading()) { this.map = load(url); } return this.map; } /** * urlからdigesterを使用してMapを読み込む * @param url URL * @return urlから読み込んだMap */ protected Map load(URL url) { try { return (Map)digester.parse(url); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException("Exception occurs while loading configuration.", e); } } /** * @return 再読み込みが必要ならtrueを戻す */ protected boolean needsReloading() { return this.map == null; } /** * mapのtoString()の結果を戻す */ public String toString() { return getMap().toString(); } /** * * @see java.util.Map#clear() */ public void clear() { getMap().clear(); } ... 以下委譲メソッドが続く}
環境
- J2SE 5.0
- commons-digester-1.8.jar
- commons-logging-1.0.4.jar
- commons-beanutils-core-1.7.0.jar
解説
- map/listが再帰的に使える。mapはHashMap、listはArrayListに変換される。
- ルートエレメントはmap
- map/list内にstring, integerを含める事が出来る
- map内のエレメントは、key=で指定された文字列をキーにHashMapにセットされる
- ConfigurationクラスはMapインタフェースを実装。但し読み込んだHashMapに委譲しているだけ。
その他
Commons Configurationを使いたかったけど、キーに対する値をMapで欲しい時って結構多いので微妙だ。(config.getMap("key")が欲しいのよ。)
あんまりMapをベタに使うのってjava wayじゃないよね。でもruleを毎回書かなくてよい楽さは異常なので重宝しますよ。
とは言えせめてキーぐらいはリテラルで書かずに使えるようにしたい。ということでその辺は次回。
- xml読み込み用digester-rules
- 用Digester解析XML
- 知识库--Digester+Rules(73)
- 用Digester处理XML配置文件
- xml | Digester
- 用Digester类解析XML数据
- 用Digester简化XML文档处理
- 用Digester简化XML文档处理
- 用Digester簡化XML配置文件處理
- 用Digester简化XML文档处理
- 用Digester简化XML文档处理
- 用Digester简化XML文档处理
- 用Digester解析xml到bean
- 用Digester解析xml到bean
- 用Digester解析xml到bean
- 用Digester解析xml到bean
- 用Digester解析xml到bean
- 用Digester解析xml到bean
- Rolling cURL: PHP并发最佳实践
- 我的财务自由和时间自由——3楼继续更新中
- SSH各层关系
- Django --- 从已有数据库生成模型 (model)
- Drupal Views开发过程中使用说明4
- xml読み込み用digester-rules
- 看起来很厉害的样子
- 关于乱码的那些事儿
- MongoDB管理与开发精要《红丸出品》4.10 客户端GUI工具
- C语言为什么必须有main函数
- 正确时间使用正确工具找到正确答案
- 关于复制文件或文件夹时提示没有足够的可用磁盘空间的解决办法-释放磁盘空间,磁盘整理
- IOCP应用
- QT:我自己封装的一个简易的二维表类SimpleTable