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 }