使用默认ContentType和@RequestMethod.produces

时间:2017-09-07 15:21:28

标签: spring rest spring-mvc content-type

我的Spring应用程序总是返回HTTP 406 - 如果我尝试从我的RestController获取图像,如果我没有使用正确的扩展名或Accept-Header,那么这是不可接受的。

  • curl http://localhost/images/42 - > 406
  • curl http://localhost/images/42.png - > 200
  • curl http://localhost/images/42 -H 'Accept: image/png' - > 200

这是我的控制器代码:

@RequestMapping(path = "/images/{id}", produces = MediaType.IMAGE_PNG_VALUE)
public void getImage(@PathVariable("id") long id, HttpServletResponse response) throws IOException {
    [...]
}

如果没有请求,则AFAICT spring会选择默认内容类型(JSON),这与该方法的结果不兼容,从而显示406。

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.defaultContentType(MediaType.APPLICATION_JSON)
            .favorParameter(true);
}

如果删除默认的ContentType,则没有406,但是如果我省略Accept-Header / file-extension,那么我的其他方法开始生成XML / Plain-Text / HTML / stuff(任意)。 (基于控制器中方法的顺序)

有一些遗留应用程序没有设置标头并依赖JSON,因此这不是一个选项。

TLDR:如果它与我要求的Controller方法兼容,我怎么告诉Spring它应该只使用默认的Content-Type?

1 个答案:

答案 0 :(得分:1)

更改configureContentNegotiation方法以包含默认值后的回退。

ContentNegotiationConfigurer#defaultContentTypeStrategy(ContentNegotiationStrategy) ContentNegotiationStrategy

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    final List<MediaType> defaultMediaTypes = ImmutableList.of(MediaType.APPLICATION_JSON, MediaType.ALL);
    // First try the default, if the method produces (@RequestMapping#produces) something else use any.
    configurer.defaultContentTypeStrategy(request -> defaultMediaTypes)
            .favorParameter(true);
}