SpringMVC使用了@ResponseBody报406错误的问题(1)

    昨天在编写一个程序的时候,使用@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种配置的解决方法,在我这里无法解决问题,暂时不知道是什么原因。



  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值