2016-11-11 62 views
2

我正在使用Spring Web服務通過wsdl生成的文件使用第三方SAP系統調用的應用程序。將由wsdl生成的XmlGregorianCalendar類型的日期替換爲java.util.Date?

通過ws導入使用wsdl生成的文件之一具有類型爲「XMLGregorianCalendar」的Date屬性,並且作爲響應,我們將獲得相應字段的空值。

我想將日期從XmlGregorianCalendar轉換爲java.util.Date。

已引用:how replace XmlGregorianCalendar by Date? 但無法通過wsdl提供適當的xjb綁定。

如果有人可以建議由wsdl生成的日期轉換,這將是很大的幫助..... 在此先感謝! Shuchi

+1

僅供參考......'java.util.Date'被['java.time.Instant']代替(https://docs.oracle.com/javase/8/docs/api/java/time/Instant .html)在Java 8和更高版本中,都表示在[UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time)中的時間軸上。和['XMLGregorianCalendar'](https://docs.oracle.com/javase/8/docs/api/javax/xml/datatype/XMLGregorianCalendar.html)更適合映射到['java.time.ZonedDateTime'](http ://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html)來保留時區信息。轉換:'myXmlGregCal.toGregorianCalendar()。toZonedDateTime()' –

回答

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); 
    } 
} 
+0

感謝您的回覆......因爲我對此感到陌生,請您幫助我如何將此GlobalBindings與wsdl關聯,以便從thirdPartySap儘管XMLGregorianCalendar日期類型被映射到java.util.Date。 – shuchi

+0

您必須將綁定文件作爲參數傳遞給wsdl2java實用程序。 -b binding.xml – sahoora

4

WSDL沒有處理XJB。 xjb用於xjc編譯器作爲-b參數傳遞。 即

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:日期和xsd:時間類型爲java.util.Calendar。

我不推薦使用java.util.Date。日期處理有很多麻煩(尤其是在不同的時區)。 最好使用java.util.Calendar。日曆是很容易處理和默認轉換器的實現是有在JDK:

javax.xml.bind.DatatypeConverter 

但是,如果你仍然想使用java.Util.Date你需要有自己的小轉爐用了兩個靜態方法「解析」和「打印」,然後將其設置在xjb中。在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); 
    } 
} 

您的對話會是這樣的:

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

「WSDL沒有處理xjb」不確定你的意思。 wsimport調用xjc。 wsimport接受傳遞給xjc的** - b ** * bindingsfile *參數。 – VGR

+0

WSDL - Web服務定義語言。而已。當JAXB生成Java類時,xjb只針對Java中的一個實現 - JAXB。 Java還有更多的實現:Axis,Axis2,XBeans和其他一些... WSDL適用於每個人實現。 C,C++,C#開發人員不知道xjb。 Enven那些使用Axis2的人。 :) – Vadim

+0

啊,我明白了。你的觀點是WSDL本身是語言中立的。 – VGR

-2

這可能是一個黑客位,但它的工作原理。

使用wsimport生成代碼後,您可以在文件中執行查找和替換,用java.util.Date替換對XmlGregorianCalendar的所有引用。 JAXB將樂意爲您做所有的處理,並自動進行轉換。沒有適配器需要。我沒有遇到任何使用這種方法的問題。

+0

不知道爲什麼這是投票。 – spy

+0

如果你投了票,至少有禮貌的評論爲什麼。此方法適用於日期和日曆。 – spy

0

我已經從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參數。

0

的@vadim答案爲我工作有一些額外的細節...

我是用彈簧啓動1.5.3和2.3.1版本JAXB2 - Maven的插件,在那種情況下我不得不宣佈我的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; 
    } 
} 

希望這可以幫助別人! :)

相關問題