关于使用commons-betwixt组件实现xml信息-->Java Bean的转化的一些感受

本文介绍了如何使用commons-betwixt组件将XML信息转化为Java Bean。通过示例展示了两种转化方式:一种是利用BeanReader结合Digester的parse方法,另一种是直接注册Bean类,让BeanReader自动完成转化。文中详细解释了转化流程和不同转化方式的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现这一功能的核心类是BeanReader,如果你看过betwixt的源代码,你会发现
public class BeanReader extends Digester{}
如果你细看一下BeanReader的源代码,你会发现betwixt在处理xml-->JavaBean转化时其实是调用Digester这个类的parse方法。但除了此方式

可以实现转化的功能以外,BeanReader自身也有一些新的机制对xml进行转化,完善了Digester的很多欠缺功能,让转化更加方便。

首先,来看一下BeanReader完全使用Digester的parse方法进行转化的流程。(其实觉得说是Digester怎样处理转化更为恰当)
1。xml信息
******************examples.xml*************************
<address-book>
  <person id="1" category="acquaintance" try="would be ignored">
    <name>Gonzo</name>
    <email type="business">gonzo@muppets.com</email>
    <gender result="the whole tag would be ignored">male</gender>
  </person>
  <person id="2" category="rolemodel">
    <name>Kermit</name>
    <email type="business">kermit@muppets.com</email>
    <email type="home">kermie@acme.com</email>
  </person>
</address-book>
******************examples.xml*************************
2。定义实体对象Person和AddressBook
******************Person.java**************************
import java.util.HashMap;
import java.util.Iterator;

public class Person {
 private int id;
   private String category;
   private String name;
   private HashMap emails = new HashMap();
     
   /**
    * A unique id for this person. Note that the Digester automatically
    * converts the id to an integer.
    */
   public void setId(int id) {
       this.id = id;
   }
  
   public void setCategory(String category) {
       this.category = category;
   }
  
   public void setName(String name) {
       this.name = name;
   }
  
   /** we assume only one email of each type... */
   public void addEmail(String type, String address) {
       emails.put(type, address);
   }
  
 
   public void print() {
       System.out.println("Person #" + id);
       System.out.println("  category=" + category);
       System.out.println("  name=" + name);
      
       for(Iterator i = emails.keySet().iterator(); i.hasNext(); ) {
           String type = (String) i.next();
           String address = (String) emails.get(type);
          
           System.out.println("  email (type " + type + ") : " + address);
       }
      
   }
******************Person.java**************************
******************AddressBook.java*********************
import java.util.Iterator;
import java.util.LinkedList;

public class AddressBook {
 LinkedList person = new LinkedList();
   
 public LinkedList getPerson(){
  return person;
 }
    public void addPerson(Person p) {
        person.addLast(p);
    }
   
    public void print() {
        System.out.println("Address book has " + person.size() + " entries");

        for(Iterator i = person.iterator(); i.hasNext(); ) {
            Person p = (Person) i.next();
            p.print();
        }
    }
}

******************AddressBook.java*********************
3。实现转化功能
******************AddressBookDigester.java**************
public class AddressBookDigester{
public static void main(String[] args) throws IOException, SAXException, IntrospectionException{
  
  // 创建一个BeanReader实例
  BeanReader reader = new BeanReader();
  // 创建AddressBook实例,并将其压入栈顶。
  AddressBook book = new AddressBook();
  reader.push(book);
  // 增加规则
  addRules(reader);
  
  reader.parse(new File("examples.xml"));
  book.print();
  
 }
private static void addRules(BeanReader d) {
  // 当遇到<person>时,创建类Person的一个实例,并将其压入栈顶
  d.addObjectCreate("address-book/person", Person.class);

  // 将<person>标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根据各自的名字进行映射,(例如,将

标签属性id与属性设置方法setId进行映射,将标签属性category与属性设置方法setCategory进行映射),然后将属性的值作参数传递给执行相

应的方法。
  // 如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个<person>的try属

性)。
  d.addSetProperties("address-book/person");

  // 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数
  d.addSetNext("address-book/person", "addPerson");

  // 当遇到<person>的子元素<name>时,调用栈顶对象(Person实例)的setName方法。
  // 此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数

,且参数的值是元素的内容)
  d.addCallMethod("address-book/person/name", "setName", 0);

  // 当遇到<person>的子元素<email>时,调用栈顶对象(Person实例)的addEmail
  // 方法,addEmail方法有两个参数,取值分别来自<email>的属性type的值和<email>本身的内容。
  // 此处addCallParam方法的第一参数是规则,第二个参数是指明被调用方法(addEmail)参数的序号,第三个是参数为字符串

时指属性的名字)
  d.addCallMethod("address-book/person/email", "addEmail", 2);
  d.addCallParam("address-book/person/email", 0, "type");
  d.addCallParam("address-book/person/email", 1);
 }

}
******************AddressBookDigester.java**************

运行结果如下:
Address book has 2 entries
Person #1
  category=acquaintance
  name=Gonzo
  email (type business) : gonzo@muppets.com
Person #2
  category=rolemodel
  name=Kermit
  email (type business) : kermit@muppets.com
  email (type home) : kermie@acme.com

其次,再看看不使用Digester的add***Method()方法,对转化属性进行配置的方式。
1。定义实体类
*************************PersonBean.java****************
public class PersonBean {
   
    private String name;
    private int age;
   
    /** Need to allow bean to be created via reflection */
    public PersonBean() {}
   
    public PersonBean(String name, int age) {
        this.name = name;
        this.age = age;
    }
   
    public String getName() {
        return name;
    }
   
    public void setName(String name) {
        this.name = name;
    } 
   
    public int getAge() {
        return age;
    }
   
    public void setAge(int age) {
        this.age = age;
    }
   
    public String toString() {
        return "PersonBean[name='" + name + "',age='" + age + "']";
    }
}
*************************PersonBean.java****************
2.person.xml文件
*************************person.xml*********************
<beans>
  <personbean>
    <age>22</age>
    <name>luna</name>
  </personbean>
</beans>
*************************person.xml*********************
3。实现转化功能
*************************ReadApp.java*******************
import java.io.StringReader;

import org.apache.commons.betwixt.io.BeanReader;

public class ReadApp {
   
    public static final void main(String args[]) throws Exception{
       
         // 初始化BeanReader并对其进行配置
  BeanReader reader = new BeanReader();
  reader.getXMLIntrospector().getConfiguration()
    .setAttributesForPrimitives(false);
  reader.getBindingConfiguration().setMapIDs(false);
  // 注册bean,告诉betwixt把xml转化成什么bean
  reader.registerBeanClass("personbean", PersonBean.class);
  // 得到一个Object对象并打印
  PersonBean person = (PersonBean)reader.parse(new File("person.xml"));
  System.out.println(person);
    }
   
}
*************************ReadApp.java*******************
运行结果:
PersonBean[name='luna',age='22']

说明几点:
Digester类的parse()是xml向javabean转化的核心方法,两者的最大区别是,前者通过详细的add***()方法,告诉了BeanReader的转化步骤,

而后者则是用registerBeanClass()注册将要转化成的bean对象类型,而其中的方法调用则是BeanReader自动去按号入座完成的。而后者也一次

只能转化一个bean对象,可采用迭代的方法对多哥对象进行操作。

前者适用于在已经知道bean类型及具体属性的情况下,可以用add***()一步步的设定转化的步骤,而如果产生的对象是预先未知的,只有在知

道结果的情况下才知道它的属性,这个时候只要在后者方法中使用registerBeanClass()把该类注册给betwxit,剩下的功能,这个组件就可以

自动完成了 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值