如題,最近以spring mvc作為后台框架,前端異步獲取數據時(.html為后綴名的訪問方式),報406 Not Acceptable錯誤。當初都不知道啥原因,前后台都沒報錯就是返回不了數據,於是查了下http 406響應碼:406 (SC_NOT_ACCEPTABLE)表示請求資源的MIME類型與客戶端中Accept頭信息中指定的類型不一致。下面請看出錯的操作流程及代碼:
1、先配置spring mvc 核心servlet (DispatcherServlet) 至web.xml中,其中配置可以以.html和.do為后綴名的請求。(注意:只顯示重要代碼,下面也是一樣)
<servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dispatcher-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
2、controller部分代碼如下:
@RequestMapping(value="chat/startClient") @ResponseBody public AjaxResult startClient(UserEntity user,HttpServletRequest request) { AjaxResult result = new AjaxResult(1); if (user.getUserId() == null){ user.setUserId(System.currentTimeMillis()); SessionUtil.setAttr(request, SessionUtil.SESSION_USER, user); } else { UserEntity sessionUser = SessionUtil.getUser(request); if (sessionUser.getUserId().equals(user.getUserId())) { user = sessionUser; } } if (Client.startClient(user)) { result.setData(user); } return result; }
3、jsp 異步請求代碼如下:
$.ajax({ url:'${pageContext.request.contextPath}/chat/startClient.html', dataType: 'json', data:{userId:$("input[name=userId]").val(),userName:$("#userName").val()}, success: function(result){ var state = result.error; if(state == 1){ $('.modal-header .close').click(); $("input[name=userName]").val($("#userName").val()); } } });
配置以上代碼啟動項目訪問上面jsp中的異步方法時,通過瀏覽器的開發者工具(google)查看請求結果如下,通過響應頭來看Content-type確實不一樣,返回的是text/html,而請求的是application/json,所以瀏覽器無法解析或者接受這樣的類型,就報錯406錯誤。
針對上面情況在網上折騰了一會,終於找到了破解之法,該問題的主要原因:Spring MVC有點不一樣,如果你沒有配置什么樣的請求方式對應什么樣的響應方式的話,它會根據url的后綴名對應不同響應頭的格式,如下:
public class MediaType extends MimeType implements Serializable { private static final long serialVersionUID = 2069937152339670231L; public static final MediaType ALL = valueOf("*/*"); public static final String ALL_VALUE = "*/*"; public static final MediaType APPLICATION_ATOM_XML = valueOf("application/atom+xml"); public static final String APPLICATION_ATOM_XML_VALUE = "application/atom+xml"; public static final MediaType APPLICATION_FORM_URLENCODED = valueOf("application/x-www-form-urlencoded"); public static final String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded"; public static final MediaType APPLICATION_JSON = valueOf("application/json"); public static final String APPLICATION_JSON_VALUE = "application/json"; public static final MediaType APPLICATION_OCTET_STREAM = valueOf("application/octet-stream"); public static final String APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream"; public static final MediaType APPLICATION_XHTML_XML = valueOf("application/xhtml+xml"); public static final String APPLICATION_XHTML_XML_VALUE = "application/xhtml+xml"; public static final MediaType APPLICATION_XML = valueOf("application/xml"); public static final String APPLICATION_XML_VALUE = "application/xml"; public static final MediaType IMAGE_GIF = valueOf("image/gif"); public static final String IMAGE_GIF_VALUE = "image/gif"; public static final MediaType IMAGE_JPEG = valueOf("image/jpeg"); public static final String IMAGE_JPEG_VALUE = "image/jpeg"; public static final MediaType IMAGE_PNG = valueOf("image/png"); public static final String IMAGE_PNG_VALUE = "image/png"; public static final MediaType MULTIPART_FORM_DATA = valueOf("multipart/form-data"); public static final String MULTIPART_FORM_DATA_VALUE = "multipart/form-data"; public static final MediaType TEXT_HTML = valueOf("text/html"); public static final String TEXT_HTML_VALUE = "text/html"; public static final MediaType TEXT_PLAIN = valueOf("text/plain"); public static final String TEXT_PLAIN_VALUE = "text/plain"; public static final MediaType TEXT_XML = valueOf("text/xml"); public static final String TEXT_XML_VALUE = "text/xml"; private static final String PARAM_QUALITY_FACTOR = "q"; }
解決方法:所以我們要針對此情況進行配置,更改html對應返回的類型。(注意:1、先聲明下我使用的spring 版本:4.1.9,2、如果想要使用@ResponseBody返回json格式,就需要加載這三個包:jackson-core、jackson-databind和jackson-annotations,請自行去mvn repository中獲取) 一般我們是配置在mvc配置文件中需要配置<mvc:annotation-driven />, 所以我們只要修改下這里就行,修改配置代碼如下:
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" /> <!-- 以.html為后綴名訪問,默認返回數據類型是 text/html, 所以要修改返回的數據類型 --> <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="mediaTypes"> <map> <entry key="html" value="application/json;charset=UTF-8"/> </map> </property> </bean>
ContentNegotiationManagerFactoryBean 是內容協商管理工廠bean對象,主要用來配置多視圖請求格式。
其中有人問我說,為什么要用.html作為后綴名訪問,如果不用它的話也不會有這樣的錯誤出現,多省事。 其實我我覺的用.html作為后綴名訪問的話,使得url形成了一種偽路徑,相對來說增強了安全性。