当服务器失败时,Spring RequestEntity <object>需要强制接受标头

时间:2017-03-11 23:22:28

标签: spring spring-mvc

我正在使用Spring Framework版本4.3.6。 它适用于RestTemplate,因此支持XMLJSON

提醒:关于HTTP方法,POSTPUT有义务强制定义Content-Type标头。它适用于XMLJSON

我对RequestEntity<Object>有关于测试的情况:

我为POST

创建了以下内容
RequestEntity<Object> requestEntity = 
      RequestEntity.post(uri).contentType(MediaType.APPLICATION_XML)
                             .header("Accept-Language", locale.toString())
                             .body(entity);

直到这里,当服务器没有抛出任何异常时它才能正常工作。这意味着,实体可以毫无问题地保存或保存在数据库中。

在其他测试场景中,实体已存在于数据库中时出现问题。我有@ControllerAdvice通过@ExceptionHandler工作。服务器端的工作方式如何。它捕获异常并生成错误消息但是......

...问题XML一起发生,我收到以下错误消息(当然@Test方法失败)

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '{' (code 123) in prolog; expected '<'
 at [row,col {unknown-source}]: [1,1]; nested exception is java.io.IOException: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '{' (code 123) in prolog; expected '<'
 at [row,col {unknown-source}]: [1,1]

我确实意识到通过以下版本避免错误消息的独特方法:

RequestEntity<Object> requestEntity = 
      RequestEntity.post(uri).contentType(MediaType.APPLICATION_XML)
                             .accept(MediaType.APPLICATION_XML)//<---- new
                             .header("Accept-Language", locale.toString())
                             .body(entity);

我很困惑,为什么它有效,因为POST不是必须定义Accept标头。即使在服务器端,我也可以为ResponseEntity<Object>响应)定义Content-TypeAccept标头到XML的值,{{ 1}}失败了。解决此问题的唯一方法是为@Test请求)添加RequestEntity<Object>部分。

这里的另一个问题是我们必须假设使用.accept(MediaType.APPLICATION_XML)的其他Java开发人员将创建RestTemplate对象,只需定义RequestEntity<Object>而不用定义Content-Type标题。

注意:即使Accept使用RestTemplate方法

,也会失败

同样,它只发生在setErrorHandler,对于XML我有以下内容:

JSON

并且始终适用于有效和无效(已保留的实体)方案。

解决这种情况的最佳方法是什么?

α

即使我做了以下版本的建议:

RequestEntity<Object> requestEntity = 
      RequestEntity.post(uri).contentType(MediaType.APPLICATION_JSON_UTF8)
                             .header("Accept-Language", locale.toString())
                             .body(entity);

我得到同样的情况

关于@Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(true) .favorParameter(false) .ignoreAcceptHeader(false) //.defaultContentType(new MediaType(MediaType.TEXT_PLAIN, StandardCharsets.UTF_8)) .defaultContentType(new MediaType(MediaType.APPLICATION_XML, StandardCharsets.UTF_8)) .mediaType("html", MediaType.TEXT_HTML) .mediaType("xml", new MediaType(MediaType.APPLICATION_XML, StandardCharsets.UTF_8)) .mediaType("json", MediaType.APPLICATION_JSON_UTF8); } ,我不使用XML,因为它不支持通用收藏,因此我使用了杰克逊jackson-dataformat-xml

重要我只有在JAXB2RequestEntity<Object>一起使用时才会出现这种情况,以便进行其他测试

RestTemplate

观察,没有 ResultActions resultActions = mockMvc.perform(post(uri).contentType(MediaType.APPLICATION_XML) .header("Accept-Language", locale.toString()) .content(entity)).andDo(print()); 句。

一切正常。

1 个答案:

答案 0 :(得分:1)

Application/json可能已在某处的服务应用程序中配置为默认媒体类型。这就是为什么除非你将Accept标题指定为application/xml,否则你会得到json响应。

如果要使application/xml成为默认的响应媒体类型,则需要配置ContentNegotiationManagerFactoryBean(可能您已经在执行此操作但是对于application / json)。像这样:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

  /**
    * Setup a simple strategy: use all the defaults and return XML by default when not sure. 
    */
  @Override
  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.defaultContentType(MediaType.APPLICATION_XML);
  }
}

您可以在spring文档here中找到它。

您需要关注的另一件事是您在错误场景中使用的实体。如果使用Jaxb注释(@XmlRootElement

正确注释