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

zi8p0yeb  于 2023-05-05  发布在  Java
关注(0)|答案(6)|浏览(124)

我正在开发一个应用程序,在该应用程序中,我们使用Spring Webservices通过WSDL生成的文件调用第三方SAP系统。
通过ws导入使用wsdl生成的文件之一具有类型为“XMLGregorianCalendar”的Date属性,作为响应,我们将获得相应字段的空值。
我想将日期从XmlGregorianCalendar转换为java. util. Date。
曾提及:how replace XmlGregorianCalendar by Date?,但无法通过wsdl提供适当的xjb绑定。
如果有人能建议转换由wsdl生成的日期,这将是很大的帮助。提前感谢!舒池

ogsagwnx

ogsagwnx1#

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:date和xsd:time类型到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" />
ruoxqz4g

ruoxqz4g2#

你必须创建一个自定义的数据类型适配器并添加到绑定文件中。

<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);
    }
}
nmpmafwu

nmpmafwu3#

@vadim的回答对我来说很有用,还有一些额外的细节......
我使用的是spring Boot 1.5.3和2.3.1版本的jaxb 2-maven-plugin,在这种情况下,我必须声明我的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;
    }
}

希望这对某人有帮助!!:)

ogsagwnx

ogsagwnx4#

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

oiopk7p5

oiopk7p55#

我已经将bean的java类型从XMLGregorianCalendar更改,直接在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参数。

mxg2im7a

mxg2im7a6#

感谢Vadim's answer,我最终使用了LocalDateLocalDateTime
xjb:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="3.0" xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    jaxb:extensionBindingPrefixes="xjc">

    <jaxb:globalBindings>
        <xjc:serializable uid="-1" />
        
        <jaxb:javaType
            name="java.time.LocalDateTime"
            xmlType="xs:dateTime"
            parseMethod="JaxbDateConverter.parseDateTime"
            printMethod="JaxbDateConverter.printDateTime"
        />
        
        <jaxb:javaType
            name="java.time.LocalDate"
            xmlType="xs:date"
            parseMethod="JaxbDateConverter.parseDate"
            printMethod="JaxbDateConverter.printDate"
        />
    
        <jaxb:javaType
            name="java.time.LocalDate"
            xmlType="xs:gYearMonth"
            parseMethod="JaxbDateConverter.parseDate"
            printMethod="JaxbDateConverter.printDate"
        />
    
        <jaxb:javaType
            name="java.time.LocalDate"
            xmlType="xs:gYear"
            parseMethod="JaxbDateConverter.parseDate"
            printMethod="JaxbDateConverter.printDate"
        />
    
        <jaxb:javaType
            name="java.time.LocalDate"
            xmlType="xs:gMonthDay"
            parseMethod="JaxbDateConverter.parseDate"
            printMethod="JaxbDateConverter.printDate"
        />
    </jaxb:globalBindings>
</jaxb:bindings>

(not确保它适用于gMonthDay
JaxbDateConverter:

import jakarta.xml.bind.DatatypeConverter;
import lombok.val;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;

public class JaxbDateConverter {
    public static LocalDateTime parseDateTime(String xml) {
        val calendar = DatatypeConverter.parseDateTime(xml);
        val tz = ZoneId.systemDefault();
        val res = LocalDateTime.ofInstant(calendar.toInstant(), tz);
        
        return res;
    }
    
    public static String printDateTime(LocalDateTime date) {
        val calendar = Calendar.getInstance();
        val tz = ZoneId.systemDefault();
        val zoneOffSet = tz.getRules().getOffset(date);
        val ms = date.toEpochSecond(zoneOffSet) * 1000;
        calendar.setTimeInMillis(ms);
        return DatatypeConverter.printDateTime(calendar);
    }
    
    public static LocalDate parseDate(String xml) {
        val calendar = DatatypeConverter.parseDateTime(xml);
        val tz = ZoneId.systemDefault();
        val res = LocalDate.ofInstant(calendar.toInstant(), tz);
        
        return res;
    }
    
    public static String printDate(LocalDate date) {
        val calendar = Calendar.getInstance();
        val tz = ZoneId.systemDefault();
        val dateTime = date.atStartOfDay();
        val zoneOffSet = tz.getRules().getOffset(dateTime);
        val timeStartOfDay = LocalTime.of(0, 0, 0);
        val ms = date.toEpochSecond(timeStartOfDay, zoneOffSet) * 1000;
        calendar.setTimeInMillis(ms);
        return DatatypeConverter.printDateTime(calendar);
    }
}

相关问题