浏览 9271 次
锁定老帖子 主题:JAXB开发的技巧
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-11-20
以下是需要输出的XML文本格式 <Books> <Book> <name>书名A</name> <author>作者A</author> <price>作者A</price> </Book> <Book> <name>书名B</name> <author>作者B</author> <price>作者B</price> </Book> </Books> 首先我们需要使用XML Schema来描述XML格式,怎样自动生成xsd,我们可以通过trang.jar这个包来生成 java -jar trang.jar a.xml a.xsd 生成的XSD文件格式如下 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="Books"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" ref="Book"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Book"> <xs:complexType> <xs:sequence> <xs:element ref="name"/> <xs:element ref="author"/> <xs:element ref="price"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="name" type="xs:NCName"/> <xs:element name="author" type="xs:NCName"/> <xs:element name="price" type="xs:NCName"/> </xs:schema> 现在可以使用jdk自带的xjc命令来生成代码了,xjc的具体使用方面就不多说,大家可以自己看看它的帮助文档 $ xjc a.xsd parsing a schema... compiling a schema... generated\Book.java generated\Books.java generated\ObjectFactory.java package generated; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * <p>Java class for anonymous complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element ref="{}Book" maxOccurs="unbounded"/> * </sequence> * </restriction> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "book" }) @XmlRootElement(name = "Books") public class Books { @XmlElement(name = "Book", required = true) protected List<Book> book; /** * Gets the value of the book property. * * <p> * This accessor method returns a reference to the live list, * not a snapshot. Therefore any modification you make to the * returned list will be present inside the JAXB object. * This is why there is not a <CODE>set</CODE> method for the book property. * * <p> * For example, to add a new item, do as follows: * <pre> * getBook().add(newItem); * </pre> * * * <p> * Objects of the following type(s) are allowed in the list * {@link Book } * * */ public List<Book> getBook() { if (book == null) { book = new ArrayList<Book>(); } return this.book; } } package generated; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * <p>Java class for anonymous complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element ref="{}name"/> * <element ref="{}author"/> * <element ref="{}price"/> * </sequence> * </restriction> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "name", "author", "price" }) @XmlRootElement(name = "Book") public class Book { @XmlElement(required = true) @XmlJavaTypeAdapter(CollapsedStringAdapter.class) @XmlSchemaType(name = "NCName") protected String name; @XmlElement(required = true) @XmlJavaTypeAdapter(CollapsedStringAdapter.class) @XmlSchemaType(name = "NCName") protected String author; @XmlElement(required = true) @XmlJavaTypeAdapter(CollapsedStringAdapter.class) @XmlSchemaType(name = "NCName") protected String price; /** * Gets the value of the name property. * * @return * possible object is * {@link String } * */ public String getName() { return name; } /** * Sets the value of the name property. * * @param value * allowed object is * {@link String } * */ public void setName(String value) { this.name = value; } /** * Gets the value of the author property. * * @return * possible object is * {@link String } * */ public String getAuthor() { return author; } /** * Sets the value of the author property. * * @param value * allowed object is * {@link String } * */ public void setAuthor(String value) { this.author = value; } /** * Gets the value of the price property. * * @return * possible object is * {@link String } * */ public String getPrice() { return price; } /** * Sets the value of the price property. * * @param value * allowed object is * {@link String } * */ public void setPrice(String value) { this.price = value; } } package generated; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlElementDecl; import javax.xml.bind.annotation.XmlRegistry; import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import javax.xml.namespace.QName; /** * This object contains factory methods for each * Java content interface and Java element interface * generated in the generated package. * <p>An ObjectFactory allows you to programatically * construct new instances of the Java representation * for XML content. The Java representation of XML * content can consist of schema derived interfaces * and classes representing the binding of schema * type definitions, element declarations and model * groups. Factory methods for each of these are * provided in this class. * */ @XmlRegistry public class ObjectFactory { private final static QName _Author_QNAME = new QName("", "author"); private final static QName _Price_QNAME = new QName("", "price"); private final static QName _Name_QNAME = new QName("", "name"); /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: generated * */ public ObjectFactory() { } /** * Create an instance of {@link Book } * */ public Book createBook() { return new Book(); } /** * Create an instance of {@link Books } * */ public Books createBooks() { return new Books(); } /** * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} * */ @XmlElementDecl(namespace = "", name = "author") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) public JAXBElement<String> createAuthor(String value) { return new JAXBElement<String>(_Author_QNAME, String.class, null, value); } /** * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} * */ @XmlElementDecl(namespace = "", name = "price") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) public JAXBElement<String> createPrice(String value) { return new JAXBElement<String>(_Price_QNAME, String.class, null, value); } /** * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}} * */ @XmlElementDecl(namespace = "", name = "name") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) public JAXBElement<String> createName(String value) { return new JAXBElement<String>(_Name_QNAME, String.class, null, value); } } 下面我们就可以开始来写代码了 package generated; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.OutputStream; import java.util.List; import javax.xml.bind.JAXB; public class Test { public static void main(String[] args) throws FileNotFoundException { marshal(new FileOutputStream("out.xml")); unmarshal(new FileReader("out.xml")); } private static void unmarshal(FileReader reader) { try { Books books = JAXB.unmarshal(reader, Books.class); System.out.println(books.getBook().size()); System.out.println(books.getBook().get(0).getName()); System.out.println(books.getBook().get(0).getAuthor()); System.out.println(books.getBook().get(0).getPrice()); } finally { try { reader.close(); } catch (IOException e) { } } } private static void marshal(OutputStream output) { ObjectFactory factory = new ObjectFactory(); Books books = factory.createBooks(); List<Book> bookList = books.getBook(); Book book = factory.createBook(); book.setName("书名A"); book.setAuthor("作者A"); book.setPrice("价格A"); bookList.add(book); book = factory.createBook(); book.setName("书名B"); book.setAuthor("作者B"); book.setPrice("价格B"); bookList.add(book); book = factory.createBook(); book.setName("书名C"); book.setAuthor("作者C"); book.setPrice("价格C"); bookList.add(book); try { JAXB.marshal(books, output); } finally { try { output.close(); } catch (IOException e) { } } } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-11-22
挽尊
我觉得很好, 以前没接触过 。 没人顶, 看来大家都是大贤啊 |
|
返回顶楼 | |
发表时间:2011-11-24
JAX-WS 的Dispatch client可以用到类似的方式
URL wsdlLocation = new URL("http://127.0.0.1:8080/cxfDemo/DemoService?wsdl"); QName serviceName = new QName("http://demo.com", "DemoService"); QName portName = new QName("http://demo.com", "DemoPort"); JAXBContext context = JAXBContext.newInstance("com.test.bbc"); Service service = Service.create(wsdlLocation, serviceName); Dispatch<Object> dispatch = service.createDispatch(portName, context, Service.Mode.PAYLOAD); ObjectFactory factory = new ObjectFactory(); QueryPerson queryPerson = factory.createQueryPerson(); JAXBElement<QueryPerson> jaxbElement = factory.createQueryPerson(queryPerson); JAXBElement<QueryPersonResponse> retJaxbElement = (JAXBElement<QueryPersonResponse>)dispatch.invoke(jaxbElement); QueryPersonResponse res = retJaxbElement.getValue(); Person person = res.getReturn(); System.out.println(person.getName()); |
|
返回顶楼 | |
发表时间:2011-11-24
最后修改:2011-11-24
以前用xjc生成的类,对于复杂的schema,会产生一些啰嗦的类。
比方一个list属性或者 string属性,当在schema中将其定义为element而非属性时,xjc后会产生一个类来描述改elment。 这在schema中为了重用有必要,但在java中就显得啰嗦了,做了不必要的抽象和封装 |
|
返回顶楼 | |
发表时间:2011-11-24
JAXB会产生很多类,不便管理,我们大部分使用Smooks解析XML
|
|
返回顶楼 | |
发表时间:2011-11-25
zhuyl_wind 写道 JAXB会产生很多类,不便管理,我们大部分使用Smooks解析XML
Smooks 能根据schema 生成 class 么? |
|
返回顶楼 | |
发表时间:2011-11-26
freish 写道
JAX-WS 的Dispatch client可以用到类似的方式
URL wsdlLocation = new URL("http://127.0.0.1:8080/cxfDemo/DemoService?wsdl"); QName serviceName = new QName("http://demo.com", "DemoService"); QName portName = new QName("http://demo.com", "DemoPort"); JAXBContext context = JAXBContext.newInstance("com.test.bbc"); Service service = Service.create(wsdlLocation, serviceName); Dispatch<Object> dispatch = service.createDispatch(portName, context, Service.Mode.PAYLOAD); ObjectFactory factory = new ObjectFactory(); QueryPerson queryPerson = factory.createQueryPerson(); JAXBElement<QueryPerson> jaxbElement = factory.createQueryPerson(queryPerson); JAXBElement<QueryPersonResponse> retJaxbElement = (JAXBElement<QueryPersonResponse>)dispatch.invoke(jaxbElement); QueryPersonResponse res = retJaxbElement.getValue(); Person person = res.getReturn(); System.out.println(person.getName()); 其实在java里面对于webservice的调用也可以用jdk自带的wsimport命令来生成,例如:
wsimport stock.wsdl -b stock.xml -b stock.xjb wsimport -d generated http://example.org/stock?wsdl |
|
返回顶楼 | |
发表时间:2011-11-26
zhuyl_wind 写道 JAXB会产生很多类,不便管理,我们大部分使用Smooks解析XML
对于自动生成的类,我们是不需要经常管理的,通讯方式是xml格式,我们比较关系的是如果这个xml格式有变动,我们是否可以比较高效的修改代码,例如xml格式变了,我们只需使用xjc命令通过新的schema文件来生成类和对逻辑做些改动即可。 |
|
返回顶楼 | |
发表时间:2012-01-13
JAXB是否可以生成多层结构?
比如,顶层是一个Map,Map里面包含List和Map和Object,List里面也可以存在List、Map和Object。 |
|
返回顶楼 | |
发表时间:2012-10-30
很有用,非常感谢,分享这么好的东西。
|
|
返回顶楼 | |