jsp頁面ajax請求錯誤:406Not Acceptablehtml
後臺代碼:前端
[2017:05:1709:51:22]:Resolving exception from handler [publicjava.util.Map<java.lang.String, java.lang.Object> com.demo.controller.DemoController.findWxmpType()]:org.springframework.web.HttpMediaTypeNotAcceptableException: Could not findacceptable representationjava
項目環境:spingMVC 4.1.3 + spring + mybatis + jsp + jqueryjquery
傳輸數據格式:jsonweb
debug調試ajax
【想直接看解決方案的,請直接到文章末尾處】spring
spring MVC部分配置:json
<!-- 註解驅動 -->微信
<mvc:annotation-driven>mybatis
<!-- 若是自定義message-converters,默認的message-converters將失效 -->
<mvc:message-converters>
<!-- 定義文本轉化器 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg index="0"value="UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 定義Controller的掃描包 -->
<context:component-scan base-package="com.demo.controller"/>
<!-- 定義視圖解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"value="/WEB-INF/pages/" />
<property name="suffix"value=".jsp" />
</bean>
<!-- 處理靜態資源被「/」所攔截的問題 -->
<mvc:default-servlet-handler />
web.xml部分配置:
<!-- 加載spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext*.xml</param-value>
</context-param>
<!--Spring的ApplicationContext 載入:Spring的監聽器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 加載SpringMVC的配置文件 -->
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/demo-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置訪問映射的視圖路徑和後綴 -->
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!—全部請求 -->
<!--<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>-->
jsp頁面:
$.post(path+"/wxmp/findWxmpType.html",function(data){
alert(data);
console.info("msg:"+data.msg);
if(data.msg=="success"){
alert(data.msg);
}})
Controller代碼:
@RequestMapping(value = "/findWxmpType", method =RequestMethod.POST)
@ResponseBody
publicMap<String, Object> findWxmpType() {
Long startTime = System.currentTimeMillis();
Map<String,Object> maps= newHashMap<String, Object>();
try {
// 微信公衆號搜索列表
maps.put("msg", "success");
LOGGER.debug("響應結果:maps【{}】", maps);
} catch (Exception e) {
LoggerUtil.errorLog("執行失敗", startTime, System.currentTimeMillis(),
LOGGER, e);
maps.put("msg", "加載數據異常,請稍後再試");
}
returnmaps;
}
經過debug跟蹤,controller返回map集合數據是沒有問題的。
問題點出在:springMVC在對返回數據進行轉換處理的過程當中!
網上百度了一下方法:
1,在controller返回的對象中必須包含getter/setter方法;(這個並非問題緣由)
2, 在controller的@RequestMapping(value= "/findWxmpType", method = RequestMethod.POST,produces="application/json")
加上紅色字體部分。並無解決問題,produces這個屬性,你們能夠百度下其具體做用是什麼。簡單來講:就是用於匹配頁面的請求頭Accept信息是否和響應頭Accept信息(produces設置)一致。
3,配置jackson轉換器,指定返回數據類型爲text/html;
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<!--解決 HttpMediaTypeNotAcceptableException: Could not findacceptable
representation -->
<propertyname="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<!--<value>application/json;charset=UTF-8</value> -->
</list>
</property>
</bean>
這個解決方案,配置後運行效果以下:
數據是能夠進行傳輸了,但已經不是json格式,jsp沒法直接取到msg數據。
so,並無解決問題!!!刪除配置!
springMVC在處理返回數據的時候是經過轉換器HttpMessageConverter進行處理的。
org.springframework.web.HttpMediaTypeNotAcceptableException:Could not find acceptable representation
這個錯誤是:不能找到能接受的HttpMediaType協議。也就是說jsp頁面的請求頭Accept信息和controller返回的響應頭accept頭信息不一致。
前端jsp的Accept頭信息:匹配全部。
指定MediaTypes爲json:
進入HttpMessageConverter轉換器源碼中:
插入一個小話題,eclipse跟蹤異常源碼方法:
點擊藍色部分:彈框:
點擊OK。
從新訪問頁面,進入debug斷點:
跟蹤A:
@Override
public List<MediaType>resolveMediaTypes(NativeWebRequest webRequest) throwsHttpMediaTypeNotAcceptableException {
for (ContentNegotiationStrategystrategy : this.contentNegotiationStrategies) {
List<MediaType>mediaTypes = strategy.resolveMediaTypes(webRequest);
if (mediaTypes.isEmpty() ||mediaTypes.equals(MEDIA_TYPE_ALL)) {
continue;
}
return mediaTypes;
}
return Collections.emptyList();
}
跟蹤B:resolveMediaTypes(webRequest);
@Override
public List<MediaType>resolveMediaTypes(NativeWebRequest webRequest) throwsHttpMediaTypeNotAcceptableException {
String key =getMediaTypeKey(webRequest);
if (StringUtils.hasText(key)) {
MediaType mediaType =lookupMediaType(key);
if (mediaType != null) {
handleMatch(key,mediaType);
returnCollections.singletonList(mediaType);
}
mediaType =handleNoMatch(webRequest, key);
if (mediaType != null) {
addMapping(key,mediaType);
returnCollections.singletonList(mediaType);
}
}
return Collections.emptyList();
}
跟蹤C:getMediaTypeKey(webRequest);從當前請求request當中獲取到MediaType
@Override
protected String getMediaTypeKey(NativeWebRequestwebRequest) {
//獲取request對象
HttpServletRequest servletRequest= webRequest.getNativeRequest(HttpServletRequest.class);
if (servletRequest == null) {
logger.warn("AnHttpServletRequest is required to determine the media type key");
return null;
}
//獲取當前請求路徑:/wxmp/searchWxmps.html
String path =urlPathHelper.getLookupPathForRequest(servletRequest);
//獲取searchWxmps.html
String filename =WebUtils.extractFullFilenameFromUrlPath(path);
//獲取請求後綴:html
String extension =StringUtils.getFilenameExtension(filename);
return(StringUtils.hasText(extension)) ? extension.toLowerCase(Locale.ENGLISH) :null;
}
回到:跟蹤B:
下一步:
而後返回MediaType。
回到:跟蹤A:
下一步:直到ProducesRequestConverter:
下一步:
@Override
protected booleanmatchMediaType(HttpServletRequest request) throwsHttpMediaTypeNotAcceptableException {
//acceptedMediaTypes=text/html 在通過springMVC解析以後的,頁面想要的數據頭信息
List<MediaType> acceptedMediaTypes =getAcceptedMediaTypes(request);
for (MediaTypeacceptedMediaType : acceptedMediaTypes) {
// getMediaType()=application/json咱們配置的<value>application/json;charset=UTF8</value>
if(getMediaType().isCompatibleWith(acceptedMediaType)) {
return true;
}
}
return false;
}
結果就是:
在從jsp頁面發送ajax請求的時候,代碼是:
$.post(path+"/wxmp/findWxmpType.html",function(data){}
請求路徑爲:http://m.demo.com/wxmp/findWxmpType.html這個後綴「.html」就是問題的根源。
該方法實際上只是爲了請求數據,徹底能夠不帶「.html」,可是在web.xml裏面,進行的僞靜態訪問配置<servlet-mapping>
由於該配置,全部的訪問,必須加上後綴「.html」才能進入後臺。
帶上這個配置以後,springMVC在解析前臺請求頭信息Accept的時候,本來是:*/* ,卻解析成了:text/html
這樣的話,咱們在controller中加上@ResponseBody對返回數據進行json轉換,設置響應頭Accept=application/json以後,匹配matchProduces異常。
1,在web.xml中添加這段配置:
<!—全部請求可進入 -->
<servlet-mapping>
<servlet-name>wupao-mwss</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
也就是放開 前文web.xml中最後的註釋部分便可。
2,jsp頁面請求更改成:$.post(path+"/wxmp/findWxmpType",function(data){}
去掉」.html」便可解決問題!!!