转自:http://blog.csdn.net/flyliuweisky547/article/details/23872231
Tomcat是利用Digester解析server.xml。Digester是Apache下的开源项目
Digester官网:http://commons.apache.org/proper/commons-digester/
使用Digester,需要依赖一些jar包。Digester依赖的jar包可以从网上下载,也可以使用Tomcat提供的jar包
方案一:从网上下载jar包
commons-beanutils.jar
commons-digester.jar
commons-logging.jar
commons-collections.jar(下载commons-collections-3。commons-collections-4将commons-collections的package命名由org.apache.commons.collections改为org.apache.commons.collections4,而Digester内部仍按org.apache.commons.collections使用的)
方案二:使用Tomcat目录下的jar包
tomcat-juli.jar($CATALINA_HOME\bin)
tomcat-util.jar($CATALINA_HOME\lib)
tomcat-util-scan.jar($CATALINA_HOME\lib)
本文采用方案一
下面来看看Digester如何解析School.xml
- <?xml version='1.0' encoding='utf-8'?>
- <School name="CSDN">
- <Grade name="1">
- <Class name="1" number="31"/>
- <Class name="2" number="32"/>
- </Grade>
- <Grade name="2">
- <Class name="1" number="41"/>
- <Class name="2" number="42"/>
- </Grade>
- </School>
School是School.xml的最顶层节点,School节点下包含Grade节点,Grade节点下包含Class节点。(学校下有两个年级,每个年级下有两个班级,班级下的number表示人数)
首先要创建与School.xml中各个节点对应的实体类School.java、Grade.java、Class.java(这些类都放在digester包下)
School.java
- package digester;
-
- public class School {
- private String name;
- private Grade grades[] = new Grade[0];
- private final Object servicesLock = new Object();
-
- public void addGrade(Grade g){
- synchronized (servicesLock) {
- Grade results[] = new Grade[grades.length + 1];
- System.arraycopy(grades, 0, results, 0, grades.length);
- results[grades.length] = g;
- grades = results;
- }
- }
-
- public Grade[] getGrades() {
- return grades;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- }
School里的Grade数组用来存放School包含的Grade。调用School. addGrade(Grade g),可以往Grade数组添加Grade
Grade.java
- package digester;
-
- public class Grade {
- private String name;
- private Class classes[] = new Class[0];
- private final Object servicesLock = new Object();
-
- public void addClass(Class c){
- synchronized (servicesLock) {
- Class results[] = new Class[classes.length + 1];
- System.arraycopy(classes, 0, results, 0, classes.length);
- results[classes.length] = c;
- classes = results;
- }
- }
-
- public Class[] getClasses() {
- return classes;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- }
Class.java
- package digester;
-
- public class Class {
- private String name;
- private int number;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getNumber() {
- return number;
- }
-
- public void setNumber(int number) {
- this.number = number;
- }
-
- }
然后创建测试类DigesterTest.java。DigesterTest.java的digester方法用来读取School.xml、创建Digester并设置规则、解析School.xml;print方法用来打印School的信息
- package digester;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
-
- import org.apache.tomcat.util.digester.Digester;
- import org.xml.sax.InputSource;
- import org.xml.sax.SAXException;
-
- public class DigesterTest {
- private School school;
-
- public School getSchool() {
- return school;
- }
-
- public void setSchool(School s) {
- this.school = s;
- }
-
- public void digester() throws IOException, SAXException{
-
- File file = new File("D:\\School.xml");
- InputStream inputStream = new FileInputStream(file);
- InputSource inputSource = new InputSource(file.toURI().toURL().toString());;
- inputSource.setByteStream(inputStream);
-
- Digester digester = new Digester();
-
- digester.setValidating(false);
-
- digester.push(this);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- digester.addObjectCreate("School",
- "digester.School",
- "className");
-
- digester.addSetProperties("School");
-
-
-
-
-
-
-
- digester.addSetNext("School",
- "setSchool",
- "digester.School");
-
-
- digester.addObjectCreate("School/Grade",
- "digester.Grade",
- "className");
- digester.addSetProperties("School/Grade");
-
- digester.addSetNext("School/Grade",
- "addGrade",
- "digester.Grade");
-
-
- digester.addObjectCreate("School/Grade/Class",
- "digester.Class",
- "className");
- digester.addSetProperties("School/Grade/Class");
- digester.addSetNext("School/Grade/Class",
- "addClass",
- "digester.Class");
- digester.parse(inputSource);
- }
-
-
- public void print(School s){
- if(s!=null){
- System.out.println(s.getName() + "有" + s.getGrades().length + "个年级");
- for(int i=0;i<s.getGrades().length;i++){
- if(s.getGrades()[i] !=null){
- Grade g = s.getGrades()[i];
- System.out.println(g.getName() + "年级 有 " + g.getClasses().length + "个班:");
- for(int j=0;j<g.getClasses().length;j++){
- if(g.getClasses()[j] !=null){
- Class c = g.getClasses()[j];
- System.out.println(c.getName() + "班有" + c.getNumber() + "人");
- }
- }
- }
- }
- }
- }
-
- public static void main(String[] args) throws IOException, SAXException {
- DigesterTest digesterTest = new DigesterTest();
- digesterTest.digester();
- digesterTest.print(digesterTest.school);
- }
- }
DigesterTest的输出:
- CSDN有2个年级
- 1年级 有 2个班:
- 1班有31人
- 2班有32人
- 2年级 有 2个班:
- 1班有41人
- 2班有42人
Tomcat解析server.xml是在Catalina的load方法内进行的。load方法可以划分成三步:
1. 创建Digester并设置规则
load方法内通过Digester digester = createStartDigester()创建Digester 并设置规则。createStartDigester也是Catalina内的方法
createStartDigester方法的内容(为了简介,每种创建规则的方式各列一个)
- protected Digester createStartDigester() {
- Digester digester = new Digester();
- digester.setValidating(false);
- digester.setRulesValidation(true);
- HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
- ArrayList<String> attrs = new ArrayList<>();
- attrs.add("className");
- fakeAttributes.put(Object.class, attrs);
- digester.setFakeAttributes(fakeAttributes);
- digester.setUseContextClassLoader(true);
-
- digester.addObjectCreate("Server",
- "org.apache.catalina.core.StandardServer",
- "className");
- digester.addSetProperties("Server");
-
- digester.addSetNext("Server",
- "setServer",
- "org.apache.catalina.Server");
-
- digester.addObjectCreate("Server/Service",
- "org.apache.catalina.core.StandardService",
- "className");
- digester.addSetProperties("Server/Service");
-
- digester.addSetNext("Server/Service",
- "addService",
- "org.apache.catalina.Service");
-
- digester.addRule("Server/Service/Connector",
- new ConnectorCreateRule());
-
-
-
-
-
-
- digester.addRuleSet(new EngineRuleSet("Server/Service/"));
-
- addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
- }
2. 读取server.xml文件
- InputSource inputSource = null;
- InputStream inputStream = null;
- File file = null;
- try {
- file = configFile();
- inputStream = new FileInputStream(file);
- inputSource = new InputSource(file.toURI().toURL().toString());
- } catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("catalina.configFail", file), e);
- }
- }
3. 利用Digester解析xml文件
- try {
- inputSource.setByteStream(inputStream);
- digester.push(this);
- digester.parse(inputSource);
- } catch (SAXParseException spe) {
- log.warn("Catalina.start using " + getConfigFile() + ": " +
- spe.getMessage());
- return;
- } catch (Exception e) {
- log.warn("Catalina.start using " + getConfigFile() + ": " , e);
- return;
- } finally {
- try {
- inputStream.close();
- } catch (IOException e) {
-
- }
- }
参考文章:
http://blog.csdn.net/caihaijiang/article/details/5944955
http://www.cnblogs.com/bjzhanghao/archive/2005/03/25/125747.html