如何让 jaxb 插件使用 OffsetDateTime
How to make jaxb plugin use OffsetDateTime
我们有一个 xsd 和 xs:dateTime
个字段。这是我们内部的 API,我们可以保证始终包含偏移量数据,因此它与 ISO-8601 兼容。例如:
2016-01-01T00:00:00.000+01:00
目前,jaxb2 插件将 xs:dateTime
映射到 XMLGregorianCalendar
类型的字段。如何配置插件,使其使用 OffsetDateTime
?
我不关心解决方案是针对 maven-jaxb2-plugin
、jaxb2-maven-plugin
还是 cxf-codegen-plugin
,我们会使用任何有效的方法。
您可以将 jaxb2-maven-plugin
与 jaxb-bindings
文件一起使用。
首先我创建了一个 odt.xsd
文件:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="teste" type="Teste" />
<xsd:complexType name="Teste">
<xsd:sequence>
<xsd:element name="date" type="xsd:dateTime" minOccurs="1"
maxOccurs="1" nillable="false"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
然后我创建了一个 jaxb-bindings.xjb
文件,它定义了 date
字段的类型,以及与之相互转换的 class:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" jaxb:version="2.0">
<jaxb:bindings schemaLocation="odt.xsd">
<jaxb:bindings node="//xsd:element[@name='date']">
<jaxb:javaType name="java.time.OffsetDateTime"
parseMethod="xsd.test.OffsetDateTimeAdapter.parse"
printMethod="xsd.test.OffsetDateTimeAdapter.print" />
</jaxb:bindings>
<jaxb:schemaBindings>
<jaxb:package name="xsd.test" />
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxb:bindings>
此文件引用 xsd.test.OffsetDateTimeAdapter
class 以及将 OffsetDateTime
与 String
相互转换的相应方法,因此我也创建了它:
package xsd.test;
import java.time.OffsetDateTime;
public class OffsetDateTimeAdapter {
public static OffsetDateTime parse(String value) {
return OffsetDateTime.parse(value);
}
public static String print(OffsetDateTime value) {
return value.toString();
}
}
然后,在 pom.xml
中,我添加了插件的配置:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The package of your generated sources -->
<packageName>xsd.test</packageName>
<sources>
<source>src/main/resources/odt.xsd</source>
</sources>
<xjbSources>
<xjbSource>src/main/resources/jaxb-bindings.xjb</xjbSource>
</xjbSources>
</configuration>
</plugin>
有了这个,我刚刚用 mvn clean package
构建了项目,创建的 jar 包含 xsd.test
包中生成的文件。 Teste
class 包含 date
字段作为 OffsetDateTime
:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Teste", propOrder = {
"date"
})
public class Teste {
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected OffsetDateTime date;
// getter and setter
}
有了这个,date
字段被映射到 OffsetDateTime
,使用自动生成的 Adapter1
(内部使用上面创建的 xsd.test.OffsetDateTimeAdapter
class ).从 xml:
解析日期的示例
ObjectFactory f = new ObjectFactory();
JAXBContext context = JAXBContext.newInstance("xsd.test");
Unmarshaller unmarshaller = context.createUnmarshaller();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns2:teste xmlns:ns2=\"xsd.test\"><date>2016-01-01T00:00+01:00</date></ns2:teste>";
JAXBElement<Teste> jaxElement = unmarshaller.unmarshal(new StreamSource(new ByteArrayInputStream(xml.getBytes())), Teste.class);
OffsetDateTime odt = jaxElement.getValue().getDate();
System.out.println(odt); // 2016-01-01T00:00+01:00
并且当将日期编组为 xml 时,OffsetDateTime
直接转换为 String
,例如 2016-01-01T00:00+01:00
.
另一种方法是使用命令行 xjc
,它随 JDK:
xjc src/main/resources/odt.xsd -d src/main/java/ -p xsd.test -b src/main/resources/jaxb-bindings.xjb
这会在 xsd.test
包的 src/main/java
目录中生成 classes。
jTextTime library 解决了这个问题。
库围绕 JDK8 OffsetXXX
date/time 类 因为它们是 XML 模式类型 date
的(唯一)自然等价物, dateTime
和 time
。它还处理 differences between XML types and JSR-310 types,因为不幸的是没有一对一的匹配。
这样使用:
添加依赖:
<dependency>
<groupId>com.addicticks.oss</groupId>
<artifactId>jtexttime</artifactId>
<version> ... latest ...</version>
</dependency>
创建您的 XJC 绑定:
创建一个名为 src/main/xjb/jaxb-datetime-bindings.xjb
的文件,内容如下。
如果您使用的是 JAXB2 Maven 插件,那么插件会自动获取它。如果你正在使用另一个 Maven 插件,那么你必须告诉它在哪里可以找到这个文件。
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file is automatically picked up by the jaxb2-maven-plugin
if it lives in src/main/xjb -->
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jxb:globalBindings>
<!-- Avoid having to work with XMLGregorianCalendar.
Instead, map as follows:
XML dateTime : OffsetDateTime
XML date : OffsetDateTime (time value truncated)
XML time : OffsetTime -->
<xjc:javaType adapter="com.addicticks.texttime.jaxb.OffsetDateTimeXmlAdapter"
name="java.time.OffsetDateTime" xmlType="xs:dateTime"/>
<xjc:javaType adapter="com.addicticks.texttime.jaxb.OffsetDateXmlAdapter"
name="java.time.OffsetDateTime" xmlType="xs:date"/>
<xjc:javaType adapter="com.addicticks.texttime.jaxb.OffsetTimeXmlAdapter"
name="java.time.OffsetTime" xmlType="xs:time"/>
</jxb:globalBindings>
</jxb:bindings>
JAXB2 Maven 插件 将默认获取 src/main/xjb/
文件夹中的所有 .xjb
文件,因此您不必在插件的配置。
项目的 README 有更多关于如何使用库的信息。
我们有一个 xsd 和 xs:dateTime
个字段。这是我们内部的 API,我们可以保证始终包含偏移量数据,因此它与 ISO-8601 兼容。例如:
2016-01-01T00:00:00.000+01:00
目前,jaxb2 插件将 xs:dateTime
映射到 XMLGregorianCalendar
类型的字段。如何配置插件,使其使用 OffsetDateTime
?
我不关心解决方案是针对 maven-jaxb2-plugin
、jaxb2-maven-plugin
还是 cxf-codegen-plugin
,我们会使用任何有效的方法。
您可以将 jaxb2-maven-plugin
与 jaxb-bindings
文件一起使用。
首先我创建了一个 odt.xsd
文件:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="teste" type="Teste" />
<xsd:complexType name="Teste">
<xsd:sequence>
<xsd:element name="date" type="xsd:dateTime" minOccurs="1"
maxOccurs="1" nillable="false"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
然后我创建了一个 jaxb-bindings.xjb
文件,它定义了 date
字段的类型,以及与之相互转换的 class:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" jaxb:version="2.0">
<jaxb:bindings schemaLocation="odt.xsd">
<jaxb:bindings node="//xsd:element[@name='date']">
<jaxb:javaType name="java.time.OffsetDateTime"
parseMethod="xsd.test.OffsetDateTimeAdapter.parse"
printMethod="xsd.test.OffsetDateTimeAdapter.print" />
</jaxb:bindings>
<jaxb:schemaBindings>
<jaxb:package name="xsd.test" />
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxb:bindings>
此文件引用 xsd.test.OffsetDateTimeAdapter
class 以及将 OffsetDateTime
与 String
相互转换的相应方法,因此我也创建了它:
package xsd.test;
import java.time.OffsetDateTime;
public class OffsetDateTimeAdapter {
public static OffsetDateTime parse(String value) {
return OffsetDateTime.parse(value);
}
public static String print(OffsetDateTime value) {
return value.toString();
}
}
然后,在 pom.xml
中,我添加了插件的配置:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The package of your generated sources -->
<packageName>xsd.test</packageName>
<sources>
<source>src/main/resources/odt.xsd</source>
</sources>
<xjbSources>
<xjbSource>src/main/resources/jaxb-bindings.xjb</xjbSource>
</xjbSources>
</configuration>
</plugin>
有了这个,我刚刚用 mvn clean package
构建了项目,创建的 jar 包含 xsd.test
包中生成的文件。 Teste
class 包含 date
字段作为 OffsetDateTime
:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Teste", propOrder = {
"date"
})
public class Teste {
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected OffsetDateTime date;
// getter and setter
}
有了这个,date
字段被映射到 OffsetDateTime
,使用自动生成的 Adapter1
(内部使用上面创建的 xsd.test.OffsetDateTimeAdapter
class ).从 xml:
ObjectFactory f = new ObjectFactory();
JAXBContext context = JAXBContext.newInstance("xsd.test");
Unmarshaller unmarshaller = context.createUnmarshaller();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns2:teste xmlns:ns2=\"xsd.test\"><date>2016-01-01T00:00+01:00</date></ns2:teste>";
JAXBElement<Teste> jaxElement = unmarshaller.unmarshal(new StreamSource(new ByteArrayInputStream(xml.getBytes())), Teste.class);
OffsetDateTime odt = jaxElement.getValue().getDate();
System.out.println(odt); // 2016-01-01T00:00+01:00
并且当将日期编组为 xml 时,OffsetDateTime
直接转换为 String
,例如 2016-01-01T00:00+01:00
.
另一种方法是使用命令行 xjc
,它随 JDK:
xjc src/main/resources/odt.xsd -d src/main/java/ -p xsd.test -b src/main/resources/jaxb-bindings.xjb
这会在 xsd.test
包的 src/main/java
目录中生成 classes。
jTextTime library 解决了这个问题。
库围绕 JDK8 OffsetXXX
date/time 类 因为它们是 XML 模式类型 date
的(唯一)自然等价物, dateTime
和 time
。它还处理 differences between XML types and JSR-310 types,因为不幸的是没有一对一的匹配。
这样使用:
添加依赖:
<dependency>
<groupId>com.addicticks.oss</groupId>
<artifactId>jtexttime</artifactId>
<version> ... latest ...</version>
</dependency>
创建您的 XJC 绑定:
创建一个名为 src/main/xjb/jaxb-datetime-bindings.xjb
的文件,内容如下。
如果您使用的是 JAXB2 Maven 插件,那么插件会自动获取它。如果你正在使用另一个 Maven 插件,那么你必须告诉它在哪里可以找到这个文件。
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file is automatically picked up by the jaxb2-maven-plugin
if it lives in src/main/xjb -->
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jxb:globalBindings>
<!-- Avoid having to work with XMLGregorianCalendar.
Instead, map as follows:
XML dateTime : OffsetDateTime
XML date : OffsetDateTime (time value truncated)
XML time : OffsetTime -->
<xjc:javaType adapter="com.addicticks.texttime.jaxb.OffsetDateTimeXmlAdapter"
name="java.time.OffsetDateTime" xmlType="xs:dateTime"/>
<xjc:javaType adapter="com.addicticks.texttime.jaxb.OffsetDateXmlAdapter"
name="java.time.OffsetDateTime" xmlType="xs:date"/>
<xjc:javaType adapter="com.addicticks.texttime.jaxb.OffsetTimeXmlAdapter"
name="java.time.OffsetTime" xmlType="xs:time"/>
</jxb:globalBindings>
</jxb:bindings>
JAXB2 Maven 插件 将默认获取 src/main/xjb/
文件夹中的所有 .xjb
文件,因此您不必在插件的配置。
项目的 README 有更多关于如何使用库的信息。