【问题标题】:Spring MVC @Response Body XML has extra <string> tags - why?Spring MVC @Response Body XML 有额外的 <string> 标签 - 为什么?
【发布时间】:2015-01-14 22:36:24
【问题描述】:

我已经配置了如下所示的东西:

@Configuration
@EnableWebMvc
@ComponentScan(value = "com.whatever.api")
public class SpringMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(createXmlHttpMessageConverter());
        converters.add(new MappingJackson2HttpMessageConverter());

        super.configureMessageConverters(converters);
    }

    private HttpMessageConverter<Object> createXmlHttpMessageConverter() {
        MarshallingHttpMessageConverter xmlConverter =
            new MarshallingHttpMessageConverter();

        // List<MediaType> mediaType = new ArrayList<>();
        // mediaType.add(MediaType.TEXT_XML);

        XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();
        // xmlConverter.setSupportedMediaTypes(mediaType);
        xmlConverter.setMarshaller(xstreamMarshaller);
        xmlConverter.setUnmarshaller(xstreamMarshaller);

        return xmlConverter;
    }

    @Bean
    MappingJackson2HttpMessageConverter jacksonConverter() {
        return new MappingJackson2HttpMessageConverter();
    }

    @Bean
    MarshallingHttpMessageConverter xmlConverter() {
        return new MarshallingHttpMessageConverter();
    }

    @Bean
    XStreamMarshaller xstreamMarshaller() {
        return new XStreamMarshaller();
    }

    // added to support files in body of add document request
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        return multipartResolver;
    }
}

这里是返回要进入响应的 XML 的方法:

    // @RequestMapping(value = "/getDocuments", method = RequestMethod.GET, produces = { MediaType.TEXT_XML_VALUE })
@RequestMapping(value = "/getDocuments", method = RequestMethod.GET)
@ResponseBody
public String
statementList(@RequestParam("doctype") String doctype,
    @RequestParam("bin") String bin,
    @RequestParam("br") String br,
    @RequestParam("mid") String mid,
    @RequestParam("passwd") String passwd,
    @RequestParam("dates") String dates,
    HttpServletRequest request) {

    String xmlResponse;
    RequestHandler requestHandler = new RequestHandlerImpl(systemProperties, null, tableDataDao);
    xmlResponse = requestHandler.getStatements(bin, br, mid, passwd, dates);
    System.out.println("xmlResponse=" + xmlResponse);

    return xmlResponse;
}

xmlResponse 字符串值是正确的 XML,完全符合我的要求。我的问题是响应最终看起来像这样:

    <string><?xml version="1.0" encoding="UTF-8"?><a bunch of correct, but unformatted, XML here></string>

明显的困难是“”标签似乎不知从何而来。从我注释掉的内容可以看出,我尝试设置 MediaType(为 TEXT_PLAIN、TEXT_XML 和 APPLICATION_XML),无论我选择什么,它都不会删除无关标签。

响应中的 XML 是否正确最终变得相当重要,就像在 xmlResponse String 值中一样。是否有我缺少的设置或其他什么?

【问题讨论】:

    标签: java xml spring spring-mvc


    【解决方案1】:

    看起来您自己在requestHandler 中将响应转换为XML String。但是,requestHandler 应该返回一个业务对象,statementList 应该返回该对象,而不是 String

    @RequestMapping Javadocs

    处理程序方法支持以下返回类型:

    由于statementList 返回String,消息转换器将其转换为XML(这就是为什么您看到您的响应包含在&lt;string&gt;...&lt;/string&gt; 中)。

    【讨论】:

    • 我现在用一个简单的对象进行了尝试,它确实返回了该对象的 XML 版本,但该对象的类的完全限定名称空间作为包装它的标签。那么,如果可能的话,我想知道的是如何抑制这种行为。
    • @SCRawl 我认为这种行为来自XStreamMarshaller,还有其他您可以使用的 XML 编组器(一些 JAXB 的),但我需要一些时间来确认这一切并给出你是一个有意义的回应。
    • 为了清楚起见,这里的用例只是简单地返回一个已格式化为 XML 的字符串(由完全独立的外部进程生成)。我不想将对象表示为 XML。另外:感谢您迄今为止的帮助。
    • 进一步解释:当我禁用 MappingJackson2HttpMessageConverter(和任何其他转换器)并将“生产”设置为 MediaType.APPLICATION_XML_VALUE 时,我得到了我想要的结果。启用此转换器后,如果我没有指定 XML 转换器,Spring 会将我的 XML 字符串视为格式错误的 JSON,并且如果我指定了它,它会将它视为我想要序列化的对象。我的目标似乎是找到一个不像这样的转换器。
    • @SCRawl 也许您已经考虑过这一点,但是您自己将 XML 放入 response 对象呢?即在statementList方法中添加HttpServletResponse参数,并调用response.getOutputStream.print(xmlResponse)
    【解决方案2】:

    在 kuporific 的帮助下,我已经解决了这个问题。

    我必须添加一个转换器,如下所示:

    @Configuration
    @EnableWebMvc
    @ComponentScan(value = "com.roler.api")
    public class SpringMvcConfig extends WebMvcConfigurerAdapter {
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(new MappingJackson2HttpMessageConverter());
            converters.add(new StringHttpMessageConverter());
        }
    
        @Bean
        MappingJackson2HttpMessageConverter jacksonConverter() {
            return new MappingJackson2HttpMessageConverter();
        }
    
        // added to support plain text Spring responses
        @Bean
        StringHttpMessageConverter stringHttpMessageConverter() {
            return new StringHttpMessageConverter();
        }
    ...
    

    然后我必须在此处指定纯文本:

    @RequestMapping(value = "/getDocuments", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
        @ResponseBody public String statementList(...)
    

    ...它无需 HttpServletResponse 对象即可工作。

    再次感谢您的帮助,希望有人能从中受益。

    【讨论】:

      猜你喜欢
      • 2015-03-07
      • 2022-11-20
      • 2020-08-08
      • 1970-01-01
      • 2021-05-06
      • 2013-02-04
      • 2016-03-31
      • 2019-01-02
      • 2011-09-12
      相关资源
      最近更新 更多