Digester parsing XML file

The bottom layer of TOMCAT is used for parsing server.xml.

 

Dom4j reads all an xml file into memory and builds it into a DOM tree for parsing, so Dom4j is suitable for reading relatively small xml files.

SAX parses the xml file based on the file stream. When reading the xml file stream, SAX will trigger the corresponding operation through the node. It can also be said that SAX parses the xml file based on the event trigger mechanism of the file stream.

Digeter is a common project of apache. Its function is to convert XML into an object, and users can directly obtain the node information of XML from the object. Digester is a wrapper for SAX. It also parses xml files based on file streams, but these parsing operations are transparent to users. Tomcat's configuration file conf/server.xml is read with Digester.

 

    The toolkits generally used to read xml files include DOM, SAX, and JDOM , etc., but those who have used them know that they are relatively low-level APIs, and the amount of code written is very large, and if the format of the xml file is modified, the code Significant changes are also required. Using Apache Jakarta's Digester, parsing XML files is very convenient and does not require too much attention to the underlying specific parsing process. Digester was originally just a tool in Jakarta Struts for processing struts-config.xml configuration files. Obviously, converting XML files into corresponding Java objects is a very general function, and this tool should have a wider range of uses, so soon it will be in the Jakarta Commons project (for providing a library of reusable Java components) a place. Digester is driven by "events" and converts XML files into Java objects by invoking predefined rules to manipulate object stacks .

 

    It works as follows:

              The bottom layer of Digester uses SAX (Simple API for XML) to parse XML files, so it is natural that object conversion is driven by "events". When traversing each node, it checks whether there is a matching pattern, and if so, executes the operation defined by the rule. For example, creating a specific Java object, or calling a method of a specific object, etc. The XML elements here are identified according to matching patterns, and the associated actions are defined by rules.

 

    The following xml code, the right side is the matching pattern corresponding to the left element:

<datasources>          'datasources'
  <datasource>         'datasources/datasource'
    <name/>            'datasources/datasource/name'
    <driver/>          'datasources/datasource/driver'  
  </datasource>
  <datasource>         'datasources/datasource'
    <name/>            'datasources/datasource/name'
    <driver/>          'datasources/datasource/driver'  
  </datasource>
</datasources>

 

Tomcat's relationship with Digester (note this blog, many resources)

Digester is used to parse conf/server.xml in catalina of Tomcat source code

Three Common Digester Examples

In-depth analysis of Tomcat-Digester

Understanding Tomcat (1) Using Digester to parse xml files

Digester handles multiple layers of XML (careful analysis)

 

Parsing XML configuration files with Digester

Common techniques for parsing XML

 

 ==============================================================================

<?xml version="1.0" encoding="UTF-8?>  
<database>  
    <user userName="guest" password="guest">  
    </user>  
</database>  

 1.addObjectCreate(String rule,Class class)

设置节点与Java对象的映射规则,rule指定节点的筛选规则,class设置映射对象。SAX解析时,遇到rule指定的节节点,会创建一个class实例放入堆栈中。

比如:digester.addObectCreate("database/user","com.model.UserBean").解析遇到user节点时,会创建一个UserBean实例并放入堆栈中。

 

2.addSetProperties(String rule)

设置节点的属性设置规则。当解析遇到符合rule的节点时,根据属性列表中的属性值对,使用Java反射机制使用标准的JavaBean方法设置栈顶对象实例;

比如:digester.addSetProperties("database/user"),解析遇到user节点时,会获取键值对 userName=guest,password=guest,获得栈顶的UserBean对象,设置实例的userName、password属性;

解析元素上的属性 

 

3.addBeanPropertySetter(String rule)

该方法的作用及使用方法类似于addSetProperties,只不过它是用rule所指定的标签来调用对象的setter。

该方法在tomcat6中貌似没有。 

tomcat6中Digester类路径为:import org.apache.tomcat.util.digester.Digester;

不为:import org.apache.commons.digester.Digester;

 

4.addSetNext(String rule,String methodName)

设置当前rule节点与父节点的调用规则,当遇到rule节点时,调用堆栈中的次栈顶元素调用methodName方法。将栈顶元素作为次顶元素指定方法的输入参数。

比如:digester.addSetNext("database/user","addUser"),调用database实例的addUser,user为参数

 

5.addCallMethod(String rule,String methodName,int paraNumber)

该方法同样设置对象的属性,但更加灵活,不需要对象具有setter

根据rule规则指定的属性,调用对象的methodName方法,paraNumber参数是表示方法需要的参数个数,当paraNumber=0时,可以单独使用,不然需要配合addCallParam方法

比如:digester.addCallMethod("database/user/uerName","setUserName",0);

 

6.addCallParam(String rule,int paraIndex,String attributeName)

该方法与addCallMethod配合使用,根据rule指定的标签属性来调用方法

paraIndex表明需要填充的方法形参序号,从0开始,方法由addCallMethdo指定,attributeName指定标签属性名;

 

使用注意事项:

   1.Digester类调用的顺序,必须与XML数据文件绝对一致;

   2.Digester类依赖于JavaBean规范,类必须符合规范;

   3.XML文件中标签/属性的名称必须与Bean中的一致(包括大小写);

 

 ==================================================================

 关键方法说明

(1)    serverDigester.addObjectCreate("Server","com.test.server.digester.Server")

当解析xml文件时,遇到“Server”就初始化一个“com.test.server.digester.Server”对象,并且把该对象压入栈顶

(2)    serverDigester.addSetProperties("Server", "port", "port")

给Server对象注册port属性,当解析到Server节点的port属性时调用Server的setPort方法

(3)    serverDigester.addSetNext("Server/Listener", "addListener","com.test.server.digester.Listener")

当解析Server节点下的Listener节点的时候,调用Server对象的addListener方法,把当前Listener对象写入到Server对象中。无论Server节点下有多少个Listener节点,都会调用addListener方法

(4)    serverDigester.addCallMethod("Server/Service/Engine", "setEngine", 0)

Service中添加Engine,调用当前top object的setEngine函数,参数个数为0

addCallMethod与addBeanPropertySetter方法等价

 

Example1:

<?xml version="1.0" encoding="ISO-8859-1"?>
<student name="llin" age="16" grade="3">
    <subject name="math" teacher="yu" />
</student>

 

package digester;

import java.util.ArrayList;

public class Student {
    private String name;
    private int age;
    private int grade;
    private ArrayList<Subject> list = new ArrayList();
    
    public Student (){
        System.out.println("A student go to school");
    }

    public void add ( Subject subjects ){
        System.out.println("add Subjects " + subjects.getName() + " to the Student: "+ this.getName());
        list.add( subjects );
    }      
    /////////////////////////////////////////////////
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println( " set age of Student:" + name);
        this.age = age;
    }

    public int getGrade() {
        return grade;
    }

    public void setGrade(int grade) {
        System.out.println( " set score of Student:" + name );
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println(" set name pf Student" );
        this.name = name;
    }

    public ArrayList<Subject> getList (){
        return this.list;
    }
}

 

package digester;

public class Subject {
    private String name;
    private String teacher;

    public Subject() {
        System.out.println("One subjects waiting scheduling!");
    }

    public void print() {
        System.out.println("Subjects  :" + name + "of " + teacher + "in schedule");
    }    
    /////////////////////////////////////////////////////    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println(" set name of Subjects:" + name);
        this.name = name;
    }

    public String getTeacher() {
        return teacher;
    }

    public void setTeacher(String teacher) {
        System.out.println(" set teacher of Subjects :" + teacher);
        this.teacher = teacher;
    }   
}

 

 

package digester;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import org.apache.tomcat.util.digester.Digester;
import org.xml.sax.SAXException;

public class StudentDigesterTest {
	public static void main ( String [] args ) throws IOException{
		unUseRule();
		//useRule();
    }	
	
	public static void unUseRule(){
		File xml = new File( "../apache-tomcat-6.0.41-src/test/student.xml");
        Digester digester = new Digester();
        
        digester.addObjectCreate( "student" , "digester.Student" );
        digester.addSetProperties("student");
        digester.addObjectCreate("student/subject" , "digester.Subject");
        digester.addSetProperties("student/subject");
        //上面该句可用这句代替digester.addSetProperties("student/subject","subject","subject");
/**
* public void addSetProperties(String pattern,String attributeName,String propertyName)
*/
        digester.addSetNext("student/subject" , "add" );
        
        Student student = null;
        try {
            student = (Student)digester.parse(xml);
        }catch ( SAXException e ){
            System.out.println("parse with mistakes!");
        } catch (IOException e) {
			e.printStackTrace();
		}
        Iterator it = student.getList().iterator();
        while ( it.hasNext()) {

        }
	}
	
	public static void useRule(){
		File xml = new File( "../apache-tomcat-6.0.41-src/test/student.xml");
        Digester digester = new Digester();
        digester.addRuleSet(new MyRuleSet());
        
        Student student = null;
        try {
            student = (Student)digester.parse(xml);
        }catch ( SAXException e ){
            System.out.println("parse with mistakes!");
        } catch (IOException e) {
			e.printStackTrace();
		}
        Iterator it = student.getList().iterator();
        while ( it.hasNext()) {

        }
	}
}

  

package digester;

import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.digester.RuleSetBase;

public class MyRuleSet  extends RuleSetBase{
    @Override
    public void addRuleInstances(Digester digester) {
    	digester.addObjectCreate( "student" , "digester.Student" );
        digester.addSetProperties("student");
        digester.addObjectCreate("student/subject" , "digester.Subject");
        digester.addSetProperties("student/subject");
        digester.addSetNext("student/subject" , "add" );
    }
}

 

 两种方法结果都为:


 

 Example2:

viewcache2.xml:

<?xml version="1.0" encoding="UTF-8" ?>  
<viewcache>  
    <areas>  
        <area id="1098" parentId="1001" areaType="province" name="上海" ordering="1867" phoneArea="111"/> 
        <area id="1099" parentId="1098" areaType="capital" name="北京" ordering="1868" phoneArea="010"/>
    </areas>  
</viewcache> 

 

package digester;
import java.util.ArrayList;
import java.util.List;

public class ViewCache {  
    private ArrayList<Area> areaList             = new ArrayList<Area>();  

    
    public ArrayList getAreaList() {
		return areaList;
	}


	public void setAreaList(ArrayList areaList) {
		this.areaList = areaList;
	}


	// 供Digester调用的方法  
    public void addArea(Area area) {  
    	System.out.println("addArea..");
        this.areaList.add(area);  
    }  
}  

 

package digester;

public class Area {  
    private int    id;  
    private String name;  
    private String areaType;  
    private int    parentId;  
    private int    ordering;  
//    private String zip;  
      
    private String phoneArea;

    public Area(){
    	System.out.println("Area constructor..");
    }
    
	public int getId() {
		return id;
	}

	public void setId(int id) {
		System.out.println( " set id of Area:" + id);
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println( " set name of Area:" + name);
		this.name = name;
	}

	public String getAreaType() {
		return areaType;
	}

	public void setAreaType(String areaType) {
		System.out.println( " set areaType of Area:" + areaType);
		this.areaType = areaType;
	}

	public int getParentId() {
		return parentId;
	}

	public void setParentId(int parentId) {
		System.out.println( " set parentId of Area:" + parentId);
		this.parentId = parentId;
	}

	public int getOrdering() {
		return ordering;
	}

	public void setOrdering(int ordering) {
		System.out.println( " set ordering of Area:" + ordering);
		this.ordering = ordering;
	}

	/*public String getZip() {
		return zip;
	}

	public void setZip(String zip) {
		this.zip = zip;
	}*/

	public String getPhoneArea() {
		return phoneArea;
	}

	public void setPhoneArea(String phoneArea) {
		System.out.println( " set phoneArea of Area:" + phoneArea);
		this.phoneArea = phoneArea;
	}  
    
    
}

 

package digester;
import java.io.IOException;

import org.apache.tomcat.util.digester.Digester;
import org.xml.sax.SAXException;

public class AreaDigester {  
      
    public ViewCache digester() throws Exception {  
        Digester digester = new Digester();  
        digester.setValidating(false);  
        digester.addObjectCreate("viewcache/areas", ViewCache.class);  
        // 指明匹配模式和要创建的类   
        digester.addObjectCreate("viewcache/areas/area", Area.class);  
        
        //使用这句可以打印出Area字段set值时的syso语句,下面的打印不出,没搞清楚。。。
        digester.addSetProperties("viewcache/areas/area");  
       
//        digester.addSetProperties("viewcache/areas/area/id");  
//        digester.addSetProperties("viewcache/areas/area/parentId", "parentId", "parentId");  
//        digester.addSetProperties("viewcache/areas/area/name", "name", "name");  
//        digester.addSetProperties("viewcache/areas/area/areaType", "areaType", "areaType");  
//        digester.addSetProperties("viewcache/areas/area/ordering", "ordering", "ordering");  
//        //digester.addSetProperties("viewcache/areas/area/zip", "zip", "zip");  
//        digester.addSetProperties("viewcache/areas/area/phoneArea", "phoneArea", "phoneArea");  

        // 当移动到下一个标签中时的动作  
        digester.addSetNext("viewcache/areas/area", "addArea");  
          
        ViewCache vc = null;  
        try {  
            vc = (ViewCache) digester.parse("../apache-tomcat-6.0.41-src/test/viewcache2.xml");  
        } catch (IOException e) {  
            throw new Exception(e);  
        } catch (SAXException e) {  
            throw new Exception(e);  
        }  
        return vc;  
    }  
    
    public static void main(String[] args) {
		AreaDigester m = new AreaDigester();
		ViewCache vc = null;
		try {
			vc = m.digester();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}  

 结果:



 

 

 

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326567617&siteId=291194637