【问题标题】:Is there a way to have a root element wrapper with javax.xml?有没有办法让 javax.xml 有一个根元素包装器?
【发布时间】:2011-11-18 05:04:19
【问题描述】:

我有一份 Jeresey 申请。我有几个资源使用带有 javax.xml 注释的提供者注释的 bean,因此结果以 xml 或 json 形式返回,具体取决于在接受标头中发送的内容,xml 是默认值。一切正常。现在,我需要为每个响应添加一个根元素。

这是一个示例 Provider Bean,资源用数据设置并返回结果。

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "error")
public class ErrorProvider {


private String errorCode;
private String errorMessage;

public ErrorProvider(){}

public ErrorProvider(final String errorCode,final String errorMessage){
    setErrorCode(errorCode);
    setErrorMessage(errorMessage);
}

@XmlAttribute(name = "number")
public String getErrorCode() {
    return errorCode;
}

public void setErrorCode(final String errorCode) {
    this.errorCode = errorCode;
}

@XmlElement
public String getErrorMessage() {
    return errorMessage;
}

public void setErrorMessage(final String errorMessage) {
    this.errorMessage = errorMessage;
}
}

资源方法上的produces注解是:

@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})

所以默认返回是 XML,除非在请求的接受标头中定义了 json。就像我说的,这很好用。它返回如下内容:

<error code="100">
    <errorMessage>An error occurred</errorMessage>
</error>

好的,背景说得够多了,现在是问题。我需要为所有这些提供者添加一个根元素,这对所有提供者都是一样的。所以它看起来像这样:

<transaction>
    <status>ok</status>
    <error code="100">
        <errorMessage>An error occurred</errorMessage>
    </error>
</transaction>

在类级别拥有类似@XmlElementWrapper 的东西会很酷。我尝试创建另一个用 javax.xml 注释的 bean 并尝试扩展它,尝试做一个泛型类型的 bean。我就是想不通。我能做的最好的事情是在错误 XML 中包含事务注释,就像它是另一个元素一样。我知道我可以编辑每个提供者 bean 以包含事务根元素,但我认为应该有一种方法可以创建一次并应用于每个提供者 bean。

【问题讨论】:

  • 你不能创建一个名为 Transaction 的 Bean,其中包含一个字段 status 和另一个类型为 ErrorProvider 的字段 error 并适当地添加注释吗?
  • a deeper at how jaxb works,我猜你在找@XmlType,但我不确定你的问题是否理解
  • T Man - 我想到了这一点,并且在这种情况下它工作得相当好,但是我有多个 Provider bean 我需要这样做,所以拥有多个 Provider 不是一个可行的解决方案在主 Transaction bean 中键入字段。
  • 我会进一步研究 XmlType,当我读到它时,它似乎并没有达到我想要的效果。所有的提供者 bean 都可以正常工作——我只需要在返回时将它们都包装在一个标准元素中——希望这会有所帮助..

标签: java xml jersey


【解决方案1】:

您可以添加一个使用 Transaction 对象包装您的响应的 ContainerResponseFilter。这就是它的样子(未经测试):

public class MyFilter implements ContainerResponseFilter {
    @Override
    public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
        response.setEntity(new Transaction(response.getEntity()));
        return response;
    }
}

您可以在此处了解有关如何注册过滤器的更多信息:http://jersey.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/package-summary.html

【讨论】:

  • 这听起来很有希望。听起来资源方法的响应将通过那里过滤,我可以在其中应用标准包装器元素。我试试看。
  • 没错——您将拥有一个 Transaction bean(使用 XmlRootElement 注释),当过滤器被调用时,它会修改响应,以便通过 Transaction 对象包装当前实体。所以,一旦泽西试图编组,它应该吐出正确的东西。确保您的 Transaction 类具有公共默认构造函数以及采用您要包装的类型的构造函数(上面的代码在传递给 Transaction 构造函数时应该转换为该类型)。
  • 这实际上效果很好,而且我认为这是更好的方法,在出路时。我希望过滤器用于每个响应,但实体可以是任何提供程序 bean 的实例。这是我能够做到的唯一方法。为实体可能是的每个提供者 bean 在事务 bean 上定义一个属性。在过滤器上检查实体的实例并适当地转换它。有没有办法使整个过程更加成熟?我不确定如何设置事务 bean 以了解它可能需要处理的不同类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 2020-05-05
  • 1970-01-01
  • 2011-02-15
  • 2012-01-31
  • 2021-07-19
相关资源
最近更新 更多