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
指定为元素的属性