`

关于struts框架中的xml解析

    博客分类:
  • XML
阅读更多
degister In Action (xml解析)
引言

  前前后后,研究struts 的框架源代码,也有几回了,一直没有找到其解析XML 配置文件的代码 =.= !,其实是被误导了(想当然的以为它会用DOM4j或JDOM),前几天,又拿来struts的源码来跟,发现了些端倪.就仔细研究了一下,意外发现了一个很好用的解析XML的东西,即org.apache.common.digester 包.
 在网上求证了一下,发现原本digester 包是和Struts一起发布的,原来只是为了解析struts-config.xml配置文件而设计的,后来发现这个包解析xml很通用,也很好用,于是,放到了commons库中.笔者小试了一下,发现果然方便,它可以直接将XML文档转换成对象,它的目标是以尽可能简单的方式把xml文件转换成对象,思想上有点类似ORM,也许以后可以起个名字叫OXM(object-xml-mapping)在本文中,也将采用OXM这个词汇.
   
 
      注:本文不适合java以及struts初学者阅读,读者最好有通过SAX或DOM解析XML的经验,的经,以便更好的理解..

CH.1   digester   小窥


这一章是一个小的示例,用来像大家展示使用digester来解析xml的基本的流程.以及,使用digester来进行了xml解析是多么的简洁和简单. 本节的示例不要求你能马上读懂,在以后的章节我还会对每个类进行更详细的讲解.
好吧,让我们开始我们的digester之旅.



1.1  一个简单的xml解析示例

首先,在项目中导入commons-digester.jar包以及关联包commons-collections.jar ,commons-beanutils.jar ,commons-logging.jar.
 


然后,建立一个要解析的名为simple.xml的xml文档 代码如下.

Xml代码
<?xml version="1.0" encoding="UTF-8"?> 
<person  name="7upcat"  age="24"> 
  <address>深 圳 市 下 梅 林 </address> 
</person> 

<?xml version="1.0" encoding="UTF-8"?>
<person  name="7upcat"  age="24">
  <address>深 圳 市 下 梅 林 </address>
</person>


接着,建立,一个同这个xml文档进行映射的pojo类.
Java代码
package com.zhengzm.prj.digester;  
 
/** 
*  
* @author 7upCat 
*  
*/ 
public class Person {  
 
private String age;  
private String name;  
private String address;  
 
public String getAge() {  
return age;  
}  
 
public void setAge(String age) {  
this.age = age;  
}  
 
public String getName() {  
return name;  
}  
 
public void setName(String name) {  
this.name = name;  
}  
 
public String getAddress() {  
return address;  
}  
 
public void setAddress(String address) {  
this.address = address;  
}  
 
}  
 
 
解析代码如下.  
 
 
package com.zhengzm.prj.digester.simple_example;  
 
import java.io.File;  
import java.io.IOException;  
 
import org.apache.commons.digester.Digester;  
import org.xml.sax.SAXException;  
 
public class TestDigester {  
 
      
      
    public static void main(String[] args) throws IOException, SAXException {  
          
        //创建解析对象digester  
         Digester  digester=new Digester();  
         //为digester对象填加解析规则  
         digester.addObjectCreate("person/", Person.class);  
         digester.addSetProperties("person/");  
         digester.addBeanPropertySetter("person/address","address");  
         //解析xml文档返回Person对象.  
         Person o=(Person)digester.parse(new File("simpleXml.xml"));  
         //输出这个对象的值  
                  System.out.println("the person is "+ o.getName() );  
               System.out.println("she/he is"+ o.getAge()+"years old");  
               System.out.println("she/he lives in "+o.getAddress());  
    }  


package com.zhengzm.prj.digester;

/**
*
* @author 7upCat
*
*/
public class Person {

private String age;
private String name;
private String address;

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

public String getName() {
return name;
}

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

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

}


解析代码如下.


package com.zhengzm.prj.digester.simple_example;

import java.io.File;
import java.io.IOException;

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

public class TestDigester {



public static void main(String[] args) throws IOException, SAXException {

//创建解析对象digester
Digester  digester=new Digester();
//为digester对象填加解析规则
digester.addObjectCreate("person/", Person.class);
digester.addSetProperties("person/");
digester.addBeanPropertySetter("person/address","address");
//解析xml文档返回Person对象.
Person o=(Person)digester.parse(new File("simpleXml.xml"));
//输出这个对象的值
                  System.out.println("the person is "+ o.getName() );
               System.out.println("she/he is"+ o.getAge()+"years old");
               System.out.println("she/he lives in "+o.getAddress());
}
}

控制台输出结果如下:

the person is 7upcat
she/he is24years old
she/he lives in 深 圳 市 下 梅 林



我们看到simple.xml文档被解析后直接生成了一个Person对象,然后我们就可以直接对Person对象进行操作..
其它的xml解析方式,无论是SAX,还是DOM,都无法直接做到这点(其实digester是对SAX的简单封装),并且,Struts的配置文件是由degister来解析的, 它在实际应用中.表现也很稳定.
     
       其实这一章可以写一下,其实的很多种解析xml的工具的代码,来分别和digester进行比较一下.但是时间实在是有限(=.= !  要上班ING).,就不一一列举了.
       下一章我们将介绍digester中的核心类Digester 和Rule  的api.以及digester的实现相制.
    


CH2.   digester  API   introduction   (好像名字有点大咧  )



这一章将介绍digester中的两个核心的类Digester 以及Rule并,让你明白digester的实现机制,当然,暂时不打算从源代码级别讲起,因为那个太花精力,而且,我们主要是学如何使用它(这符合XP思想?  其实可能只是作者太忙了没有时间专门去研究 ^^) 

2.1   Digester类.

  digester包中最重要的类就是Digester了.整个解析过程实际上就是通过调用这个对象的 java.lang.Object parse(java.io.File file)   方法来进行的,这个方法的返回值是所解析xml文档的根元素对应的对象,它还包括很多个重载版本,参数分别可以接受,InputStream,java.io.Reader,java.net.URL,等.
                 

  org.xml.sax.helpers.DefaultHandler
        |
        +--org.apache.commons.digester.Digester


由上面的继承结构可以看出,Digester是DefaultHandler的子类,可以推断出digester 包实际上是对SAX  api的简单封装, 我们知道SAX解析XML是基于事件的,那当然,在digester中也是如此.整个解析过程将触发一系列事件,然后我们通过处理这些事件来完成我们的工作.
下面我们就使用Digester来解析一个XML文档吧.


在项目中建立person.xml如下:

Xml代码
<?xml version="1.0" encoding="UTF-8"?> 
<person name="7upCat" age="24"> 
   <address city="深 圳 " street="梅 林 ">   
   </address> 
   <friend name="vincent"></friend> 
   <friend name="鱼 生 烟 "></friend>         
</person> 

<?xml version="1.0" encoding="UTF-8"?>
<person name="7upCat" age="24">
   <address city="深 圳 " street="梅 林 ">
   </address>
   <friend name="vincent"></friend>
   <friend name="鱼 生 烟 "></friend>      
</person>




从这个XML文件中可以看出,对于每个person 都会有 name和age两个属性,并且,每个person节点都会有多个friends子节点,有一个address子节点.
    我们的目标是,通过解析上面的XML文件,得到一个Person对象,并且这个对象中包含多个Friend对象的集合,一个Address对象.





接着,建立需要做 OXM的 pojo (plain old java object)类(^^相信,如果读者有用过hibernate的经验应该可以很容易理解).
     注: pojo  就是符合javabean规范的普通的java对象.(含setter getter)



Person 类.
Java代码
 
package com.zhengzm.prj.digester.ch2.pojo;  
 
import java.util.Vector;  
 
/** 
* 每 一 个 person中 包 含 了 ,这 个 人 的 名 字 ,年 龄 ,居 住 地 址 address对 象 ,朋 友 的 集 合 friends 
*  
* @author 7upCat 
*  
*/ 
public class Person {  
private String name;  
private String age;  
public Address address;  
 
 
 
 
/** 
* friends 对 象 的 集 合 . 
*/ 
 
public Vector<Friend> friends = new Vector<Friend>();  
 
public void addFriend(Friend f) {  
friends.addElement(f);  
}  
 
public Vector<Friend> getFriends() {  
return friends;  
}  
 
public void setFriends(Vector<Friend> friends) {  
this.friends = friends;  
}  
 
public Address getAddress() {  
return address;  
}  
 
public void setAddress(Address address) {  
this.address = address;  
}  
 
public String getName() {  
return name;  
}  
 
public void setName(String name) {  
this.name = name;  
}  
 
public String getAge() {  
return age;  
}  
 
public void setAge(String age) {  
this.age = age;  
}  
 
@Override 
public String toString() {  
StringBuffer sb = new StringBuffer();  
sb.append("这 个 家 伙 名 叫 " + this.name + "今 年 " + this.age + "岁 了 ");  
sb.append("\n");  
sb.append("他 /居 住 在 :  " + address.toString());  
sb.append("\n");  
sb.append("他 /她 的 朋 友 是 :");  
for (Friend friend : friends) {  
sb.append(friend.getName());  
sb.append("  ");  
}  
return sb.toString();  
 
  }  
 



package com.zhengzm.prj.digester.ch2.pojo;

import java.util.Vector;

/**
* 每 一 个 person中 包 含 了 ,这 个 人 的 名 字 ,年 龄 ,居 住 地 址 address对 象 ,朋 友 的 集 合 friends
*
* @author 7upCat
*
*/
public class Person {
private String name;
private String age;
public Address address;




/**
* friends 对 象 的 集 合 .
*/

public Vector<Friend> friends = new Vector<Friend>();

public void addFriend(Friend f) {
friends.addElement(f);
}

public Vector<Friend> getFriends() {
return friends;
}

public void setFriends(Vector<Friend> friends) {
this.friends = friends;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}

public String getName() {
return name;
}

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

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("这 个 家 伙 名 叫 " + this.name + "今 年 " + this.age + "岁 了 ");
sb.append("\n");
sb.append("他 /居 住 在 :  " + address.toString());
sb.append("\n");
sb.append("他 /她 的 朋 友 是 :");
for (Friend friend : friends) {
sb.append(friend.getName());
sb.append("  ");
}
return sb.toString();

  }

}



Friend 类

Java代码
package com.zhengzm.prj.digester.ch2.pojo;  
 
 
/** 
*  
* @author 7upCat 

*/ 
public class Friend {  
 
private String name;  
 
public String getName() {  
return name;  
}  
 
public void setName(String name) {  
this.name = name;  
}  
 
@Override 
public String toString() {  
return    name;  
}  
 


package com.zhengzm.prj.digester.ch2.pojo;


/**
*
* @author 7upCat
*
*/
public class Friend {

private String name;

public String getName() {
return name;
}

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

@Override
public String toString() {
return    name;
}

}



Address 类

Java代码
package com.zhengzm.prj.digester.ch2.pojo;  
 
 
/** 
*  
* a address  object contaions   the  name of  the  city and  the name of the street 
*   
* @author 7upCat 

*/ 
public class Address {  
 
private String city;  
private String street;  
 
public String getCity() {  
return city;  
}  
 
public void setCity(String city) {  
this.city = city;  
}  
 
public String getStreet() {  
return street;  
}  
 
public void setStreet(String street) {  
this.street = street;  
}  
 
@Override 
public String toString() {  
   
return  city+"市 ,"+street+"\n";  
}   
 


package com.zhengzm.prj.digester.ch2.pojo;


/**
*
* a address  object contaions   the  name of  the  city and  the name of the street

* @author 7upCat
*
*/
public class Address {

private String city;
private String street;

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

@Override
public String toString() {

return  city+"市 ,"+street+"\n";
}

}
准备工作终于完成,解析的代码如下所示

Java代码
Digester  digester=new Digester();  
Person person=(Person)digester.parse(new File("person.xml"));  
System.out.println(person); 

Digester  digester=new Digester();
Person person=(Person)digester.parse(new File("person.xml"));
  System.out.println(person);

运行,结果为null 为什么呢? 结果不应该是Person对象吗?    请读者回忆一下我们刚才做过的事情.
      1.写了一个person.xml的xml文件.
      2.写了一组和person.xml做映射的pojo.  
      3.解析xml文档.

   : )   似乎少了点什么吧.大家不妨想想做ORM的时候,  我们做过的步骤.
         1.建立数据库表.
         2.写一组同这些数据库表做映射的pojo.
         3.添写,将这些pojo同数据库表关联起来的配置文件(可能是xml,也可能是properties文档).
         4.对pojo对象进行数据库操作.


   细心的读者一定发现了,在我们解析xml文档的时候少了哪一步骤, 我们并没有把xml文件,同pojo以某种形式关联起来,于是,理解应当我们解析的时候并没有产生相应的Object ..
   可在digester中xml文档,同pojo 是如何关联起来的呢? 在digester中实际上是通过监听器来实现这个的,下面一节我们将介绍Rule类,以及它的子类.并为Digester对象添加监听器.
   
  




2.2  Rule类以及digester世界中的pattern.


    Rule是digester世界中的监听器的抽象基类,  由于,Rule是抽象类,不能被实例化,所以你要使用Rule的时候必需继承它,并覆盖相应的方法.Digester则是被监听对象,如果你不为你的Digester对象,来注册监听,那么解析xml文档中的所有事件都将全部被忽略.
     Rule类一共声明了3个方法,如果,每个方法都有一个namespace 敏感的重载版本.(注一)

  void begin(Attributes attributes)
解析时遇到符合pattern匹配规则的文档的xml的节点时被调用.
  void body(String text)
解析时遇到符合pattern匹配规则的文档的xml的节点的值时被调用,并将这个值做为参数传递给方法.如果这个节点没有值,这个方法也会被调用,并将 null做为调用参数
  void end()
解析时遇到符合pattern匹配规则的文档的xml的节点结束时被调用. 


注一: 所谓的namespace敏感的重载版本实际上说的意思是,当Digester对象通过,  setNamespaceAware(boolean namespaceAware) 方法设置为true的时候,那么,将会调用.重载版本的方法,而不是上面的3个方法.


 
例如下面这个SimpleRule就是覆盖了Rule的begin方法, 并简单向控制台输出信息.

Java代码
package com.zhengzm.prj.digester.simple_example;  
 
import org.apache.commons.digester.Rule;  
import org.xml.sax.Attributes;  
 
/*** 
* 一 个 简 单 的 Rule实 现 ,仅 向 控 制 台 输 出 一 句 话 / 
* @author 7upCat 

*/ 
public class SimpleRule  extends Rule {  
 
 
   
@Override 
public void begin(Attributes attributes) throws Exception {  
System.out.println(" begin countered");  
   
}  
 
@Override 
public void body(String namespace, String name, String text)  
throws Exception {  
System.out.println("body endcountered ");  
}  
 
@Override 
public void end() throws Exception {  
System.out.println("end countered");  
}  


package com.zhengzm.prj.digester.simple_example;

import org.apache.commons.digester.Rule;
import org.xml.sax.Attributes;

/***
* 一 个 简 单 的 Rule实 现 ,仅 向 控 制 台 输 出 一 句 话 /
* @author 7upCat
*
*/
public class SimpleRule  extends Rule {



@Override
public void begin(Attributes attributes) throws Exception {
System.out.println(" begin countered");

}

@Override
public void body(String namespace, String name, String text)
throws Exception {
System.out.println("body endcountered ");
}

@Override
public void end() throws Exception {
System.out.println("end countered");
}
}

   我们通过,  Digester对象的  addRule(java.lang.String pattern, Rule rule)方法,来为它注册监听器. 参数pattern是匹配的规则.在digester中,是以嵌套的标签名称以“/“相连接来做为匹配规则的. 以2,1中的person.xml文件为例.
Xml代码
<?xml version="1.0" encoding="UTF-8"?> 
<person name="7upCat" age="24"> 
   <address city="深圳" street="梅林">   
   </address> 
  <friend name="vincent"   age="24" ></friend> 
<friend name="鱼生烟"     age=“23“></friend>         
</person> 

<?xml version="1.0" encoding="UTF-8"?>
<person name="7upCat" age="24">
   <address city="深圳" street="梅林">
   </address>
  <friend name="vincent"   age="24" ></friend>
<friend name="鱼生烟"     age=“23“></friend>      
</person>


"person/“ 将同<person>标签匹配
"person/address/“   同<address>标签匹配
"person/friend/“   同<friend>标签匹配

    

我们现在先把这个SimpleRule注册给Degister 对象,然后再来解析一下,person.xml看看会出现什么情况呢?
Java代码
Digester  digester=new Digester();  
digester.addRule("person/",new SimpleRule() );  
Person o=(Person)digester.parse(new File("person.xml"));  
System.out.println("the person is "+ o );  
         

Digester  digester=new Digester();
digester.addRule("person/",new SimpleRule() );
Person o=(Person)digester.parse(new File("person.xml"));
System.out.println("the person is "+ o );

输出结果是:

begin countered
body endcountered
end countered
the person is null


我们看到, SimpleRule中的方法均被调用了.然而,我们的Person对象依然没有被创建.不要灰心,现在你已经明白了,digester包实现的基本原理,   Degister类通过继承org.xml.sax.helpers.DefaultHandle来监听使用SAX来解析XML文档时发生的事件,并对事件产生的数据进行了包装,然后调用注册在Degister中相匹配的Rule的子类的方法.对数据进行进一步封装.
   下一章,我们将介绍一些Degister中一些十分有用的方法,和一些由digester包提供好的Rule的实现 .
分享到:
评论

相关推荐

    Struts框架中struts-config.xml文件配置小结

    ### Struts框架中struts-config.xml文件配置详解 #### 一、引言 在Java Web开发领域,Struts是一个非常重要的MVC(Model-View-Controller)框架,它极大地简化了Web应用程序的开发过程。而在Struts框架中,`struts...

    Dom4j解析struts2框架的struts.xml

    本篇文章将深入探讨如何使用Dom4j这个XML处理库来解析`struts.xml`,以便自定义和配置Struts2框架。 Dom4j是一个灵活且功能丰富的Java库,专门用于处理XML文档。它提供了全面的API,可以方便地读取、写入、修改和...

    struts框架原理图

    为了更好地理解和应用Struts框架,本文将深入解析这些关键知识点。 ### Struts框架概述 Struts是一个开源的Web应用程序框架,属于MVC(Model-View-Controller)模式的一种实现。它主要用于Java EE平台上的Web开发...

    仿struts框架的自制代码

    在这个“仿struts框架的自制代码”中,我们可以看到作者尝试模仿Struts的核心功能,并结合了多种技术,如DOM4J、JNDI以及处理Excel的代码。 1. **Servlet**: Servlet是Java服务器端的API,用于扩展服务器的功能。在...

    struts.xml常用配置解析

    Struts.xml配置文件是Struts2框架的核心配置文件,它定义了应用的行为和结构。本文主要解析了其中两个重要的配置元素:`&lt;include&gt;`标签和Action的别名。 首先,我们来看 `&lt;include&gt;` 标签的使用。当Struts2的应用中...

    struts框架详细介绍

    Struts框架是一个基于MVC(模型-视图-控制器)设计模式的Java Web应用程序框架,由Apache软件基金会的Struts项目开发。它旨在提供一种结构化的、可维护性高的开发方式,以帮助开发者构建Web应用。以下是Struts框架的...

    基于MVC模式Struts框架

    - **ActionServlet**:作为Struts框架的核心,配置在`web.xml`中。 - **ActionMapping**:定义每个请求URL与对应的Action类之间的映射,例如`/budgetInfo`可以映射到`BudgetInfoAction`。 4. **流程梳理**: - ...

    struts框架需要的所有jar包汇总

    将这些JAR包拷贝到`WEB-INF/lib`目录下,可以确保Struts框架的正常运行,同时这些库也支持其他相关的功能,如XML解析、数据验证、日志记录和文件上传等。在实际开发中,还需要根据项目需求添加其他必要的库,如...

    struts2 jquery xml

    Struts2 jQuery XML 是一个基于Java的Web开发框架的组合,它将Apache Struts2的MVC架构与jQuery库结合,提供了丰富的用户界面组件和更流畅的AJAX交互。Struts2是一个强大的、灵活的MVC框架,而jQuery则简化了...

    J2EE项目实训——Struts框架技术.rar

    10. **ActionServlet**:Struts框架的入口点是ActionServlet,它是Servlet的子类,负责解析请求,调用Action,处理结果等。 11. ** strut2-struts1-plugin**:如果项目中还包含Struts1的遗留代码,可以通过Struts2...

    dom4j解析struts.xml需要的包装类

    在Struts2中,配置文件`struts.xml`扮演着核心角色,它定义了动作(Action)、包(Package)和结果(Result)等关键组件的行为。为了方便地解析和处理这些配置,开发者常常会创建自定义的包装类(Wrapper Class),...

    在老项目中加入struts2,xml报错

    在整合老项目与Struts2框架的过程中,可能会遇到XML解析相关的错误,这通常是由于Struts2在启动时尝试使用不兼容或不适合的XML解析器导致的。本文将深入探讨这个问题,提供解决方案,并介绍如何避免此类问题。 错误...

    学生管理的Struts框架开发实例

    Struts框架是Java Web开发中常用的一个开源MVC框架,由Apache软件基金会维护。它提供了一种组织应用程序的方式,使得开发者能够将业务逻辑、控制流程和表现层分离,从而提高代码的可重用性和可维护性。在这个"学生...

    struts.xml的错误解决办法

    在开发过程中,我们经常会遇到与`struts.xml`配置文件相关的错误,这是由于XML解析问题或者DTD(文档类型定义)引用的问题引起的。`struts.xml`是Struts2框架的核心配置文件,它定义了动作、结果、拦截器等关键组件...

    struts框架-文件上传下载

    Struts框架是Java Web开发中常用的一个开源MVC框架,由Apache软件基金会维护...以上是对Struts框架中文件上传下载功能的详细解析,希望对你理解这一主题有所帮助。如需进一步讨论,可以加入指定的QQ群或通过邮件联系。

    Struts2中struts_xml的Action配置详解

    Struts2作为一款强大的MVC框架,其核心配置文件`struts.xml`在应用程序中扮演着至关重要的角色。本文将深入解析`struts.xml`中的Action配置,帮助开发者更好地理解和运用这一关键组件。 首先,Action配置是Struts2...

    用Struts框架实现多文件上传功能(初学者的入门项目案例)

    Struts框架通过解析这些请求,提供了一种处理文件上传的便捷方式。 在Struts框架中,文件上传主要依赖于两个关键组件:`Commons FileUpload`库和`Struts2上传插件`。`Commons FileUpload`是Apache的一个子项目,...

    自定义类似struts的mvc框架

    在IT行业中,构建一个自定义的类似于Struts的MVC框架是一项挑战性的任务,它涉及到对Web开发模式的深入理解,以及对Java、JSP、XML解析等技术的熟练运用。Struts作为Java EE领域中著名的MVC框架,其设计思想和实现...

    Struts struts-config.xml配置

    在Java Web开发领域,Struts框架一直是构建MVC架构应用的重要工具之一。而`struts-config.xml`配置文件则是Struts应用的核心配置文件,它负责管理Struts应用中的各种组件配置。本文将详细介绍`struts-config.xml`...

Global site tag (gtag.js) - Google Analytics