1

我得到了一个非常复杂的生成类堆栈,需要使用 DWR 在服务器和客户端之间发送它。其中一个类使用 jax.xml.datatype.Duration。这是我使用持续时间创建带有测试数据的 bean 的 Java 代码:

DatatypeFactory df = DatatypeFactory.newInstance();
Duration duration = df.newDuration(RANDOM.nextLong());
testObject.setDuration(duration);

DWR 不喜欢对象中的持续时间:

错误 [org.directwebremoting.dwrp.DefaultConverterManager] - 找不到“com.sun.org.apache.xerces.internal.jaxp.datatype.DurationImpl”的转换器

偶尔我会看到类 com.sun.org.apache.xerces.internal.jaxp.datatype.DurationImpl 的相同消息(我想是当我从 JavaScript 回到 Java 时)

定义常规转换器无济于事:

<dwr:convert type="bean" match="com.sun.org.apache.xerces.internal.jaxp.datatype.DurationImpl"/>
<dwr:convert type="bean" match="javax.xml.datatype.Duration"/>

我确定上述方法不起作用,因为它们不是真正的豆子。但我不知道如何让它发挥作用。我在几个地方读过你可以定义一个自定义转换器,但细节似乎很模糊,在大多数情况下已经过时了。DWR 网站说有一个链接可以解释这一切,但它只是将您链接到 javadoc,这对我的实际实现没有帮助。

谁能帮我弄清楚如何处理持续时间?

4

2 回答 2

2

我找不到提供答案的地方,所以我不得不从不同的地方拼凑一些信息——spring-dwr 模式、扩展所提供的类的示例等。

对于初学者来说,这是配置 spring.xml 的正确方法:

  <dwr:configuration>
    <dwr:init>
        <dwr:converter id="durationConverter" class="com.foo.DurationConverter"/>
    </dwr:init>

    <dwr:convert class="com.sun.org.apache.xerces.internal.jaxp.datatype.DurationImpl" type="durationConverter"/>
    <dwr:convert class="javax.xml.datatype.Duration" type="durationConverter"/>
    ...
  </dwr:configuration>

我不确定我是否需要 DurationImpl 和 Duration 转换声明,但我已经看到了它们的消息,所以我把它们都放进去了。

这是我构建转换器的方式:

public class DurationConverter extends BeanConverter {

    @Override
    public Duration convertInbound(Class<?> type, InboundVariable iv, InboundContext ic) throws MarshallException {
        String value = iv.getValue();

        // If the text is null then the whole bean is null
        if (value == null) {
            return null;
        }

        Duration duration = null;
        try {
            DatatypeFactory df = DatatypeFactory.newInstance();
            duration = df.newDuration(Long.valueOf(value));

        } catch (DatatypeConfigurationException ex) {
            Logger.getLogger(DurationConverter.class.getName()).log(Level.SEVERE, null, ex);
        }

        return duration;
    }

    @Override
    public OutboundVariable convertOutbound(Object o, OutboundContext oc) throws MarshallException {
        Duration duration = (Duration) o;
        String varname = oc.getNextVariableName();
        Map<String, OutboundVariable> ovs = new TreeMap<>();
        OutboundVariable durationOV = getConverterManager().convertOutbound(duration.getSeconds(), oc); 

        ovs.put("duration", durationOV);

        ObjectJsonOutboundVariable oj = new ObjectJsonOutboundVariable();
        oj.setChildren(ovs);

        return oj;
    }
}

希望这可以帮助其他人在同样的事情上挣扎。

于 2013-04-30T13:27:20.613 回答
1

我不知道 DWR,但在查看 com.sun.org.apache.xerces.internal.jaxp.datatype.DurationImpl 时,没有公共默认构造函数,我之前在类似情况下看到过 JAXB 的此类问题。在 JAXB 中,我在包中使用 package-info.java 文件,该文件包含包含在您的案例持续时间中的对象定义(在我的案例中为 java.util.Locale)。我的对象存储在 com.foo.domain 中。

@XmlJavaTypeAdapter(type = java.util.Locale.class, value=com.foo.util.LocaleXmlAdapter.class)
package com.foo.domain;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

现在我的 LocaleXmlAdapter.class 定义

public class LocaleXmlAdapter extends XmlAdapter<String, Locale> {
    @Override
    public Locale unmarshal(String localeString) throws Exception {
        {insert your impl}
    }

    @Override
    public String marshal(Locale locale) throws Exception {
        {insert your impl}
    }
}

这允许 JAXB 解决缺少默认构造函数的问题。

于 2013-04-26T21:00:45.103 回答