JAXB2.0编组和解组实现

 

       JAXB是数据绑定框架之一,它在SOA的实现(如WebService)中被广泛的应用。这里所说的“绑定”是指XML文档与JAVA对象树之间的关联关系:可以根据JAVA对象树生成XML实例文档,这一过程叫做“编组”;而根据XML实例文档生成JAVA对象树的过程叫做“解组”。与JAXB类似的框架还有XMLBeans和Castor等。

       从另一方面来讲,JAXB也是XML解析方式之一。与SAX和DOM等不同的是,在解析的过程中操作的不再是DOM节点,取而代之的是JAVA对象树。

       JAXB最核心的接口和类有如下几个:

       1)javax.xml.bind.Marshaller:编组器。提供编组、验证、事件处理等操作;

       2)javax.xml.bind.Unmarshaller:解组器。提供解组、验证、事件处理等操作;

       3)javax.xml.bind.JAXBContext:JAXB客户端的入口。提供了实现 JAXB 所需的解组器、编组器和验证等。

       JAXB在核心的基础上提供了验证和事件处理的功能。

       验证的目的在于保证编组结果或用于解组的资源数据是符合相关模式(Schema或DTD)规范的。JAXB1.0验证实现采用的是JAXP早期的验证方法,即通过调用Marshaller和Unmarshaller实例对象的setValidating(boolean validating)来控制是否启用验证,不过这种方式在JAXB2.0中已被废弃,取而代之的是采用JAXP的验证分离方式,即通过调用Marshaller和Unmarshaller实例对象的setSchema(Schema schema)方法,设置相关的验证模式即可。(JAXP的验证可参考http://code727.iteye.com/blog/1908320)

       默认情况下,JAXB在编组或解组的过程中,如果发现所绑定的数据资源不符合相关的模式约束时,只是简单的抛出MarshalException和UnmarshalException,并会阻止当前编组或解组过程继续往下进行。为了更好的控制验证出现错误时的后续行为以及对错误信息的展示,JAXB提供了一个javax.xml.bind.ValidationEventHandler接口专门来做这些工作,用户需自定义实现此接口,完成后将相关的实例对象赋予Marshaller和Unmarshaller实例对象即可。

 

       从上面UML图中可看出,ValidationEventHandler接口只声明了一个public boolean handleEvent( ValidationEvent event )方法,这个方法不需要在客户端进行显示调用,而是当发生验证错误时,由Marshaller和Unmarshaller实例对象自动回调,此方法返回boolean值,表示是否继续进行后续的处理。

       ValidationEventHandler可以处理三种类型的错误,如下:

       1)Warning:警告,对应ValidationEvent.WARNING常量标识;

       2)Error:一般性错误,对应ValidationEvent.ERROR常量标识;

       3)Fatal Error:严重错误,对应ValidationEvent.FATAL_ERROR常量标识。

       handleEvent()方法的参数是一个ValidationEvent接口对象,当错误发生时,可通过此对象可获取到错误信息以及错误在文档中的坐标位置(javax.xml.bind.ValidationEventLocator)。
       JAXB另外一个核心部分就是模式(Schema或DTD),上述的编组、解组和验证等都是围绕模式来开展的:

       1)对于编组来说,模式是根据JAVA对象树生成XML实例文档的依据;

       2)对于解组来说,模式是将XML实例数据绑定到JAVA对象树上的依据;

       3)更为重要的是,模式是构建(生成)JAVA对象树结构的依据,在解组和编组被执行之前,相关的JAVA对象树结构是必须存在的。

      JAXB需要相关的参考实现来支持。例如,SUN的JAVA Web Service开发包(WSDP)就包括了相关的实现,但对于JAXB1.0和2.0来说,各自的实现有着比较显著的区别,如下:

 JAXB1.0JAXB2.0
定义
  1. JSR31;
  2. 解组和编组操作以及炎症时所用的API;
  3. 模式编译器的绑定方式。
  1. JSR222;
  2. JavaEE5规范的一部分,依赖于注解(Annotation)和泛型(参数类型)。
主要特征/区别
  1. 实现支持W3C XML Schema的子集;
  2. 不能将任意的JAVA类绑定到XML,用于编组的类必须是通过JAXB模式编译器所生成的;
  3. 为每个XML Schema中的组件都生成公共接口和私有实现类;
  4. 支持对生成类实例的模式进行验证,但也可以选择禁止验证。
  1. 全面支持W3C XML Schema规范;
  2. 通过注解可以将任意的JAVA类绑定到XML;
  3. 只生成不会实现任何特定接口或继承任何类的POJO类,编组和解组所需的元数据都包括在JAVA注解中;
  4. 本身不支持验证,而是集成JAXP的验证;
  5. 不仅包括JAXB1.0的模式编译器,还包括Schema(模式)生成器,可以查找JAVA类中的注解并生成XML Schema;
  6. 集成StAX:Marshaller接口的实现将JAVA对象树编组为一个java.xml.stream.XMLStreamWriter或java.xml.stream.XMLEventWriter对象;Unmarshaller接口的实现将java.xml.stream.XMLStreamReader或java.xml.stream.XMLEventReader对象解组为一棵JAVA对象树。
  7. 支持回调方法,允许在对象被编组或解组之前或之后,进行相关的额外操作。还允许向编组器或解组器中的实例中注册监听对象,以便接收每个对象的编组和解组事件。

 

       WSDP可以在https://jaxb.java.net中下载,完成后解压文件,例如:jaxb-ri-2.2.7,在此文件夹里又包含了如下4个主要目录:

       1)bin:包含运行模式编译器和生成器的批处理脚本;

       2)doc:包含编译器和生成器的说明文档和JAXB API的JAVAdocs;

       3)lib:包含JAXB API和参考实现的JAR文件;

       4)samples:包含各类JAXB应用程序示例。

       如果我们的应用程序是运行在Jdk1.6+版本上的,则无需进行WSDP的安装,其中JAR里的实现已包含在了JRE(rt.jar)中。

       在Linux或Window的命令终端中键入如下命令:

       xjc -version

       如果随后输出xjc的版本信息,则说明JAXB运行环境已准备就绪。

 

一、JAXB2.0编组实现

       利用JAXB进行编组的第一步就是为JAVA对象树模型创建模式(Schema或DTD) 。例如: 一个简易版的工作简历(Resume)模板的模式定义为如下所示:

       

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://www.jaxbdemo.daniele.com/resume" 
	xmlns:tns="http://www.jaxbdemo.daniele.com/resume">

	<!-- 简历根元素 -->
	<xsd:element name="resume" type="tns:resume"/>
	
	<!-- 简历内容定义 -->	
	<xsd:complexType name="resume">
		<xsd:sequence>
			<xsd:element name="baseInfo" type="tns:baseInfo" />
			<xsd:element name="selfAssessment" type="tns:selfAssessment" />
			<xsd:element name="careerObjective" type="tns:careerObjective" >
				<!-- 定义各个location子元素之间的文本值不能重复 -->
				<xsd:unique name="location" >
					<xsd:selector xpath=".//location"></xsd:selector>
					<xsd:field xpath="."></xsd:field>
				</xsd:unique>
			</xsd:element>
		</xsd:sequence>
		<xsd:attribute name="id" use="optional" />
	</xsd:complexType>
	
	<!-- "基本信息"部分定义 -->
	<xsd:complexType name="baseInfo">
		<xsd:sequence>
			<xsd:element name="name" type="xsd:string"/>
			<xsd:element name="gender" type="tns:gender" />
			<xsd:element name="birthDate" type="xsd:date" />
			<xsd:element name="residency" type="xsd:string" />
			<xsd:element name="experience" type="tns:experience" />
			<xsd:element name="email" type="tns:email" />
			<xsd:element name="mobilePhone" type="tns:mobilePhone" />
			<xsd:element name="height" type="tns:height" minOccurs="0" maxOccurs="1" />
			<xsd:element name="maritalStatus" type="tns:maritalStatus" minOccurs="0" maxOccurs="1" />
		</xsd:sequence>
	</xsd:complexType>
	
	<!-- "自我评价"部分定义 -->
	<xsd:complexType name="selfAssessment">
		<xsd:sequence>
			<xsd:element name="description" type="xsd:string"/>
		</xsd:sequence>
	</xsd:complexType>
	
	<!-- "求职意向"部分定义 -->
	<xsd:complexType name="careerObjective">
		<xsd:sequence>
			<xsd:element name="jobType" type="tns:jobType" default="Full-time"/>
			<xsd:element name="location" type="tns:location" minOccurs="1" maxOccurs="5" />
		</xsd:sequence>
	</xsd:complexType>
	
	<!-- 性别类型定义 -->
	<xsd:simpleType name="gender">
		<xsd:restriction base="xsd:string">
			<xsd:enumeration value="male" />
			<xsd:enumeration value="female" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 工作年限定义 -->
	<xsd:simpleType name="experience">
		<xsd:restriction base="xsd:integer">
			<xsd:minExclusive value="-1" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 电子邮件定义 -->
	<xsd:simpleType name="email">
		<xsd:restriction base="xsd:string">
			<xsd:pattern value="(\w+\.)*\w+@(\w+\.)+[A-Za-z]{2,9}" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 移动电话定义 -->
	<xsd:simpleType name="mobilePhone">
		<xsd:restriction base="xsd:string">
			<xsd:pattern value="\d{11}" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 身高定义 -->
	<xsd:simpleType name="height">
		<xsd:restriction base="xsd:int">
			<xsd:minExclusive value="0" />
			<xsd:maxExclusive value="300" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 婚姻状况定义 -->
	<xsd:simpleType name="maritalStatus">
		<xsd:restriction base="xsd:string">
			<xsd:enumeration value="married" />
			<xsd:enumeration value="unmarried" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 工作性质定义 -->
	<xsd:simpleType name="jobType">
		<xsd:restriction base="xsd:string">
			<xsd:enumeration value="Full-time" />
			<xsd:enumeration value="Part-time" />
			<xsd:enumeration value="Intern/Trainee" />
			<xsd:enumeration value="Both Full-time And Part-time" />
		</xsd:restriction>
	</xsd:simpleType>
	
	<!-- 工作地点定义 -->
	<xsd:simpleType name="location">
		<xsd:restriction base="xsd:string">
			<xsd:minLength value="1" />
			<!-- 移除开头和结尾部分的空格,而中间多个连续的空格会被缩减为一个的空格 -->
			<xsd:whiteSpace value="collapse" />
		</xsd:restriction>
	</xsd:simpleType>
	
</xsd:schema>
       根据JAXB2.0的规范,第二步则是编译上述的Schema并生成对应的JAVA对象树模式,即相关的POJO类。这里需要使用xjc来编译,例如:

 

       xjc -p com.daniele.jaxbdemo.resume.domain -d src resource/resume.xsd

       表示将resource/resume.xsd生成的基础类放到src输出目录下的com.daniele.jaxbdemo.resume.domain包中。其中-p和-d是命令行参数,更多的参数可参考WSDP的文档。

      
图1 xjc编译命令

图2 xjc编译生成的类
   

       从图2中可看出还生成了一个ObjectFacotory,它是一个专门创建complexType元素的工厂类。上述两步确认无误后就可以进行相关的编组实现了。

       编组实现的基础步骤如下:

       1)按照Schema规则设置JAVA对象树各节点值;

       2)创建JAXBContext实例;

       3)根据Context实例创建Marshaller实例;

       4)创建用于输出目的的JAXBElement实例;

       5)调用Marshaller实例的marshal()方法,并将上述的JAXBElement实例传递给此方法。

      

package com.daniele.jaxbdemo.resume.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import com.daniele.jaxbdemo.resume.domain.BaseInfo;
import com.daniele.jaxbdemo.resume.domain.CareerObjective;
import com.daniele.jaxbdemo.resume.domain.Gender;
import com.daniele.jaxbdemo.resume.domain.JobType;
import com.daniele.jaxbdemo.resume.domain.MaritalStatus;
import com.daniele.jaxbdemo.resume.domain.ObjectFactory;
import com.daniele.jaxbdemo.resume.domain.Resume;
import com.daniele.jaxbdemo.resume.domain.SelfAssessment;
import com.daniele.jaxbdemo.validation.JAXBValidationEventHandler;
import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;

/**
 * <p>简历模板编组测试类</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-7-29
 * @see     
 * @since   JAXBDemo1.0.0
 */
public class ResumeMarshallerTest {

	public static void main(String[] args) throws JAXBException, IOException, SAXException {
		
		ObjectFactory factory = new ObjectFactory();
		
		/* 设置"基础信息"部分的数据 */
		BaseInfo baseInfo = factory.createBaseInfo();
		baseInfo.setName("daniele");
		baseInfo.setGender(Gender.MALE);
		baseInfo.setBirthDate(XMLGregorianCalendarImpl.createDate(1983, 7, 27, 0));
		baseInfo.setExperience(new BigInteger("7"));
		baseInfo.setEmail("code727@gmail.com");
		baseInfo.setMobilePhone("13888888888");
		baseInfo.setResidency("ChengDu Hi Tech Zone");
		baseInfo.setHeight(171);
		baseInfo.setMaritalStatus(MaritalStatus.MARRIED);
		
		/* 设置"自我描述"部分的数据 */
		SelfAssessment selfAssessment = factory.createSelfAssessment();
		selfAssessment.setDescription("5 years java development and 2 years test management.");
		
		/* 设置"求职意向"部分的数据 */
		CareerObjective careerObjective = factory.createCareerObjective();
		careerObjective.setJobType(JobType.FULL_TIME);
		List<String> location = new ArrayList<String>();
		location.add("ChengDu");
		location.add("DuJiangYan");
		careerObjective.setLocation(location);
		
		/* 设置根元素<Resume>下的各个子元素 */
		Resume resume = factory.createResume();
		resume.setBaseInfo(baseInfo);
		resume.setSelfAssessment(selfAssessment);
		resume.setCareerObjective(careerObjective);
		
		// 根据上下文路径(用于绑定目的的POJO类所在的包路径)创建JAXB上下文
		JAXBContext context = JAXBContext.newInstance("com.daniele.jaxbdemo.resume.domain");
		Marshaller marshaller = context.createMarshaller();
		
		File schemaSource = new File("resource/resume.xsd");
		Schema schema = SchemaFactory.newInstance(
				XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaSource);
		// 设置编组过程中所遵循的验证规则。如果不设置,则不能保证最终的编组结果是合法的。
		marshaller.setSchema(schema);
		
		JAXBValidationEventHandler handler = new JAXBValidationEventHandler();
                handler.setContinueWhenWarning(true);
		handler.setContinueWhenError(false);
		handler.setContinueWhenFatalError(false);
		
		/*
		 *  设置在编组过程中所使用的验证事件处理器。
		 *  当Marshaller实例对象中设置了schema对象,并且在编组过程中出现验证警告或错误时,
		 *  则会自动调用处理器的handleEvent()方法进行处理,
		 */
		marshaller.setEventHandler(handler);
		
		// 创建可用于编组输出的根元素
		JAXBElement<Resume> root = factory.createResume(resume);
		
		// 在最终的编组输出中增加xsi:schemaLocation属性,并设置值为Schema文件的URI
		marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, root.getName()
				.getNamespaceURI() + " " + schemaSource.getName());
//		marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, schemaSource.getName());
		// 设置编组后进行格式化输出
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		
		// 编组输出方式一:根据JAXBElement类型的根元素来编组
//		marshaller.marshal(root, new FileOutputStream(new File(
//				"resource/resume_daniele.xml")));
		
		/*
		 *  编组输出方式二:根据某个POJO类实例所表示的根元素来编组
		 *  注意:利用xjc命令在生成POJO类时,没有使用@XmlRootElement注解来将某一个类标注为XML根元素,
		 *       因此这里需要在Resume类上人为的加入此注解。
		 */
		marshaller.marshal(resume, new FileOutputStream(
				new File("resource/resume_daniele.xml")));
	}

}
 
package com.daniele.jaxbdemo.validation;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.ValidationEventLocator;

/**
 * <p>JAXB编组或解组验证事件处理器</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-7-29
 * @see     
 * @since   JAXBDemo1.0.0
 */
public class JAXBValidationEventHandler implements ValidationEventHandler {
	
	private static final String WARNING_EVENT = "Warning";
	
	private static final String ERROR_EVENT = "Error";
	
	private static final String FATAL_ERROR_EVENT = "FatalError";
	
	private Writer writer;
	
	private StringBuffer message;
	
	/** 当出现警告级别的验证问题时是否还继续后续处理 */
	private boolean continueWhenWarning = true;
	
	/** 当出现一般性错误级别的验证问题时是否还继续后续处理 */
	private boolean continueWhenError = false;
	
	/** 当出现致命性错误级别的验证问题时是否还继续后续处理 */
	private boolean continueWhenFatalError = false;
	
	public JAXBValidationEventHandler() {
		this(System.out);
	}
	
	public JAXBValidationEventHandler(OutputStream out) {
		writer = new BufferedWriter(new OutputStreamWriter(out));
		message = new StringBuffer();
	}
	
	/**
	 * <p>处理编组或解组过程中出现的验证警告或错误的通知。</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param event:事件对象
	 * @return 
	 * @since JAXBDemo1.0.0
	 */
	@Override
	public boolean handleEvent(ValidationEvent event) {
		int severity = event.getSeverity();
		try {
			if (severity == ValidationEvent.WARNING)
				return handleWarning(event);
			else if (severity == ValidationEvent.ERROR)
				return handleError(event);
			else
				return handleFatalError(event);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
		
	}
	
	/**
	 * <p>处理警告级别的验证事件</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param event:事件对象
	 * @return 
	 * @throws IOException 
	 * @since JAXBDemo1.0.0
	 */
	protected boolean handleWarning(ValidationEvent event) throws IOException {
		handleEventMessage(event, WARNING_EVENT);
		return continueWhenWarning;
	}
	
	/**
	 * <p>处理一般性错误级别的验证事件</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param event:事件对象
	 * @return 
	 * @throws IOException 
	 * @since JAXBDemo1.0.0
	 */
	protected boolean handleError(ValidationEvent event) throws IOException {
		handleEventMessage(event, ERROR_EVENT);
		return continueWhenError;
	}
	
	/**
	 * <p>处理严重性错误级别的验证事件</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param event:事件对象
	 * @return 
	 * @throws IOException 
	 * @since JAXBDemo1.0.0
	 */
	protected boolean handleFatalError(ValidationEvent event) throws IOException {
		handleEventMessage(event, FATAL_ERROR_EVENT);
		return continueWhenFatalError;
	}
	
	/**
	 * <p>根据事件级别处理提示信息</p> 
	 * @author <a href="mailto:code727@gmail.com">Daniele</a> 
	 * @param event:事件对象
	 * @param eventLevel:事件级别名称
	 * @throws IOException 
	 * @since JAXBDemo1.0.0
	 */
	protected void handleEventMessage(ValidationEvent event, String eventLevel) throws IOException {
		String eventMessage = event.getMessage();
		ValidationEventLocator locator = event.getLocator();
		message.setLength(0);
		message.append(eventLevel).append("[").append(locator.getLineNumber())
				.append(",").append(locator.getColumnNumber()).append("]");
		int index = eventMessage.indexOf(":");
		if (index != -1)
			message.append(eventMessage.substring(index));
		else
			message.append(":").append(eventMessage);
		message.append("\n");
		writer.write(message.toString());
		writer.flush();
	}

	public boolean isContinueWhenWarning() {
		return continueWhenWarning;
	}

	public void setContinueWhenWarning(boolean continueWhenWarning) {
		this.continueWhenWarning = continueWhenWarning;
	}

	public boolean isContinueWhenError() {
		return continueWhenError;
	}

	public void setContinueWhenError(boolean continueWhenError) {
		this.continueWhenError = continueWhenError;
	}

	public boolean isContinueWhenFatalError() {
		return continueWhenFatalError;
	}

	public void setContinueWhenFatalError(boolean continueWhenFatalError) {
		this.continueWhenFatalError = continueWhenFatalError;
	}
	
}
    上述ResumeMarshallerTest运行后将会在resource目录中自动生成resume_daniele.xml实例文档:

 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:resume xmlns:ns2="http://www.jaxbdemo.daniele.com/resume"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.jaxbdemo.daniele.com/resume resume.xsd">
	
	<baseInfo>
		<name>daniele</name>
		<gender>male</gender>
		<birthDate>1983-07-27Z</birthDate>
		<residency>ChengDu Hi Tech Zone</residency>
		<experience>7</experience>
		<email>code727@gmail.com</email>
		<mobilePhone>13888888888</mobilePhone>
		<height>171</height>
		<maritalStatus>married</maritalStatus>
	</baseInfo>
	
	<selfAssessment>
		<description>5 years java development and 2 years test management.</description>
	</selfAssessment>
	
	<careerObjective>
		<jobType>Full-time</jobType>
		<location>ChengDu</location>
		<location>DuJiangYan</location>
	</careerObjective>
	
</ns2:resume>
 

 

二、JAXB2.0解组实现

      与编组实现类似,解组实现的基础步骤如下:

       1)创建JAXBContext实例;

       2)根据Context实例创建Unmarshaller实例;

       3)调用Unmarshaller实例的unmarshal()方法,将解组的XML实例文档资源传递给此方法,并返回绑定了实例数据的JAXBElement实例对象;

       4)从JAXBElement实例对象中获取数据。

 

package com.daniele.jaxbdemo.resume.test;

import java.io.File;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import com.daniele.jaxbdemo.resume.domain.BaseInfo;
import com.daniele.jaxbdemo.resume.domain.CareerObjective;
import com.daniele.jaxbdemo.resume.domain.MaritalStatus;
import com.daniele.jaxbdemo.resume.domain.Resume;
import com.daniele.jaxbdemo.validation.JAXBValidationEventHandler;

/**
 * <p>简历模板解组测试类</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-7-29
 * @see     
 * @since   JAXBDemo1.0.0
 */
public class ResumeUnmarshallerTest {

	public static void main(String[] args) throws JAXBException, SAXException {
		
		JAXBContext context = JAXBContext.newInstance("com.daniele.jaxbdemo.resume.domain");
		Unmarshaller unmarshaller = context.createUnmarshaller();
		
		File schemaSource = new File("resource/resume.xsd");
		Schema schema = SchemaFactory.newInstance(
				XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaSource);
		// 设置解组过程中所遵循的验证规则。如果不设置,则不能保证最终的解组结果是合法的。
		unmarshaller.setSchema(schema);
		
		JAXBValidationEventHandler handler = new JAXBValidationEventHandler();
		handler.setContinueWhenWarning(true);
		handler.setContinueWhenError(false);
		handler.setContinueWhenFatalError(false);
		
		/*
		 *  设置在解组过程中所使用的验证事件处理器。
		 *  当Unmarshaller实例对象中设置了schema对象,并且在解组过程中出现验证警告或错误时,
		 *  则会自动调用处理器的handleEvent()方法进行处理,
		 */
		unmarshaller.setEventHandler(handler);
		
		JAXBElement<Resume> resumeElement = unmarshaller.unmarshal(
				new StreamSource(new File("resource/resume_daniele.xml")),
				Resume.class);
		Resume resume = resumeElement.getValue();
		
		System.out.println("简历详情如下:");
		BaseInfo info = resume.getBaseInfo();
		System.out.println("------ 【基本信息】 ------");
		System.out.println("name       :" + info.getName());
		System.out.println("gender     :" + info.getGender());
		System.out.println("birthDate  :" + info.getBirthDate());
		System.out.println("residency  :" + info.getResidency());
		System.out.println("email      :" + info.getEmail());
		System.out.println("mobilePhone:" + info.getMobilePhone());
		int height = info.getHeight();
		if (height > 0)
			System.out.println("height :" + height);
		MaritalStatus maritalStatus = info.getMaritalStatus();
		if (maritalStatus != null) 
			System.out.println("maritalStatus:" + maritalStatus.value());
		
		System.out.println("------ 【个人评价】 ------");
		System.out.println(resume.getSelfAssessment().getDescription());
		
		CareerObjective careerObjective = resume.getCareerObjective();
		System.out.println("------ 【求职意向】 ------");
		System.out.println("jobType :" + careerObjective.getJobType().value());
		System.out.println("location:" + careerObjective.getLocation());
		
	}
}
      考虑如下一个场景:实际的解组应用通常都发生客户端,我们往往只会接收到服务端发送来的一个XML实例文档,而不知道JAVA对象树模型究竟是怎样的,因此就不能像上述ResumeUnmarshallerTest类里所展示的那样直接从对象树中获取数据(因为在客户端需要一个能接收当前XML实例数据的对象树后,才能获取到被封装的数据),为了解决这个问题,我们需要根据XML实例文档来生成Shcema,然后再从Shcema中生成对象树模型。

 

       因此如何根据XML实例文档来生成Shcema就成为了关键,可以借助第三方的工具来完成,如http://www.xmlforasp.net/CodeBank/System_Xml_Schema/BuildSchema/BuildXMLSchema.aspx,   


 
       如上图,可以在第一个文本框中输入完整的XML实例文档内容后点击“Generate Schema”按钮,等待一段时间,页面会自动生成下面第二个文本框以及Shema结构定义的内容。

       除此之外,在实际的应用中可能还需要根据带了JAXB注解的对象树来生成XML Schema,为此参考实现提供了shcemagen命令来完成这一工作。

24、JAXB 2.0 与 JAX - WS 2.0:实现 Web 服务客户端开发 本文详细介绍了如何利用 JAXB 2.0 和 JAX-WS 2.0 实现 Java Web 服务客户端开发。涵盖了 JAXB 2.0 的多种类型映射方法,包括基于注解和 XML 模式的映射方式,并深入解析了 JAX-WS 2.0 的客户端调用机制,包括服务端点接口(SEI)的生成、代理调用流程及核心注解的作用。通过实际示例演示了如何使用 wsimport 工具和调用 Web 服务的具体代码实现。最后分析了 JAXB 和 JAX-WS 的优势与应用场景,帮助开发者更好地理解和应用这些技术进行高效服务集成与开发 阅读详情

相关推荐

22、JAXB 2.0 数据绑定:注解与绑定语言的应用

本文深入探讨了 JAXB 2.0 数据绑定的两种实现方式:注解和绑定语言。通过具体代码示例,分析了从 Java 类和 XML 模式出发的不同映射方法,并对比了它们的优缺点。同时,文章还介绍了常见问题的解决方案和最佳实践建议,帮助开发者更好地使用 JAXB 2.0 进行数据绑定,确保 XML 与 Java 对象之间的高效转换。

91

Java之xml解析(JAXB方式)

​ JAXB(Java Architecture for XML Binding)是Java API的一部分,它提供了一种将Java类映射到XML结构的方式,也可以将XML结构转换为Java类的实例。它是一种简化Java与XML交互的方式,可以通过注释或外部XML映射文件将Java类与XML元素映射起来。和Marshaller。可以将XML文档转换为Java对象,而Marshaller则可以将Java对象转换为XML文档。而XJC是JAXB的一个辅助工具,用于根据XML Schema生成Java类。

qq_44166712的博客 3337

9、Java Web Services 之 JAXB 2.0 深入解析

本文深入解析了 JAXB 2.0 在 Java Web Services 中的应用,涵盖 JAXB 2.0 的绑定语言、运行时框架、验证机制以及可移植性等核心主题。详细探讨了 JAXB 2.0 在开发 Web 服务时的优势和局限性,并提供了应对策略和性能优化建议。适合希望通过 JAXB 2.0 实现高效 Java Web 服务开发的开发者阅读。

86

JAXB-1 JAXB 概述

JAXB 概述1 JAXB 概述1.1 O/X Mapping1.2 为什么选 JAXB1.3 JAXB 发展历程1.4 JAXB 转换/映射1.5 JAXB 相关的重要类与接口 1 JAXB 概述 JAXB(Java Architecture for XML Binding)是J2SE和J2EE平台的一部分,让开发者能够快速完成Java类和XML的互相映射。 JAXB 允许Java人员将Java...

怀旧豆酱味的专栏 1263

【WILEY】wiley期刊投稿详解:从revision到Accepted全流程实例讲解

注意:包括没标注修改位置的word文件和标注了修改位置的word文件。

Everyday try to become better -Kobe Bryant 1万+

从零搭建一个虚拟ECU:手把手用Autosar CP模块模拟汽车灯控系统(基于Vector工具链)

本文详细介绍了如何使用Vector工具链从零搭建一个基于Autosar CP架构的虚拟ECU系统,模拟汽车灯光控制功能。通过环境搭建、模块配置、通信栈设置到灯光控制逻辑实现的全流程指导,帮助开发者掌握Autosar CP模块术语的实际应用,并提供了系统集成与测试的实用方案。

weixin_42628688的博客 312

Java之JAXB的介绍与使用

Java之JAXB的介绍与使用

m0_47743175的博客 2968

MIT-BEVFusion系列六--bevfusion网络部分流程理解

简述bevfusion网络部分

duanmushuangquan的博客 4895

JAXB学习笔记(一)

JAXB 1. 概述 JAXB(Java Architecture for XML Binding)是J2SE和J2EE平台的一部分,其功能就是让开发者快速的实现Java类和XML的相互映射关系 2. JAXB转换 Java对象转换为XML的过程称为Marshal XML转换为Java对象的过程称之为UnMarshal 2.1 转换方式 XSD(XML Schema Definition) JAXB的 xjc 工具定义 schema 通过 XSD(XML Schema Definition)文档

萝卜_7 1484

25年PINN创新点大盘点!

在科研论文的激烈角逐中,想轻松产出高含金量成果?物理信息神经网络(PINN)堪称“宝藏研究方向”,是冲击高分区论文的绝佳赛道!对于渴望发表优质论文的科研伙伴,这三大研究路径值得重点关注。首先是自适应PINN,在PINN训练过程中,物理方程与实测数据间的矛盾常常导致权重调节困难,而恰好直击这一痛点,是极具价值的研究方向。其次,同样前景广阔,传统多物理场同时训练效果欠佳,如今分阶段训练方法脱颖而出,成效显著且竞争较小。最后,探索及多任务学习等技术的融合,能实现优势叠加,碰撞出创新火花。

Malaai的博客 1970

一文读懂客户健康度

什么是客户健康度?客户健康度为什么重要?怎么计算客户健康度?这篇文章,我们来聊聊。

m0_62700043的博客 1420

oxm java_使用JAXB2.0实现OXM

摘要JavaArchitectureforXMLBinding(JAXB)是一项可以根据XML模式产生Java类的Java技术。该过程中,JAXB也提供了将XML实例文档反编组到Java内容树的方法,并能将Java内容树编组回XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML...

weixin_30895873的博客 1199

AI辅助发明专利撰写实战:30分钟高效生成高质量技术专利文档

在技术专利撰写领域,尤其是软件、算法或系统架构相关的发明专利,如何将创新的技术构思快速、规范地转化为符合《专利法》要求的申请文件,是许多开发者和技术团队面临的共同挑战。传统的人工撰写方式不仅耗时耗力,对撰写人的法律和技术双重背景要求极高,还容易因格式或术语不规范导致审查意见增多。本文将分享一套利用 AI 辅助工具,系统化、高效率地完成一篇高质量发明专利说明书撰写的实战流程。通过清晰的步骤拆解、可复制的提示词(Prompt)工程以及关键注意事项,即使是首次接触专利撰写的开发者,也能在短时间内掌握从技术方案梳理

子夜轻风 953

input发送a.jax_JAX-RS 2.0:自定义内容处理

input发送a.jax 我试图想到一个更好的标题,但未能拿出一个! 请多多包涵……。 JAX-RS 2.0规范允许我们无缝地将JAXB对象编组到HTTP请求/响应主体,或从HTTP请求/响应主体中解组。 简而言之,我们可以使用域对象,而不必担心基于JAX-RS的解决方案中的低级XML序列化。 在开始之前, 这是指向下面引用的源代码的GitHub链接 –并不多,但以防万一,您需要窥视一...

最佳 Java 编程 161

【100%通过率】2023华为od机试C卷【电脑病毒感染】C语言 实现

一个局域网内有很多台电脑,分别标注为 0 ~ N-1 的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t 表示。其中网络内一台电脑被病毒感染,求其感染网络内所有的电脑最少需要多长时间。如果最后有电脑不会感染,则返回-1.

MISAYAONE的博客 1042

27、振动信号实时并行处理与风力发电机模型鲁棒控制设计

本文探讨了振动信号实时并行处理与风力发电机模型鲁棒控制设计两大核心技术。在振动信号处理方面,提出基于FPGA、RT和PC三级架构的并行采集与处理系统,实现高效、实时的振动分析,适用于电机状态监测与预测性维护。在风力发电控制方面,研究风力农场布局优化(WFLO)问题,比较九种多目标元启发式算法性能,并提出基于扰动观察法的最大功率点跟踪(MPPT)控制策略,提升发电效率与系统鲁棒性。研究成果为工业设备智能监控与可再生能源优化提供了有效技术路径。

sunny的博客 72

Spring和JAXB2.0结合使用

由于XML在分布式系统中应用如此广泛,而java又是开发网络和分布式系统可选的最佳运行环境之一,因此,java提供了很多的库,使编程人员能够轻松处理XML数据。在早期,java主要以JAXP定义的相关接口和类处理XML文档。JAXP中包括基于树结构的DOM和基于流方式的SAX和StAX。随着面向对象技术的不断发展,像JAXP这样低层次的XML处理方式,无法满足日益增长的程序规模的需求,因此XOM(

迟到的程序员 3182

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

jaxb教程_JAXB示例教程

jaxb教程Welcome to JAXB Example Tutorial. Java Architecture for XML Binding (JAXB) provides API for converting Object to XML and XML to Object easily. JAXB was developed as a separate project but it was...

从零开始的教程世界 682

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

jaxb 自定义xml_自定义您的JAXB绑定

jaxb 自定义xml JAXB是Java和XML世界之间的桥梁,使您的代码可以透明地编组和解组Java对象与XML之间的关系。 为此,您应该有一个代表XML-Schema的类。 此类由xjc创建。 在大多数情况下,xjc创建的类无法满足您的需求。 在本文中,我们将看到这样做的原因以及可以自定义此行为的方法。 先决条件 本文假设您使用Java开发工具包6.0。 请注意,同一JDK 6...

dlz00001的博客 931

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

JAXB你好世界示例

JAXB ,代表XML绑定的Java体系结构 ,它使用JAXB批注将Java对象与XML文件相互转换。 在本教程中,我们向您展示如何使用JAXB进行以下工作: 编组–将Java对象转换为XML文件。 解组–将XML内容转换为Java对象。 本文使用的技术 JDK 1.6 JAXB 2.0 使用JAXB很容易,只需使用JAXB注释对对象进行注释,然后使用jaxbMa...

一名可爱的技术搬运工 233

JAXB入门

1. 了解JAXB          JAXB 2.0 defines a standard Java/XML binding from Java representations to XML Schema components and vice versa.The goal of JAXB 2.0 is to provide a higher level of abstraction than Java implementations of SAX,DOM, XPath, or other approac

CassieChen的专栏 832

jaxb xml配置_JAXB和Log4j XML配置文件

jaxb xml配置 Log4j 1.x和Log4j 2.x均支持使用XML文件来指定日志记录配置 。 这篇文章探讨了与使用JAXB通过Java类处理这些XML配置文件相关的一些细微差别。 本文中的示例基于Apache Log4j 1.2.17 , Apache Log4j 2.6.2和Java 1.8.0_73(带有JAXB xjc 2.2.8-b130911.1802)。 Log4j...

最佳 Java 编程 498

Jaxb2 转换XML文档

——完成Java对象和XML相互转换 前面有介绍过json-lib这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html 以及Jackson这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html 它们都可以完成Java对象到XML的转换,但是还不是那么的完善。 还有XStream对JSON及XML的支持,它可以对JSON或XML的

hoojo 4251

jaxb报错_JAXB做错了; 尝试Xembly

jaxb报错 JAXB是一项具有10年历史的Java技术,它使我们能够将Java对象转换为XML文档(编组)和返回(取消编组)。 我认为这项技术基于setter和getter,并且通过将对象转换为被动数据结构而违反了面向对象编程的关键原理。 我建议您改用Xembly将Java对象编组为XML文档。 这就是JAXB编组的工作方式。 假设您有一个Book类,需要将其编组为XML文档。 您必须创...

最佳 Java 编程 253

JAXB的继承,解组到封送类的子类

我用JAXB来读写XML。我要的是一个基类JAXB的编组和继承的JAXB类解组。这是为了允许一个发送者的Java应用程序发送XML到另一个接收机的Java应用程序。发送者和接收者将共享JAXB库。我想接收到的XML解组到它扩展了通用的JAXB类接收器特定的JAXB类。 例如: 这是JAXB类,它由发送方。 @XmlRootElement(name="person") public class P

yaov_yy的专栏 4357

XML与Java类映射JAXB

前面介绍了两种常用的解析XML的API,但是 1.什么是XML与Java类的映射?         在Java应用程序中,通常要将XML解析成一个Java对象。例如,有xml数据如下: XML 概述 janet janetval@yahoo.com.cn 20080809 Jav

一直在追逐,一直在妥协 1678
上一篇: JAXP实现Schema和DTD验证
下一篇: Tomcat APR安装
心如止水dy
博客等级 码龄19年 5粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值