jaxb中的类继承

jersey中的@Produces(“application/xml”)是由jaxb来负责处理的,只要项目中引入了jaxb-api-2.2.7.jar.所以只要注解使用对了,在jersey中输出xml文件是不需要单独写@Provider处理器的。单个类你只要在类上加入@XmlRootElement注解,jaxb会把它换成xml输出。

@XmlRootElement
public class Address implements Serializable{
}

简单吧。但项目中不是所有的类都是独立存在的,它可能实现接口或继续某个父类。
来看一个jersey中可能存在的场景:客户端需要分页浏览记录(某个对象列表),一般要分页可能要作两件事
1.获得总数量或者记录的最大id值(此时自增列不能出现裂带)

int getArticleSize();

2.获得某页的数据

List
getArticleForPage(int page,int pageSize);

为了减少网络请求数量可以把1,2封装到一个结果集中.不论是否存在记录都假定它有一页的记录量

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="articleResult")
public class ArticleQueryList implements Serializable{

    private static final long serialVersionUID = 1L;
    //总数量
    @XmlElement
    int total;
    //结果集
    @XmlElementWrapper
    @XmlElement(name="article")
    List
result; //查询参数 @XmlElement String param; //页码 @XmlElement int page; //每页数量 @XmlElement int pageSize; }

@XmlAccessorType(XmlAccessType.FIELD)为默认注解可以不用写,像上面的Address类虽然没有加此注解,但不能当它不存在.

注意:如果加了XmlAccessType.FIELD类注解,此时出现下面的代码

    @XmlElementWrapper(name="result")
    @XmlElement(name="article")
    List
result;

jaxb会出错,提示:Class has two properties of the same name “result”

如果项目有很多个不同的查询列表,不可能一个对象查询列表写一个类,需要抽像一下,把page,pageSize,param移到一个抽像的父类中,而具体的对象列表归到一个子类中.

@XmlSeeAlso({
    ArticleQueryList.class,
    ChannelQueryList.class})
public abstract class QueryList implements Serializable{
    private static final long serialVersionUID = 1L;
    //总数量
    protected int total;
    //结果集
    protected List result;
    //查询参数
    @XmlElement
    private String param;
    //页码
    @XmlElement
    private int page;
    //每页数量
    @XmlElement
    private int pageSize;

    public abstract List getResult();
    public abstract void setResult(List result);
    public abstract void setTotal(int total); 
    public abstract int getTotal();
}

一个具体的文章查询列表

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="articleResult")
public class ArticleQueryList extends QueryList<Article>{

    private static final long serialVersionUID = 1L;

    @XmlElementWrapper
    @XmlElement(name="article")
    @Override
    public List
getResult() { // TODO Auto-generated method stub return super.result; } @Override public void setResult(List
result) { // TODO Auto-generated method stub super.result=result; } @Override public void setTotal(int total) { // TODO Auto-generated method stub super.total=total; } @XmlElement @Override public int getTotal() { // TODO Auto-generated method stub return super.total; } }

运行会出错:

Class has two properties of the same name "page"
    this problem is related to the following location:
        at public int net.project.query.QueryList.getPage()
        at net.project.query.QueryList
        at net.project.query.ArticleQueryList
    this problem is related to the following location:
        at private int net.project.query.QueryList.page
        at net.project.query.QueryList
        at net.project.query.ArticleQueryList
Class has two properties of the same name "pageSize"
    this problem is related to the following location:
        at public int net.project.query.QueryList.getPageSize()
        at net.project.query.QueryList
        at net.project.query.ArticleQueryList
    this problem is related to the following location:
        at private int net.project.query.QueryList.pageSize
        at net.project.query.QueryList
        at net.project.query.ArticleQueryList
Class has two properties of the same name "param"
    this problem is related to the following location:
        at public java.lang.String net.project.query.QueryList.getParam()
        at net.project.query.QueryList
        at net.project.query.ArticleQueryList
    this problem is related to the following location:
        at private java.lang.String net.project.query.QueryList.param
        at net.project.query.QueryList
        at net.project.query.ArticleQueryList

因为QueryList上有默认的@XmlAccessorType(XmlAccessType.FIELD)注解,而ArticleQueryList上显式的类注解,导致了jaxb认为出现了两个param,page,pageSize.

知道了问题出在哪,修复就容易了.

@XmlSeeAlso({
    ArticleQueryList.class,
    ChannelQueryList.class})
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public abstract class QueryList<T> implements Serializable{}

再运行就可以输出希望的xml

<articleResult>
    <param>date:todayparam>
    <page>1page>
    <pageSize>30pageSize>
    <result>
        <article>
            <id>1966id><hash>55b32556218b4a871e1cd386bccbb57bhash> <source>ifanr.comsource>
            <status>truestatus>
            <date>2015-11-21T11:17:27+08:00date>
            <title>沃尔沃的 Concept 26:要自动驾驶,也要驾驶乐趣title>
            <link>http://www.ifanr.com/587368?utm_source=rss&utm_medium=rss&utm_campaign=link>
       article>
       
    result>
    <total>180total>
articleResult>

总结:
1.如果注解的类中属性不是全部输出,一定要不要使用
@XmlAccessorType(XmlAccessType.FIELD)
或者不写@XmlAccessorType

2.@XmlSeeAlso不仅可以用于继续关系还可以用于实现关系

3.@XmlElement(name=”值”)值如果与属性名一致不要写括号内的别名

4.不希望属性输出可以使用@XmlTransient注解,例:

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class Channel implements Serializable{

    private static final long serialVersionUID = 1L;

    @XmlElement
    int id;
    @XmlElement
    String name;
    @XmlElement
    URL url;
    /**
     * 编码
     */
    @XmlTransient
    String encode;
}

5.jaxb其它的注解
可以访问:[email protected]
下载api文档和jaxb-api.jar
中文:[email protected]
常用的注解:
@XmlType(propOrder={“street”, “city” , “state”, “zip”, “name” })
指定xml中属性的排序
@XmlAttribute
指定为元素的属性

你可能感兴趣的:(java,xml,jersey,rest)