病理生理学课件下载:应用 JAXB 把 XML 转换成相应的 JavaBean

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 09:43:23

跨系统的调用目前无疑是 WebService 的天下,指的是通过 HTTP 请求方式获得 XML 或 JSON 数据的方式,RESTFul 也得到了很好的应用。规范意义上的 Soap 调用不知道还不多不多,反正当年用过的 Corba 鲜有耳闻了,就像很多人对 EJB2 不会有概念一样。

Java 在调用 WebService 获得了 XML 之后,接下来一种常见的处理方式就是把它转换成相应的 JavaBean,再丢给其他组件像 Jsp 标签,FreeMarker 等去就很流畅了。关于 XML 与 JavaBean 互相转换有两个操作叫做:Marshaller 和 Unmarshaller,还没见一个权威的翻译,大概就是编组与反编组,意义如同序列化与反序列化。也就是由 JavaBean 到 XML 叫做 Marshal,由 XML 到 Java 叫做 Unmarshal。

通常从 XML 到 JavaBean 的转换机会大的多,所以我主要也是研究了下如何把 XML 映射成 JavaBean,虽然现在的工具一样也都支持这两个方向的转换。有许多组件可以做到,像 JAXB(Java Architecture for XML Binding)、XMLBeans、JiBX、Castor。前面这些工具都提供了工具根据 XML 数据和相应的 Schma 产生相应 Java 类的功能,我还是喜欢先入为主的方式,自己手工写好了 JavaBean 主动去包容 XML 数据。

JAXB是Java EE平台的API之一,同时是Java Web服务开发包(JWSDP)的一部分。 JAXB也是Web服务互操作性技术(WSIT)的基础之一. JAXB是J2SE1.6的一部分。JAXB 1.0是在Java社群过程中作为JSR 31开发出来的。JAXB 2.0是作为JSR 222开发的。

下面看个 JAXB 把 XML 转换为 JavaBean 的例子,本例由一个 XML 文件和四个类组成,所涵盖到的内容有,元素和属性的映射,Namespace 的使用,以及一个自定义的 XmlAdapter 类。

1. XML 文件,users.xml:

01020304050607080910111213xml version="1.0" encoding="UTF-8"?><users xmlns:i="http://www.w3.org/2001/XMLSchema-instance">    <user i:type="worker">        <id>1id>        <name>Unminame>        <time>2010-11-18T21:57:15.07time>    user>    <user i:type="yuan">        <id>2id>        <name>Shename>        <time>2010-10-18T21:20:15.25time>    user>users>

2. 两个 JavaBean,为获得上面数据组装到 JavaBean,我用了两个 Java 类,分别是 UserList.java 和 User.java。

UserList.java

0102030405060708091011121314151617181920212223package cc.unmi.jaxb; import java.util.List; import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement; /** * @author Unmi CreateTime: Apr 21, 2011 */@XmlRootElement(name = "users")public class UserList {    List users;     @XmlElement(name = "user")    public List getUsers() {        return users;    }     public void setUsers(List users) {        this.users = users;    }}

为类用 XmlRootElement 注解了这是个根元素,对应于 XML 中的 users 元素,并在它的属性 users 的 getter 方法上应用了 XmlElement,节点名为 user。

User.java

0102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859package cc.unmi.jaxb; import java.util.Date; import javax.xml.bind.annotation.XmlAttribute;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * @author Unmi * CreateTime: Apr 21, 2011 */public class User {    private int id;    private String type;    private String name;    private Date date;     @XmlElement(name = "id")    public int getId() {        return id;    }     public void setId(int id) {        this.id = id;    }     @XmlElement(name = "name")    public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }     @XmlElement(name = "time")    @XmlJavaTypeAdapter(DateAdapter.class)    public Date getDate() {        return date;    }     public void setDate(Date date) {        this.date = date;    }     @XmlAttribute(name = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")    public String getType() {        return type;    }     public void setType(String type) {        this.type = type;    }     public String toString() {        return id + ":" + name + ":" + type + ":" + date;    }}

类不需要进行注解,同样是对属性的 getter 方法注解标识其对应于 XML 上的什么节点。对于时间节点用了自定义的 DateAdapter 在字符串与 Date 类型间转换。注意 getType() 的注解,用的是 XmlAttribute,并带有命名空间,这里的 namespace 不能写成 "i" 的。

DateAdapter.java

01020304050607080910111213141516171819202122232425package cc.unmi.jaxb; import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date; import javax.xml.bind.annotation.adapters.XmlAdapter; public class DateAdapter extends XmlAdapter {    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS");     public Date unmarshal(String val) throws Exception {        if (val == null) {            return null;        }        return df.parse(val);    }     public String marshal(Date val) throws Exception {        if (val == null) {            return null;        }        return df.format(val);    }}

看到分别对应于 unmarshal 和 marshal 的两个方法,写过 Struts 或 Hibernate 的 TypeHandler 会很容易理解的。

Client.java,客户端调用代码:

010203040506070809101112131415161718192021package cc.unmi.jaxb; import java.net.URL; import javax.xml.bind.JAXBContext;import javax.xml.bind.Unmarshaller; /** * @author Unmi * CreateTime: Apr 21, 2011 */public class Client {     public static void main(String[] args) throws Exception {        JAXBContext context = JAXBContext.newInstance(UserList.class);        Unmarshaller unmarshaller = context.createUnmarshaller();        URL xmlFileUrl = ClassLoader.getSystemResource("users.xml");        UserList userList = (UserList) unmarshaller.unmarshal(xmlFileUrl);        System.out.println(userList.getUsers().get(0).getName());   }}

执行后看到控制台如下输出就说明了各个属性都工作正常:

1:Unmi:worker:Thu Nov 18 21:57:15 CST 2010

特性说明:

1. 用注解的方式,可声明在 setter/getter 方法上,也可以在属性上,但不能同时对一个属性注解两次,否则就会报错:@javax.xml.bind.annotation.XmlElement annotation is found on two places; one would be suffice.
     如果只在属性上用 XmlElement 注解,也会出错:Class has two properties of the same name "id".  此时得在对应的 getter 或 setter 方法加上注解:@XmlTransient。

2. 如果取一个 List 数据必须声明出一个相应的 XxxList 类,其中包含一个 List 属性,这里的 XxxList 有点多余。还不清楚如何在业务类中直接映射出 List 属性。

3. 有 Namespace 时,需要写全 namespace,如namespace=http://www.w3.org/2001/XMLSchema-instance. 这有点啰唆。

4. 使用还是很简单,可以定义自己的类型转换类,像这里的 DateAdapter

5. 如果更深层次的 XML 结构,只需依循着 XPATH 用进行更深度的注解类的属性。理解了上面的例子,对于只表示一个 Java 对象的 XML 的映射方法就很简单了。

6. 因为注解的方法,如果一个 Bean 去映射多个 XML 时,就有困难,比如节点名变了,但映射的是同一个属性时这个 JavaBean 类不好重用。

7. Bean 需要一个默认构造函数,对象是通过默认构造函数创建的,属性要通过 setter 方法去设置,所以可以在构造方法和 setter 方法中对实例作某些修饰。

8. 更多注解的使用请浏览下包 javax.xml.bind.annotation 中的所有注解类,像 XmlElementWrapper、XmlList、DomHandler 等,都会有用处的。在 unmarshl 时可支持更多的输入源类型,最后见下几个图:

     

资料:1. http://stackoverflow.com 上搜索有关 jaxb 的资源
             2. 使用JAXB将XML Schema绑定到Java类
             3. 用JAXB生成一个XML文档
             4. Java Architecture for XML Binding (JAXB)
             5. http://jaxb.java.net/

本文链接 http://unmi.cc/jaxb-xml-javabean-start, 来自 隔叶黄莺 Unmi Blog

[版权声明]本站内文章,如未特别注明,均系原创或翻译之作,本人 Unmi 保留一切权利。本站原创及译作未经本人许可,不得用于商业用途及传统媒体。网络媒体可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。及此说明,重之之重。