论坛首页 Java企业应用论坛

我遇到的一个SpringMVC 内容协商视图解析器问题

浏览 5330 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-09-10  
情况是这样。 我要为一个POST请求生成一个JSON,于是就有了下面这个Controller和这个JSP
@RequiresRoles("ROLE_USER")
@RequestMapping(value = "/ajax/cost-pie", method = RequestMethod.POST)
public String costPie(
		ModelMap modelMap
	)
{	
	Map<String, Double> map = myService.getData(); // 经调试,读取数据业务逻辑完全正常
	modelMap.put("map", map);

	return "statistics/ajax/cost-pie";
}

有了数据以后我借助WEB-INF/jsp/statistics/ajax/cost-pie.jsp来帮我生成JSON
没有借助FastJSON 或 Jackson
<%@ page language="java" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page isELIgnored="false" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<%--
@see http://www.highcharts.com/demo/pie-basic
--%>
{
        "chart": {
            "plotBackgroundColor": null,
            "plotBorderWidth": null,
            "plotShadow": true
        },
        "title": {
            "text": ""
        },
        "tooltip": {
        	"enabled": true,
    	    "pointFormat": "{series.name}: <b>{point.percentage:.1f}%</b>"
        },
        "plotOptions": {
            "pie": {
                "allowPointSelect": false,
                "cursor": "pointer",
                "dataLabels": {
                    "enabled": true,
                    "color": "#000000",
                    "connectorColor": "#000000",
                    "format": "<b>{point.name}</b>: {point.percentage:.1f} %"
                }
            }
        },
        "series": [{
            "type": "pie",
            "name": "share",
            "data": [
            <%--
                ["Firefox",   45.0],
                ["IE",       26.8],
                ["Chrome", 12.8],
                ["Safari",    8.5],
                ["Opera",     6.2],
            --%>
            <c:if test="${sum != 0}">
                ["燃油",   ${map['GAS']     / sum * 100}],
                ["停车",   ${map['PARKING'] / sum * 100}],
                ["洗车",   ${map['WASHING'] / sum * 100}],
                ["路桥",   ${map['TOLL']    / sum * 100}],
                ["罚款",   ${map['FINE']    / sum * 100}]
            </c:if>
            <c:if test="${sum == 0}">
            	["没有消费记录", 100]
            </c:if>
            ]
        }]
 }


以下是我spring-mvc.xml配置
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
	<property name="favorPathExtension" value="true" />
	<property name="favorParameter" value="true" />
	<property name="parameterName" value="format" />
	<property name="ignoreAcceptHeader" value="true" /> <!-- 忽略HttpHeader:Accept -->
	<property name="mediaTypes">
		<value>
			json=application/json
			xml=application/xml
			html=text/html
		</value>
	</property>
	<property name="defaultContentType" value="text/html" />
</bean>

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
	<property name="order" value="0" />
	<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
	<property name="defaultViews">
	    <list>
	        <bean class="com.alibaba.fastjson.support.spring.FastJsonJsonView" />
	    </list>
	</property>
</bean>

<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="order" value="1" />
	<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
	<property name="contentType" value="text/html" />
	<property name="prefix" value="/WEB-INF/jsp/" />
	<property name="suffix" value=".jsp" />
</bean>


奇怪的现象是,即使我配置了ignoreAcceptHeader=true,当请求http://localhost:8080/statistics/ajax/cost-pie
(FireBug调试可知 Header.Accept=application/json)到达后最后mvc框架最终用FastJsonJsonView帮我展示的数据,
而不是我期望的JstlView!!!

我是用的软件版本如下
spring/spring-mvc 3.2.4.RELEASE
fastjson 1.1.36

有哪位大神遇到过和我一样的问题吗? 请多指教。
   发表时间:2013-09-11  

1、contentNegotiationManager主要用来根据如Accept等信息决定MediaType的;

2、ContentNegotiatingViewResolver用来根据MediaType选择最佳ViewResolver的:

2.1、首先ContentNegotiatingViewResolver在初始化时会搜索容器中的所有ViewResolver并注册;

2.2、当请求过来时,所有ViewResolver解析一个候选View,且把defaultViews也加入到候选View中,然后根据MediaType选择最佳的View;(如何选择可以去看下源代码,比如请求的是text/html,那么比如JstlView的contentType就是text/html时那么是匹配的)

 

 

此处发现你的contentNegotiationManager.ignoreAcceptHeader=true,表示不使用accept头进行选择视图;又因为favorPathExtension表示可以使用如a.json这种路径来选择,但是你请求的是http://localhost:8080/statistics/ajax/cost-pie,则没有找到media type,则用的是defaultContentType(text/html),所以按理说应该走的JstlView的。

 

如果按你说的FireBug调试可知 Header.Accept=application/json(如果ignoreAcceptHeader=false),那么走FastJsonView;不过现在你禁用了accept,按理说走默认的啊。

 

你可以debug跟踪下ContentNegotiatingViewResolver看看得到哪些ContentType、选择了哪些View。

0 请登录后投票
   发表时间:2013-09-11  
jinnianshilongnian 写道

1、contentNegotiationManager主要用来根据如Accept等信息决定MediaType的;

2、ContentNegotiatingViewResolver用来根据MediaType选择最佳ViewResolver的:

2.1、首先ContentNegotiatingViewResolver在初始化时会搜索容器中的所有ViewResolver并注册;

2.2、当请求过来时,所有ViewResolver解析一个候选View,且把defaultViews也加入到候选View中,然后根据MediaType选择最佳的View;(如何选择可以去看下源代码,比如请求的是text/html,那么比如JstlView的contentType就是text/html时那么是匹配的)

 

 

此处发现你的contentNegotiationManager.ignoreAcceptHeader=true,表示不使用accept头进行选择视图;又因为favorPathExtension表示可以使用如a.json这种路径来选择,但是你请求的是http://localhost:8080/statistics/ajax/cost-pie,则没有找到media type,则用的是defaultContentType(text/html),所以按理说应该走的JstlView的。

 

如果按你说的FireBug调试可知 Header.Accept=application/json(如果ignoreAcceptHeader=false),那么走FastJsonView;不过现在你禁用了accept,按理说走默认的啊。

 

你可以debug跟踪下ContentNegotiatingViewResolver看看得到哪些ContentType、选择了哪些View。


谢谢回复, 我刚刚调试了一下。 根本没有问题,是我张冠李戴,改错配置文件了。 此spring-mvc.xml非彼spring-mvc.xml, 多谢开涛,真不好意思,麻烦你了。
0 请登录后投票
   发表时间:2013-09-11  
jinnianshilongnian 写道

1、contentNegotiationManager主要用来根据如Accept等信息决定MediaType的;

2、ContentNegotiatingViewResolver用来根据MediaType选择最佳ViewResolver的:

2.1、首先ContentNegotiatingViewResolver在初始化时会搜索容器中的所有ViewResolver并注册;

2.2、当请求过来时,所有ViewResolver解析一个候选View,且把defaultViews也加入到候选View中,然后根据MediaType选择最佳的View;(如何选择可以去看下源代码,比如请求的是text/html,那么比如JstlView的contentType就是text/html时那么是匹配的)

 

 

此处发现你的contentNegotiationManager.ignoreAcceptHeader=true,表示不使用accept头进行选择视图;又因为favorPathExtension表示可以使用如a.json这种路径来选择,但是你请求的是http://localhost:8080/statistics/ajax/cost-pie,则没有找到media type,则用的是defaultContentType(text/html),所以按理说应该走的JstlView的。

 

如果按你说的FireBug调试可知 Header.Accept=application/json(如果ignoreAcceptHeader=false),那么走FastJsonView;不过现在你禁用了accept,按理说走默认的啊。

 

你可以debug跟踪下ContentNegotiatingViewResolver看看得到哪些ContentType、选择了哪些View。

顺便说一下,这个是你github上es项目的springmvc,配置,我直接拷过来改了一改,顺便一道谢谢你啦哈。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics