上一篇文章中大致讲了一下 Tomcat的Bootstrap、Catalina及Server之间的关系,这篇文章准备讲讲用来解析conf/server.xml的Digester工具类tomcat源码解析(三)——Digester类源码解析及Rule分析
我在看源码时,在Catalina中会看到大量的Digester代码段,这其实是Catalina解析server.xml配置的方式。
/**
* Create and configure the Digester we will be using for shutdown.
* @return the digester to process the stop operation
*/
protected Digester createStopDigester() {
// Initialize the digester
Digester digester = new Digester();
digester.setUseContextClassLoader(true);
// Configure the rules we need for shutting down
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
return digester;
}
为了便于理解,先上样例吧。
我的目的是将player.xml中的数据转换成的Player实例
player.xml
<player age="998" name="balabala">
<role name="worker"/>
</player>
Player.java和Role.java
/** 玩家 */
public class Player {
private String name;
private int age;
private Role role;
}
/** 角色 */
public class Role {
private String name;
}
期望输出
System.out.println(player);
Player{name='balabala', age=998, role=Role{name='worker'}}
实现代码
public class DigesterTest {
@Test
public void test() throws IOException, SAXException {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("player.xml");
Digester digester = createPlayerDigester();
Player player = (Player) digester.parse(inputStream);
System.out.println(player);
inputStream.close();
}
private Digester createPlayerDigester() {
Digester digester = new Digester();
digester.push(new Player());
digester.addSetProperties("player");
digester.addObjectCreate("player/role", "com.lance.test.digester.Role", "className");
digester.addSetProperties("player/role");
digester.addSetNext("player/role", "setRole", "com.lance.test.digester.Role");
return digester;
}
}
先不考虑代码细节,你会发现.xml的内容被解析成player对象,Tomcat的Catalina类也是一个道理,这只是用来解析server.xml等配置文件的。实现原理的细节可以参考上面提供的链接