昨天在編寫一個程式的時候,使用@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種配置的解決方案,在我這裡無法解決問題,暫時不知道是什麼原因。