0

场景:我有一个使用 Spring 3 MVC 的 Web 应用程序。使用 Spring 3 中强大的新注释(@Controller、@ResponseBody 等),我编写了一些带有 @XML 注释的域对象,用于编组对 Web 客户端的 ajax 调用。一切都很好。我声明我的 Controller 类有一个带有根 XML 对象的返回类型 @ResponseBody - 有效负载被正确编组并发送到客户端。

问题是内容中的某些数据违反了 XML 合规性。必要时我需要用 CDATA 包装它。我在这里看到一个 POST How to generate CDATA block using JAXB? 建议使用自定义内容处理程序。好的,太棒了!

public class CDataContentHandler extends (SAXHandler|XMLSerializer|Other...) {
 // see http://www.w3.org/TR/xml/#syntax
 private static final Pattern XML_CHARS = Pattern.compile("[<>&]");

 public void characters(char[] ch, int start, int length) throws SAXException {
     boolean useCData = XML_CHARS.matcher(new String(c,start,length)).find();
     if (useCData) super.startCDATA();
       super.characters(ch, start, length);
     if (useCData) super.endCDATA();
 }

}

使用 Spring MVC 3,我该如何实现?关于设置的 JAXB 方面,一切都是“自动”为我完成的,Spring 读取方法的返回类型,查看返回类型的注释并从类路径中提取 JAXB2 来进行编组(对象到 XML转换)。那么允许用户将自定义内容处理程序注册到配置的“钩子”到底在哪里?

使用 EclipseLink JAXB 实现就像将 @XmlCDATA 添加到相关的对象属性一样简单。Spring 是否有一些聪明的方法可以在这里提供帮助/将这个问题抽象为一个小的配置细节?

我知道 Spring 不依赖于任何特定的实现,但是为了这个问题,我们可以假设我使用的是默认实现。我在这里尝试了文档http://static.springsource.org/spring-ws/site/reference/html/oxm.html但据我所知,它对这个问题几乎没有帮助。

感谢大家的任何回复,非常感谢。

更新:

感谢 Akshay 下面的建议答案。这足以让我走上正轨。进一步调查,我发现在 Spring 版本 3.05 和 3.2 之间有一些历史。在 Spring 3.05 中,注册自定义 MessageConverter 曾经非常困难(这确实是这里的目标)。

这段对话几乎解释了所要求的开发更改背后的想法: https ://jira.springsource.org/browse/SPR-7504

这是构建自定义解决方案通常需要的类覆盖的链接:http://static.springsource.org/spring/docs/3.1.0.M1/javadoc-api/org/springframework/http/converter/AbstractHttpMessageConverter 。 html

以下关于堆栈溢出的问题与我所要求的非常相似(除了@ResponseBody 讨论与 JSON 和杰克逊有关) - 目标基本相同。

Spring 3.2 和 Jackson 2:添加自定义对象映射器

所以它看起来像使用,并且需要覆盖 MarshallingHttpMessageConverter,注册到 AnnotationMethodHandlerAdapter。上面的链接中有一个推荐的解决方案,也可以巧妙地使用这些东西并将整个东西包装在自定义定义的注释后面。

我还没有开发出一个可行的解决方案,但是自从我提出问题以来,我想至少发布一些可以帮助其他人解决同样问题的东西,然后开始。恕我直言,尽管在 Spring 3.2 中这一切都得到了改善,但要进行一些定制工作仍然有点像狗吃晚饭......我真的期待一个班轮配置更改等。

而不是扭曲和弯曲 Spring,对于我的特定问题,也许最简单的答案就是更改 JAXB2 实现并使用可以开箱即用的 Eclipse Link JAXB 之类的东西。

4

1 回答 1

0

基本上你需要创建一个自定义的 HttpMessageConverter。而不是依赖 spring 默认使用的 Jaxb2RootElementHttpMessageConverter。

不幸的是,定制一个转换器意味着您告诉 spring 您将负责加载您需要的所有转换器!根据您是否使用注释、组件扫描、Spring 3.1 或更早版本等,这相当复杂并且可能会变得复杂。如何添加自定义转换器的问题在这里解决:使用 @ResponseBody 自定义 HttpMessageConverter 来做 Json 事情

在您的自定义消息转换器中,您可以自由使用任何自定义 JAXB2 内容处理程序。

解决原始问题的另一种更简单的方法是使用自定义XmlJavaTypeAdapter. 创建一个自定义实现javax.xml.bind.annotation.adapters.XmlAdapter来处理 CDATA,在marshal方法中用 cdata 大括号包装返回值。然后在您映射的 pojo 中,使用XmlAdapter注释,将您的自定义适配器的类传递给它,您应该完成。

我自己没有实现适配器方法,所以无法提供示例代码。但它应该可以工作,而且工作量不会很大。

希望这可以帮助。

于 2013-04-19T14:15:15.573 回答