服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 核心技术 > 查看文档

实现xml信息到java bean的转化

  本文主要是关于使用commons-betwixt组件实现xml信息到java bean的转化的一些感受,实现这一功能的核心类是beanreader,beanreader自身也有一些新的机制对xml进行转化,完善了digester的很多欠缺功能

  本文主要是关于使用commons-betwixt组件实现xml信息到java bean的转化的一些感受,实现这一功能的核心类是beanreader,如果你看过betwixt的源代码,你会发现

public class beanreader extends digester{} 

      如果你细看一下beanreader的源代码,betwixt在处理xml-->javabean转化时其实是调用digester这个类的parse方法。但除了此方式可以实现转化的功能以外,beanreader自身也有一些新的机制对xml进行转化,完善了digester的很多欠缺功能,让转化更加方便。

  首先,来看一下beanreader完全使用digester的parse方法进行转化的流程。(其实觉得说是digester怎样处理转化更为恰当)

  1。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>

  2。定义实体对象person和addressbook

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);
       }
      
   }

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();
        }
    }

  3。实现转化功能

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);
 }
}

  运行结果如下:

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。定义实体类

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 + "']";
    }
}

  2.person.xml文件

<beans>
  <personbean>
    <age>22</age>
    <name>luna</name>
  </personbean>
</beans>

  3。实现转化功能

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);
    }
   
}

运行结果:
personbean[name='luna',age='22']
  

说明几点:

  digester类的parse()是xml向javabean转化的核心方法,两者的最大区别是,前者通过详细的add***()方法,告诉了beanreader的转化步骤,而后者则是用registerbeanclass()注册将要转化成的bean对象类型,而其中的方法调用则是beanreader自动去按号入座完成的。而后者也一次只能转化一个bean对象,可采用迭代的方法对多哥对象进行操作。

  前者适用于在已经知道bean类型及具体属性的情况下,可以用add***()一步步的设定转化的步骤,而如果产生的对象是预先未知的,只有在知道结果的情况下才知道它的属性,这个时候只要在后者方法中使用registerbeanclass()把该类注册给betwxit,剩下的功能,这个组件就可以自动完成了 。

扫描关注微信公众号