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);
}
}
我已经创建了这个 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);
}
}