Java 如何使用ApacheCXF表示没有时区的日期?

Java 如何使用ApacheCXF表示没有时区的日期?,java,web-services,soap,cxf,Java,Web Services,Soap,Cxf,我有一个WSDL,它将元素的类型指定为xs:date 当我使用ApacheCXF生成Java类时,它将变量呈现为javax.xml.datatype.XMLGregorianCalendar(到目前为止都很好) 当CXF呈现包含此内容的XML文档时,它以以下形式呈现它(其中-06:00表示时区): 2000-01-18-06:00 如何将CXF配置为不呈现时区?默认情况下,wsdl的xsd:date映射到XMLGregorianCalendar。如果这不是您想要的,那么如果您正在使用CXF的ws

我有一个WSDL,它将元素的类型指定为xs:date

当我使用ApacheCXF生成Java类时,它将变量呈现为javax.xml.datatype.XMLGregorianCalendar(到目前为止都很好)

当CXF呈现包含此内容的XML文档时,它以以下形式呈现它(其中-06:00表示时区):

2000-01-18-06:00


如何将CXF配置为不呈现时区?

默认情况下,wsdl的
xsd:date
映射到
XMLGregorianCalendar
。如果这不是您想要的,那么如果您正在使用CXF的
wsdl-to-java
工具,那么您可以提供一个绑定文件来覆盖此默认映射:

<jaxws:bindings wsdlLocation="YOUR_WSDL_LOCATION"
          xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <jaxws:bindings  node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='THE_NAMESPACE_OF_YOUR_SCHEMA']">
      <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <jxb:javaType name="java.util.Date" xmlType="xs:date"
                      parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate"
                      printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDate"/>
      </jxb:globalBindings>
  </jaxws:bindings>
</jaxws:bindings>

有关更多详细信息,请参阅“如何将xsd:dateTime映射到java.util.Date?”一节

GregorianCalendar gcal = new GregorianCalendar();
start = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
start.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
不要问我为什么在每一点理智的逻辑中——当将XMLgregorianCalendar编组到xs:date时,它保留了时区

我一直认为-时区可能更适用于xs:dateTime,但我知道。。。关于类型

对我来说,对于xs:date类型,默认设置时区是没有意义的,这是编组逻辑中的一个问题。

要完成Filip的回答(感谢他!),也许这会帮助你们中的一些人

我必须在关注字段日期上声明一个新的XmlAdapter,注释为@XmlJavaTypeAdapter

public class YourDTO {
   // ... 
   @XmlElement
   @XmlSchemaType(name = "dateTime")
   @XmlJavaTypeAdapter(type = XMLGregorianCalendar.class, value = XmlDateAdapter.class)
   public Date yourDate;
   // ...
}
适配器

public class XmlDateAdapter extends XmlAdapter<XMLGregorianCalendar, Date> {

@Override
public XMLGregorianCalendar marshal(Date date) throws Exception {
    GregorianCalendar gcal = new GregorianCalendar();
    gcal.setTime(date);
    XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
    xmlDate.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
    return xmlDate;
}
// ...
公共类XmlDateAdapter扩展了XmlAdapter{
@凌驾
公共XMLGregorianCalendar封送处理(日期)引发异常{
GregorianCalendar gcal=新的GregorianCalendar();
gcal设定时间(日期);
XMLGregorianCalendar xmlDate=DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
setTimezone(DatatypeConstants.FIELD_未定义);
返回日期;
}
// ...
之前的SOAP消息日期格式

2017-04-18T00:00:00+02:00

之后的SOAP消息日期格式

2017-04-18T00:00:00


我在上面找到了2012年的评论,现在我觉得有必要添加一个答案。我正在对一个web服务进行一些更改,不幸的是,该服务必须继续在Java 6上运行。我被要求在XML响应中抑制所有日期和时间字段的时区/偏移量部分。我是通过一个JAXB绑定文件和3对da适配器方法完成的请注意,我的解决方案使用了JodaTime库

以下是我的JAXB 2.1绑定文件:

<?xml version="1.0" encoding="UTF-8"?>
<bindings 
        xmlns="http://java.sun.com/xml/ns/jaxb" 
        version="2.1"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <globalBindings>
        <javaType 
            name="org.joda.time.DateTime"
            xmlType="xs:dateTime"
            parseMethod="com.jimtough.jaxb.DataTypeCondapter.parseDateTime"
            printMethod="com.jimtough.jaxb.DataTypeCondapter.printDateTime" />
        <javaType 
            name="org.joda.time.DateTime"
            xmlType="xs:date"
            parseMethod="com.jimtough.jaxb.DataTypeCondapter.parseDate"
            printMethod="com.jimtough.jaxb.DataTypeCondapter.printDate" />
        <javaType 
            name="org.joda.time.LocalTime"
            xmlType="xs:time"
            parseMethod="com.jimtough.jaxb.DataTypeCondapter.parseTime"
            printMethod="com.jimtough.jaxb.DataTypeCondapter.printTime" />
    </globalBindings>
</bindings>

实际上,我喜欢它映射到XMLGregorianCalendar的事实。我不想更改它。我只想更改在生成的XML文档中呈现XMLGregorianCalendar的特定格式。好的。我不确定这一点,但您可以尝试在上面给出的示例中指定自定义“printMethod”吗?还可以将“javaType”保留为XMLGregorianCalendar.Awesome。这为我带来了好处(自定义JAXB绑定或其他数据类型不是选项)对我来说,这比处理绑定文件容易得多。谢谢!这太好了!我想我会为此花费几个小时。这肯定是个错误。我明白这是稍后的答案,但它肯定是公认的答案。这是一个伟大的解决方案。不必搞乱绑定。同意这应该是公认的答案。
package com.jimtough.jaxb;

import java.util.Date;

import javax.xml.bind.DatatypeConverter;

import org.joda.time.DateTime;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

/**
 * My bizarrely named 'condapter' is a blend of the Java {@code DatatypeConverter}
 * and the Apache CXF {@code DataTypeAdapter} that provides Jodatime {@code DateTime}
 * support instead of {@code java.util.Date}.
 * 
 * @author jtough
 */
public class DataTypeCondapter {

    private DataTypeCondapter() {}

    // Jim Tough - 2017-02-22
    // JodaTime formatters claim to be threadsafe
    private static final DateTimeFormatter DTF_DATE = ISODateTimeFormat.date();
    private static final DateTimeFormatter DTF_DATETIME = ISODateTimeFormat.dateHourMinuteSecondMillis();
    private static final DateTimeFormatter DTF_TIME = ISODateTimeFormat.hourMinuteSecondMillis();

    public static DateTime parseDate(String s) {
        if (s == null) {
            return null;
        }
        Date date = DatatypeConverter.parseDate(s).getTime();
        return new DateTime(date);
    }

    public static String printDate(DateTime dt) {
        if (dt == null) {
            return null;
        }
        return DTF_DATE.print(dt);
    }

    public static LocalTime parseTime(String s) {
        if (s == null) {
            return null;
        }
        Date date = DatatypeConverter.parseTime(s).getTime();
        DateTime dt = new DateTime(date);
        return dt.toLocalTime();
    }

    public static String printTime(LocalTime lt) {
        if (lt == null) {
            return null;
        }
        return DTF_TIME.print(lt);
    }

    public static DateTime parseDateTime(String s) {
        if (s == null) {
            return null;
        }
        Date date = DatatypeConverter.parseDateTime(s).getTime();
        return new DateTime(date);
    }

    public static String printDateTime(DateTime dt) {
        if (dt == null) {
            return null;
        }
        return DTF_DATETIME.print(dt);
    }

}