spring 4 异常HttpMediaTypeNotAcceptableException解决方案

异常问题

jsp页面ajax请求错误:406Not Acceptable

后台代码:

[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 representation

项目环境

项目环境:spingMVC 4.1.3  + spring + mybatis + jsp + jquery

传输数据格式:json

debug调试

【想直接看解决方案的,请直接到文章末尾处】

项目代码及相关配置

spring MVC部分配置:

<!-- 注解驱动 -->

<mvc:annotation-driven>

<!-- 如果自定义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();

}

跟踪BresolveMediaTypes(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中最后的注释部分即可。

 

2jsp页面请求更改为:$.post(path+"/wxmp/findWxmpType",function(data){}

去掉”.html”即可解决问题!!!

时间: 2024-10-11 22:41:45

spring 4 异常HttpMediaTypeNotAcceptableException解决方案的相关文章

Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题

最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚. 例:     类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) : if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.save(capabilityQuota); }

Spring事务异常回滚,捕获异常不抛出就不会回滚

最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚. 例:     类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) : [html] view plain copy if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.s

Spring MVC异常统一处理(异常信息的国际化,日志记录)

JAVA EE项目中,不管是对底层的数据操作,还是业务层的处理过程,还是控制层的处理,都不可避免的会遇到各种可预知的(业务异常主动抛出).不可预知的异常需要处理.一般dao层.service层的异常都会直接抛出,最后由controller统一进行处理,每个过程都单独处理异常,且要考虑到异常信息和前端的反馈,代码的耦合度高,不统一,后期维护的工作也多. 同时还必须考虑异常模块和日志模块.国际化的支持. 因此需要一种异常处理机制将异常处理解耦出来,这样保证相关处理过程的功能单一,和系统其它模块解耦,

Hadoop常见异常及其解决方案

1.Shell$ExitCodeException 现象:运行hadoop job时出现如下异常: 14/07/09 14:42:50 INFO mapreduce.Job: Task Id : attempt_1404886826875_0007_m_000000_1, Status : FAILED Exception from container-launch: org.apache.hadoop.util.Shell$ExitCodeException: org.apache.hadoo

spring mvc 异常统一处理方式

springMVC提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver,另一种是使用注解的方式实现一个专门用于处理异常的Controller--ExceptionHandler. 1.实现自己的HandlerExceptionResolver,HandlerExceptionResolver是一个接 口,springMVC本身已经对其有了一个自身的实现--DefaultExceptionResolver,该解析器只是对其中的一些比较典型的异常 进行了

Spring 配置异常解决办法之Referenced file contains errors

Spring 配置异常解决办法之Referenced file contains errors (http://www.sp Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans-3.0.xsd). For more information, right click on the message in the Problems View and select "Show

Spring启动异常: cvc-elt.1: Cannot find the declaration of element &#39;beans&#39;(转)

Spring启动异常: cvc-elt.1: Cannot find the declaration of element 'beans' 2008-09-07 22:41 今天把在线聊天室代码改了下, 想启动应用测试. 结果抛出一大堆异常: -------------------------------------------------------------------------------------------- org.springframework.beans.factory.x

前端异常监控解决方案研究

摘要: 异常监控不复杂也不简单啊... 原文:前端异常监控解决方案研究 作者:frustigor 前端监控包括行为监控.异常监控.性能监控等,本文主要讨论异常监控.对于前端而言,和后端处于同一个监控系统中,前端有自己的监控方案,后端也有自己等监控方案,但两者并不分离,因为一个用户在操作应用过程中如果出现异常,有可能是前端引起,也有可能是后端引起,需要有一个机制,将前后端串联起来,使监控本身统一于监控系统.因此,即使只讨论前端异常监控,其实也不能严格区分前后端界限,而要根据实际系统的设计,在最终的

zip方式安装的Mysql5.7,插入中文时出现Incorrect string value: &#39;\xF0\x9F...&#39; for column &#39;XXX&#39; at row 1异常的解决方案

Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1 这个问题,原因是UTF-8编码有可能是两个.三个.四个字节.Emoji表情或者某些特殊字符是4个字节,而Mysql的utf8编码最多3个字节,所以数据插不进去. 我的解决方案是这样的 1.在mysql的安装目录下找到my.ini,作如下修改: [mysqld] character-set-server=utf8mb4 [mysql] default-character-