昨天在编写一个程序的时候,使用@ResponseBody,以此返回一个json格式的数据,后来发现前台一直报406错误,上网找了很久,有的是配置
<mvc:annotation-driven>
<mvc:message-converters>
<bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
解决的(需要导入fastjson相关包)
有的是配置
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html; charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
解决的(需要导入jackon相关包)
但是,我在这边这两种方法都无效,暂时不知道为什么,然后在网上找到个例子,下载下来之后,里面没有上面的两种配置,只是加了@ResponseBody注解就可以用了,看了一下jar包,发现他用的是3.1.2版本的,而我用的是3.2.5版本的,不知道是不是这个问题,于是debug一下,出现这个问题的原因终于被我找出来了,如下
两个版本的AbstractMessageConverterMethodProcessor类都有一个方法:getAcceptableMediaTypes,这个方法获取可以接收资源类型,就是这个地方,两个版本的处理方式不一样,所以,导致两个版本的结果也不一样,我们看一下实现:
3.2.5版本:
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request) throws HttpMediaTypeNotAcceptableException {
List<MediaType> mediaTypes = this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL) : mediaTypes;
}
3.1.2版本:
private List<MediaType> getAcceptableMediaTypes(HttpInputMessage inputMessage) {
try {
List<MediaType> result = inputMessage.getHeaders().getAccept();
return result.isEmpty() ? Collections.singletonList(MediaType.ALL) : result;
}
catch (IllegalArgumentException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not parse Accept header: " + ex.getMessage());
}
return Collections.emptyList();
}
}
很明显,两个方法不一样,关键的的是第一句代码,3.1.2版本的是直接获取请求头中的Accept,请求头中的Accept为*/*(使用jquery的ajax请求的时候,默认是*/*),所以,json类型的可以匹配到,所以转换成功,而3.2.5版本的获取的方式不是获取请求头,一路跟踪进去,发现它关键的代码实现如下:
protected String getMediaTypeKey(NativeWebRequest webRequest) {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
if (servletRequest == null) {
logger.warn("An HttpServletRequest is required to determine the media type key");
return null;
}
String path = urlPathHelper.getLookupPathForRequest(servletRequest);
String filename = WebUtils.extractFullFilenameFromUrlPath(path);
String extension = StringUtils.getFilenameExtension(filename);
return (StringUtils.hasText(extension)) ? extension.toLowerCase(Locale.ENGLISH) : null;
}
它是从请求的路径来返回可接收的类型,我的SpringMVC匹配的是*.html后缀,所以,它最后返回的是text/html类型,显然,无法匹配,所以最后会报错
根据上面的原因,我代码修改如下,便成功获取到了暑假:
1、将*.html后缀改成/,406错误不报了,也成功的获取到了数据
2、换成3.1.2版本的包,html和/都可以获取到数据
这是我遇到的问题和解决的方法,发出来分享一下,而网上说的那2种配置的解决方法,在我这里无法解决问题,暂时不知道是什么原因。