spring 文件扩展名请求映射 http 错误 406

spring requestmapping http error 406 on file extension

我已经创建了这个 REST 映射,以便它可以接受 URI 末尾的文件名...

@RequestMapping(value="/effectrequest/{name}/{imagename:[a-zA-Z0-9%\.]*}", 
        headers="Accept=*/*", method=RequestMethod.GET, 
        produces = "application/json")
public @ResponseBody EffectRequest effectRequest(
        @PathVariable("name") String name,
        @PathVariable("imagename") String imageName)
{
    return new EffectRequest(2, "result");
}       

其中 returns JSON 内容使用 MappingJackson2HttpMessageConverter。我用 ...

测试 jQuery AJAX 调用此映射
var effectName = 'Blur';
var imageName = 'Blah.jpg';
var requestUri = '/effectrequest/' + effectName + '/' + imageName;
alert(requestUri);

$(document).ready(function() {
$.ajax({
        url: /*[+   [[${hostname}]] + requestUri   +]*/
    }).then(function(data) {
       $('.effect').append(data.id);
       $('.image').append(data.content);
    });
});

这会生成 http://localhost/effectrequest/Blur/Blah.jpg 的 URI,并且在调试会话中,文件名在上面的 effectRequest() 方法中被正确接收。但是,客户端或 jQuery AJAX 调用从服务器收到 HTTP 406 错误(不可接受),即使 RequestMapping 中有 produces = "application/json"

经过多次调试之后,我缩小了范围 - 当我修改测试 javascript 代码以生成 http://localhost/effectrequest/Blur/Blah.json 的 URI 时,它起作用了。因此,Tomcat 或 MappingJackson2HttpMessageConverter 通过查看 URI 末尾的文件扩展名并确定我发回的 JSON 内容不好导致 HTTP 406 错误匹配。

有没有办法在不必对 .文件名中的(点)?

默认情况下,Spring MVC 在试图找出响应请求的媒体类型时更喜欢使用请求的路径。这在 javadoc for ContentNegotiationConfigurer.favorPathExtension():

中有描述

Indicate whether the extension of the request path should be used to determine the requested media type with the highest priority.

By default this value is set to true in which case a request for /hotels.pdf will be interpreted as a request for "application/pdf" regardless of the Accept header.

在您的情况下,这意味着对 /effectrequest/Blur/Blah.jpg 的请求被解释为对 image/jpeg 的请求,这使得 MappingJackson2HttpMessageConveter 试图编写一个 image/jpeg 响应做不到。

您可以使用通过扩展 WebMvcConfigurerAdapter 访问的 ContentNegotiationConfigurer 轻松更改此配置。例如:

@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void configureContentNegotiation(
            ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false);
    }
}