3

我们有一个带xs:dateTime字段的 xsd。这是我们内部的 API,我们可以保证始终包含偏移数据,因此它与 ISO-8601 兼容。例如:

2016-01-01T00:00:00.000+01:00

目前,jaxb2 插件映射xs:dateTime到 type 的字段XMLGregorianCalendar。如何配置插件,以便它使用 OffsetDateTime

我不在乎解决方案是否适用于maven-jaxb2-pluginjaxb2-maven-plugin或者cxf-codegen-plugin,我们将使用任何有效的方法。

4

2 回答 2

1

jTextTime 库解决了这个问题。

该库围绕 JDK8OffsetXXX日期/时间类,因为它们是 XML Schema 类型的(唯一)自然等价物datedateTime并且time. 它还处理XML 类型和 JSR-310 类型之间的差异,因为遗憾的是没有一对一的匹配。

像这样使用:

添加依赖:

<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 插件默认会拾取文件夹中的所有.xjb文件src/main/xjb/,因此您不必在插件的配置中指定上述文件。

该项目的README包含有关如何使用该库的更多信息。

于 2019-04-18T00:17:19.360 回答
0

您可以将jaxb2-maven-pluginjaxb-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字段的类型,以及从它转换到它的类:

<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>

该文件引用了将from 和 axsd.test.OffsetDateTimeAdapter转换为的类和相应的方法,因此我也创建了它:OffsetDateTimeString

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包含以下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字段被映射到 a OffsetDateTime,使用自动生成的Adapter1(内部使用xsd.test.OffsetDateTimeAdapter上面创建的类)。从 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.


另一种方法是使用xjcJDK 自带的命令行:

xjc src/main/resources/odt.xsd -d src/main/java/ -p xsd.test -b src/main/resources/jaxb-bindings.xjb

这会src/main/java在包的目录中生成类xsd.test

于 2017-09-11T16:59:48.873 回答