JAXB与Schema验证

JAXB的强大是不言而喻了,它把xml和javabean通过注解绑定在一起,一般情况下,JDK提供的JAXB工具类够用了,但在某些特殊应用下,比如要提供schema验证的时候,就需要更复杂的控制了,废话不说,我们通过以下代码来逐渐实现带schema验证的JAXB,最终提供一个很有用的工具类JAXB。

一,定义一个schema(关于schema的语法在此不予讨论,有兴趣的可以私下交流):upms.xsd

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
 3     targetNamespace="http://www.jxr.com" xmlns:jxr="http://www.jxr.com"
 4     elementFormDefault="qualified" attributeFormDefault="qualified">
 5 
 6     <xs:complexType name="ref">
 7         <xs:attribute name="id" type="xs:string" use="required"></xs:attribute>
 8     </xs:complexType>
 9 
10     <xs:complexType name="user">
11         <xs:complexContent>
12             <xs:extension base="jxr:ref">
13                 <xs:attribute name="name" type="xs:string" use="required"></xs:attribute>
14             </xs:extension>
15         </xs:complexContent>
16     </xs:complexType>
17 
18     <xs:complexType name="role">
19         <xs:complexContent>
20             <xs:extension base="jxr:user">
21                 <xs:sequence>
22                     <xs:element name="user" type="jxr:ref" minOccurs="0"
23                         maxOccurs="unbounded"></xs:element>
24                 </xs:sequence>
25             </xs:extension>
26         </xs:complexContent>
27     </xs:complexType>
28 
29     <xs:complexType name="group">
30         <xs:complexContent>
31             <xs:extension base="jxr:role">
32                 <xs:sequence>
33                     <xs:element name="role" type="jxr:ref" minOccurs="0"
34                         maxOccurs="unbounded"></xs:element>
35                 </xs:sequence>
36             </xs:extension>
37         </xs:complexContent>
38     </xs:complexType>
39 
40     <xs:complexType name="upms">
41         <xs:sequence>
42             <xs:element name="user" type="jxr:user" minOccurs="0"
43                 maxOccurs="unbounded"></xs:element>
44             <xs:element name="role" type="jxr:role" minOccurs="0"
45                 maxOccurs="unbounded"></xs:element>
46             <xs:element name="group" type="jxr:group" minOccurs="0"
47                 maxOccurs="unbounded"></xs:element>
48         </xs:sequence>
49     </xs:complexType>
50 
51     <xs:element name="upms" type="jxr:upms"></xs:element>
52 </xs:schema>

这是一个本人实现的upms框架的xsd文件

二,根据以上的xsd生成一个xml实例。

newfile.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <jxr:upms xmlns:jxr="http://www.jxr.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.jxr.com upms.xsd ">
 3   <jxr:user jxr:id="6" jxr:name="一般用户"/>
 4   <jxr:role jxr:id="5" jxr:name="管理员">
 5     <jxr:user jxr:id="6"/>
 6   </jxr:role>
 7   <jxr:role jxr:id="4" jxr:name="超级管理员">
 8     <jxr:user jxr:id="6"/>
 9   </jxr:role>
10   <jxr:group jxr:id="1" jxr:name="java群">
11     <jxr:user jxr:id="6"/>
12     <jxr:role jxr:id="4"/>
13   </jxr:group>
14   <jxr:group jxr:id="2" jxr:name="c群">
15     <jxr:user jxr:id="6"/>
16     <jxr:role jxr:id="5"/>
17   </jxr:group>
18 </jxr:upms>

三,实体类.

1,User.java

 1 /**
 2  * 
 3  */
 4 package com.jjh.upms;
 5 
 6 import javax.xml.bind.annotation.XmlAttribute;
 7 import javax.xml.bind.annotation.XmlType;
 8 
 9 /**
10  * @author Administrator
11  *
12  */
13 @XmlType(name="user",namespace="http://www.jxr.com")
14 class User extends Ref{
15     private String name;
16     /**
17      * @return the name
18      */
19     @XmlAttribute(name="name",namespace="http://www.jxr.com")
20     String getName() {
21         return name;
22     }
23     /**
24      * @param name the name to set
25      */
26     void setName(String name) {
27         this.name = name;
28     }
29         
30 }

2,Role.java

 1 /**
 2  * 
 3  */
 4 package com.jjh.upms;
 5 
 6 import java.util.ArrayList;
 7 import java.util.List;
 8 import javax.xml.bind.annotation.XmlElement;
 9 import javax.xml.bind.annotation.XmlType;
10 
11 /**
12  * @author Administrator
13  *
14  */
15 @XmlType(name="role",namespace="http://www.jxr.com")
16 class Role extends User{
17     private final List<Ref> users=new ArrayList<>();
18     /**
19      * 
20      */
21     protected Role() {
22         super();
23         // TODO Auto-generated constructor stub
24     }
25     /**
26      * @return the users
27      */
28     @XmlElement(name="user",namespace="http://www.jxr.com")
29     List<Ref> getUsers() {
30         return users;
31     }
32         
33 }

3,Group.java

 1 /**
 2  * 
 3  */
 4 package com.jjh.upms;
 5 
 6 import java.util.ArrayList;
 7 import java.util.List;
 8 import javax.xml.bind.annotation.XmlElement;
 9 import javax.xml.bind.annotation.XmlType;
10 
11 /**
12  * @author Administrator
13  *
14  */
15 @XmlType(name="group",namespace="http://www.jxr.com")
16 class Group extends Role{
17     private final List<Ref> roles=new ArrayList<>();
18 
19     /**
20      * @return the roles
21      */
22     @XmlElement(name="role",namespace="http://www.jxr.com")
23     List<Ref> getRoles() {
24         return roles;
25     }
26     
27 }

4,Ref.java

 1 /**
 2  * 
 3  */
 4 package com.jjh.upms;
 5 
 6 import javax.xml.bind.annotation.XmlAttribute;
 7 import javax.xml.bind.annotation.XmlType;
 8 
 9 /**
10  * @author Administrator
11  *
12  */
13 @XmlType(name="ref",namespace="http://www.jxr.com")
14 class Ref {
15     private String id;
16 
17     /**
18      * @return the id
19      */
20     @XmlAttribute(name="id",namespace="http://www.jxr.com")
21     String getId() {
22         return id;
23     }
24 
25     /**
26      * @param id the id to set
27      */
28     void setId(String id) {
29         this.id = id;
30     }
31     
32     
33 }

5,UPMS.java

 1 /**
 2  * 
 3  */
 4 package com.jjh.upms;
 5 
 6 import java.io.IOException;
 7 import java.io.InputStream;
 8 import java.util.ArrayList;
 9 import java.util.List;
10 import java.util.Objects;
11 import java.util.function.Function;
12 
13 import javax.xml.bind.annotation.XmlElement;
14 import javax.xml.bind.annotation.XmlRootElement;
15 import javax.xml.bind.annotation.XmlType;
16 
17 import com.jjh.common.JAXB;
18 /**
19  * @author Administrator
20  *
21  */
22 @XmlRootElement(name = "upms", namespace = "http://www.jxr.com")
23 @XmlType(name = "upms", namespace = "http://www.jxr.com", propOrder = { "users", "roles", "groups" })
24 public final class UPMS {
25     private final List<User> users = new ArrayList<>();
26     private final List<Role> roles = new ArrayList<>();
27     private final List<Group> groups = new ArrayList<>();
28 
29     /**
30      * 
31      */
32     private UPMS() {
33         super();
34         // TODO Auto-generated constructor stub
35     }
36 
37     /**
38      * @return the users
39      */
40     @XmlElement(name = "user", namespace = "http://www.jxr.com")
41     List<User> getUsers() {
42         return users;
43     }
44 
45     /**
46      * @return the roles
47      */
48     @XmlElement(name = "role", namespace = "http://www.jxr.com")
49     List<Role> getRoles() {
50         return roles;
51     }
52 
53     /**
54      * @return the groups
55      */
56     @XmlElement(name = "group", namespace = "http://www.jxr.com")
57     List<Group> getGroups() {
58         return groups;
59     }
60 
61     
62     
63     public static UPMS create(InputStream configure) throws Exception {
64         UPMS upms=JAXB.loadXml(UPMS.class, configure, UPMS.class.getResourceAsStream("upms.xsd"));
65         try {
66             configure.close();
67         } catch (IOException e) {
68             // TODO Auto-generated catch block
69             e.printStackTrace();
70         }
71         return upms;
72     }
73     
74 }

四,本人提供的工具类

JAXB.java

  1 /**
  2  * 
  3  */
  4 package com.jjh.common;
  5 
  6 import java.io.OutputStream;
  7 import java.io.InputStream;
  8 
  9 import javax.xml.XMLConstants;
 10 import javax.xml.bind.JAXBContext;
 11 import javax.xml.bind.Marshaller;
 12 import javax.xml.bind.Unmarshaller;
 13 import javax.xml.stream.XMLEventWriter;
 14 import javax.xml.stream.XMLOutputFactory;
 15 import javax.xml.transform.stream.StreamSource;
 16 import javax.xml.validation.SchemaFactory;
 17 
 18 import org.xml.sax.ErrorHandler;
 19 import org.xml.sax.SAXException;
 20 import org.xml.sax.SAXParseException;
 21 
 22 /**
 23  * @author Administrator
 24  */
 25 public final class JAXB {
 26 
 27     /**
 28      * 
 29      */
 30     private JAXB() {
 31         super();
 32         // TODO Auto-generated constructor stub
 33     }
 34 
 35     static public <T> T loadXml(Class<T> claze, InputStream xmlUrl, InputStream schemaUrl,
 36             Unmarshaller.Listener listener) throws Exception {
 37         return _loadXml(claze, xmlUrl, schemaUrl, listener);
 38     }
 39 
 40     static public <T> T loadXml(Class<T> claze, InputStream xmlUrl, InputStream schemaUrl) throws Exception {
 41         return _loadXml(claze, xmlUrl, schemaUrl, null);
 42     }
 43 
 44     static public <T> T loadXml(Class<T> claze, InputStream xmlUrl, Unmarshaller.Listener listener) throws Exception {
 45         return _loadXml(claze, xmlUrl, null, listener);
 46     }
 47 
 48     static public <T> T loadXml(Class<T> claze, InputStream xmlUrl) throws Exception {
 49         return _loadXml(claze, xmlUrl, null, null);
 50     }
 51 
 52     @SuppressWarnings("unchecked")
 53     static private <T> T _loadXml(Class<T> claze, InputStream xmlInput, InputStream schemaInput,
 54             Unmarshaller.Listener listener) throws Exception {
 55         try {
 56             JAXBContext jc = JAXBContext.newInstance(claze);
 57             Unmarshaller u = jc.createUnmarshaller();
 58             if (listener != null)
 59                 u.setListener(listener);
 60             if (schemaInput != null) {
 61                 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
 62                 factory.setErrorHandler(new ErrorHandler() {
 63 
 64                     @Override
 65                     public void error(SAXParseException exception) throws SAXException {
 66                         // TODO Auto-generated method stub
 67                         exception.printStackTrace();
 68                     }
 69 
 70                     @Override
 71                     public void fatalError(SAXParseException exception) throws SAXException {
 72                         // TODO Auto-generated method stub
 73                         exception.printStackTrace();
 74                     }
 75 
 76                     @Override
 77                     public void warning(SAXParseException exception) throws SAXException {
 78                         // TODO Auto-generated method stub
 79                         exception.printStackTrace();
 80                     }
 81 
 82                 });
 83                 u.setSchema(factory.newSchema(new StreamSource(schemaInput)));
 84             }
 85             return (T) u.unmarshal(xmlInput);
 86 
 87         } catch (Exception e) {
 88             // TODO Auto-generated catch block
 89             throw e;
 90         }
 91         
 92     }
 93 
 94     static public <T> void writeXml(final T obj, OutputStream xmlUrl) throws Exception {
 95         _writeXml(obj, xmlUrl, null, null);
 96     }
 97 
 98     static public <T> void writeXml(final T obj, OutputStream xmlUrl, String defaultNamespace) throws Exception {
 99         _writeXml(obj, xmlUrl, defaultNamespace, null);
100     }
101 
102     static public <T> void writeXml(final T obj, OutputStream xmlUrl, InputStream schemaUrl) throws Exception {
103         _writeXml(obj, xmlUrl, null, schemaUrl);
104     }
105 
106     static public <T> void writeXml(final T obj, OutputStream xmlUrl, String defaultNamespace, InputStream schemaUrl) throws Exception {
107         _writeXml(obj, xmlUrl, defaultNamespace, schemaUrl);
108     }
109 
110     static private <T> void _writeXml(final T obj, OutputStream xmlOutput, String defaultNamespace,
111             InputStream schemaInput) throws Exception {
112         try {
113             JAXBContext jc = JAXBContext.newInstance(obj.getClass());
114             Marshaller m = jc.createMarshaller();
115             if (schemaInput != null) {
116                 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
117                 factory.setErrorHandler(new ErrorHandler() {
118 
119                     @Override
120                     public void error(SAXParseException exception) throws SAXException {
121                         // TODO Auto-generated method stub
122                         exception.printStackTrace();
123                     }
124 
125                     @Override
126                     public void fatalError(SAXParseException exception) throws SAXException {
127                         // TODO Auto-generated method stub
128                         exception.printStackTrace();
129                     }
130 
131                     @Override
132                     public void warning(SAXParseException exception) throws SAXException {
133                         // TODO Auto-generated method stub
134                         exception.printStackTrace();
135                     }
136 
137                 });
138                 m.setSchema(factory.newSchema(new StreamSource(schemaInput)));
139             }
140             XMLOutputFactory factory = XMLOutputFactory.newInstance();
141             factory.setProperty("javax.xml.stream.isRepairingNamespaces", false);
142             XMLEventWriter xmlOut = factory.createXMLEventWriter(xmlOutput, "UTF-8");
143             if (defaultNamespace != null)
144                 xmlOut.setDefaultNamespace(defaultNamespace);
145             m.setProperty("jaxb.formatted.output", true);
146             m.marshal(obj, xmlOut);
147         } catch (Exception e) {
148             throw e;
149         }
150     }
151 }

五,测试

1 class   Test
2 {
3 public static void main(String[] args)
4 {
5 UPMS upms=UPMS.create(new ByteArrayInputStream("./newfile.xml"));
6 System.out.println(upms);
7 }
8 }

 

posted @ 2017-04-18 10:31  江金汉  阅读(1924)  评论(0编辑  收藏  举报