将wsdl生成的XmlGregorianCalendar类型的日期替换为java.util.Date?

时间:2016-11-11 13:57:27

标签: java date wsdl

我正在开发一个应用程序,我们使用Spring webservices使用wsdl生成的文件调用第三方SAP系统。

使用wsdl到ws import生成的文件之一具有类型为“XMLGregorianCalendar”的Date属性,作为响应,我们为相应的字段获取空值。

我想将日期从XmlGregorianCalendar转换为java.util.Date。

已提及:how replace XmlGregorianCalendar by Date? 但无法通过wsdl提供适当的xjb绑定。

如果有人可以建议转换由wsdl生成的日期,那将会有很大的帮助..... 提前致谢 ! 术赤

5 个答案:

答案 0 :(得分:7)

WSDL与xjb无关。 xjb用于作为-b参数传递的xjc编译器。 即。

xjc -b <file>

文档:Customizing JAXB Binding

如果你使用Maven插件生成你的JAXB Java类,它们中的任何一个都有绑定配置,即

<groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <configuration>
                    <defaultOptions>
                        <bindingFiles>
                            <bindingFile>${project.interfaces.basedir}Configuration/Bindings/common-binding.xjb</bindingFile>
                        </bindingFiles>

<plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <configuration>
                <schemaDirectory>${basedir}/src/main/resources/XMLSchema</schemaDirectory>
                <bindingDirectory>${basedir}/src/main/resources/Bindings</bindingDirectory>
            </configuration>

依旧......

xjb非常简单:

<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings>
    <jaxb:serializable uid="1" />
    <jaxb:javaType name="java.util.Calendar" xmlType="xsd:dateTime"
        parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
        printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
    <jaxb:javaType name="java.util.Calendar" xmlType="xsd:date"
        parseMethod="javax.xml.bind.DatatypeConverter.parseDate" printMethod="javax.xml.bind.DatatypeConverter.printDate" />
    <jaxb:javaType name="java.util.Calendar" xmlType="xsd:time"
        parseMethod="javax.xml.bind.DatatypeConverter.parseTime" printMethod="javax.xml.bind.DatatypeConverter.printTime" />            
</jaxb:globalBindings>

正如您所看到的,它定义了从xsd:dateTime,xsd:date和xsd:time types到java.util.Calendar的转换。

我不建议使用java.util.Date。日期处理存在许多问题(特别是对于不同的时区)。 最好使用java.util.Calendar。日历更容易处理,JDK中有默认的转换器实现:

javax.xml.bind.DatatypeConverter

但是,如果您仍然想使用java.Util.Date,您需要拥有自己的小转换器,其中包含两个静态方法“parse”和“print”,然后将其设置为xjb。即。

public class MyDateConverter {
    public static java.util.Date parse(String xmlDateTime) {
        return javax.xml.bind.DatatypeConverter.parseDateTime(xmlDateTime).getTime();
    }

    public static String print(Date javaDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(javaDate.getTime());
        return javax.xml.bind.DatatypeConverter.printDateTime(calendar);
    }
}

您在xjb中的转化将如下所示:

<jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"
    parseMethod="MyDatatypeConverter.parse"
    printMethod="MyDatatypeConverter.print" />

答案 1 :(得分:1)

您必须创建自定义数据类型适配器并添加绑定文件。

 <jaxb:globalBindings>
    <xjc:serializable uid="-6026937020915831338" />
    <xjc:javaType name="java.util.Date" xmlType="xs:date" 
          adapter="com.test.util.jaxb.DateDataTypeAdapter" />
  </jaxb:globalBindings>
</jaxb:bindings>

类DateDataTypeAdapter

package com.test.util.jaxb;

import java.util.Calendar;
import java.util.Date;
import javax.xml.bind.DatatypeConverter;

public final class DataTypeAdapter {
    private DataTypeAdapter() { }

    public static Date parseDate(String s) {
        if (s == null) {
            return null;
        }

        return DatatypeConverter.parseDate(s).getTime();
    }

    public static String printDate(Date dt) {
        if (dt == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(dt);

        return DatatypeConverter.printDate(c);
    }

    public static Date parseDateTime(String s) {
        if (s == null) {
            return null;
        }

        return DatatypeConverter.parseDateTime(s).getTime();
    }

    public static String printDateTime(Date dt) {
        if (dt == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(dt);

        return DatatypeConverter.printDateTime(c);
    }
}

答案 2 :(得分:1)

我已经从XMLGregorianCalendar更改了bean的java类型,直接在xsd的合同中添加了jaxb的配置。

我这样做了,请注意xs:annotation

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://hello.eomm.it/springws"
targetNamespace="http://hello.eomm.it/springws" elementFormDefault="qualified" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">

<xs:annotation> 
    <xs:appinfo>
        <jaxb:globalBindings>
            <jaxb:serializable uid="1" />
            <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
                parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
            <jaxb:javaType name="java.util.Calendar" xmlType="xs:date"
                parseMethod="javax.xml.bind.DatatypeConverter.parseDate" printMethod="javax.xml.bind.DatatypeConverter.printDate" />
            <jaxb:javaType name="java.util.Calendar" xmlType="xs:time"
                parseMethod="javax.xml.bind.DatatypeConverter.parseTime" printMethod="javax.xml.bind.DatatypeConverter.printTime" />
        </jaxb:globalBindings>
    </xs:appinfo>
</xs:annotation>


<xs:element name="getCountryRequest">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="name" type="xs:string" />
        </xs:sequence>
    </xs:complexType>
</xs:element>


<xs:element name="getCountryResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="country" type="tns:country" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:complexType name="country">
    <xs:sequence>
        <xs:element name="name" type="xs:string" />
        <xs:element name="population" type="xs:int" />
        <xs:element name="capital" type="xs:string" />
        <xs:element name="foundation" type="xs:date" />
        <xs:element name="currency" type="tns:currency" />
    </xs:sequence>
</xs:complexType>

[...]

运行maven构建时,还需要在JVM上添加-Djavax.xml.accessExternalSchema=all参数。

答案 3 :(得分:1)

@vadim的答案对我来说有一些额外的细节......

我使用的是spring boot 1.5.3和jaxb2-maven-plugin的2.3.1版本,在这种情况下,我必须按如下方式声明我的xjb文件:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <packageName>...</packageName>
        <sources>
            <source>src/main/resources/file.xsd</source>
        </sources>
        <xjbSources>
            <xjbSource>src/main/resources/file.xjb</xjbSource>
        </xjbSources>
        <addGeneratedAnnotation>true</addGeneratedAnnotation>
        <locale>es</locale>
    </configuration>
</plugin>

就我而言,xjb文件内容为:

<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
               jaxb:version="2.0"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               jaxb:extensionBindingPrefixes="xjc">
  <jaxb:globalBindings>
    <jaxb:serializable uid="1"/>
    <jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime"
        parseMethod="package.path.bind.DataTypeConverter.parse"
        printMethod="package.path.bind.DataTypeConverter.print"/>
  </jaxb:globalBindings>
</jaxb:bindings>

DataTypeConverter内容为:

import javax.xml.bind.DatatypeConverter;
import java.util.Calendar;
import java.util.Date;

public class DataTypeConverter {

    public static Date parse(String isoFormatDatetime) {
        return DatatypeConverter.parseDateTime(isoFormatDatetime).getTime();
    }
    public static String print(Date date) {
        return DatatypeConverter.printDateTime(toCalendar(date));
    }

    private static Calendar toCalendar(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal;
    }
}

希望这有助于某人! :)

答案 4 :(得分:-2)

这可能有点像黑客,但它确实有效。

使用wsimport生成代码后,您可以在文件中执行查找和替换,将所有对XmlGregorianCalendar的引用替换为java.util.Date。 JAXB将很乐意为您完成所有处理并自动完成转换。无需适配器。我没有遇到任何使用这种方法的问题。