restful服务中一个重要的特性就是一种资源可以有多种表现形式,在springmvc中可以使用ContentNegotiatingViewResolver这个视图解析器来实现这种方式。

描述资源的三种形式

    一、使用扩展名

http://localhost:8080/test/user.xml   以xml格式呈现

http://localhost:8080/test/user.json  以json格式呈现

http://localhost:8080/test/user     以默认视图呈现,如jsp

    二、使用http request header的Accept

GET /user HTTP/1.1

Accept:application/xml   请求时设置返回形式是xml,如使用ajax请求,则需要设置contentType:application/xml

GET /user HTTP/1.1

Accept:application/json  请求时设置返回形式是json,如使用ajax请求,则需要设置contentType:application/json

    三、使用参数

http://localhost:8080/test/user?format=json

http://localhost:8080/test/user?format=xml

上面了解了同一种资源的三种呈现方式,即json、xml、jsp,那么我们要如何使用ContentNegotiatingViewResolver类配置,使客户端请求的方式不同,返回同一种资源的三种方式呢?

ContentNegotiatingViewResolver配置

ContentNegotiatingViewResolver是视图解析器,我们在使用jsp这个视图的时候也配置了一个视图解析器InternalResourceViewResolver,他们都是视图解析器,后者着重在配置一个默认的视图解析即jsp;ContentNegotiatingViewResolver本身不会解析,他会分配其他的viewResolver去解析,并选择一个看起来像是客户端请求需要返回的一种 View 返回。

下面是ContentNegotiatingViewResolver的具体配置

<!--springmvc中根据后缀不同返回不同格式的配置
如,XXX.json 返回json格式
XXX.xml 返回xml格式
xxx 返回jsp
-->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!--这里是解析器的执行顺序,如果有多个的话,配置的数值越小,则越早执行-->
<property name="order" value="1" />
<!--
这里是是否启用扩展名支持,默认就是true
例如 /user/{userid}.json
-->
<property name="favorPathExtension" value="true"></property> <!--这里是是否启用参数支持,默认就是true
例如 /user/{userid}?format=json
-->
<property name="favorParameter" value="false"></property>
<!--这里是否忽略掉accept header,默认就是false
例如 GET /user HTTP/1.1
Accept:application/json
--> <property name="ignoreAcceptHeader" value="true"></property>
<!-- 这里是扩展名到mimeType的映射,
例如 /user/{userid}.json 中的 .json 就会映射到 application/json
-->
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" /> <entry key="xml" value="application/xml" />
</map>
</property>
<!--视图-->
<property name="defaultViews">
<list>
<!--json视图-->
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></bean>
<!--xml视图-->
<bean class="org.springframework.web.servlet.view.xml.MarshallingView"
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.cn.my.entity.Course</value>
<value>com.cn.my.entity.CourseList</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
</list>
</property>
</bean>

order:如果存在多个viewResolver则order值小的被使用,如果没有合适的viewResolver则会使用另外的;

favorPathExtension:是否支持扩展名,默认为true(支持),扩展名指的xxx.json、xxx.xml等形式

favorParameter:是否启用参数支持,默认为true(支持),即xxx?format=json、xxx?format=xml等形式,这里的参数名默认为format,可以通过配置改变。

ignoreAcceptHeader:是否忽略accept header,默认是false(不忽略),即请求时指定的contentType:application/json等,由于我这里要使用扩展名的形式返回,所以把另外两项都关闭了,可视不同情况,使用不同设置;

mediaTypes:配置扩展名到mimeType的映射,这里配置了json和xml的映射;

defaultViews:配置视图,这里配置了json和xml的视图,json使用的jackson;

最后,我还配置一个另外一个视图解析器,InternalResourceViewResolver,

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>

这是jsp的视图解析器,order属性配置为了2,在无法匹配到json、xml的情况下,会返回jsp的视图。

下面是controller的方法

package com.cn.my.controllor;

import java.util.ArrayList;
import java.util.List; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import com.cn.my.entity.Course;
import com.cn.my.entity.CourseList; @Controller
@RequestMapping("/mul")
public class MultiView { @RequestMapping("/simple/{coursId}")
public String method1(@PathVariable("coursId") String coursId,ModelMap model){
Course c=new Course();
c.setId(coursId);
c.setContent("这是测试内容");
c.setName("李四");
model.put("course", c);
return "course";
}
}

这里使用的restful服务中的uri的格式,用到了@PathVariable注解,这里方法返回的String,且没有@ResponseBody注解,在前边的返回json一文中有返回json的配置,需要@ResponseBody注解,详细的可以参看前边,同时在方法参数中有ModelMap,为什么这里要返回一个字符串呢,目的是为了统一,我们知道如果要返回到jsp视图,那么这里要返回的一个代表逻辑视图名的字符串,为了使三种方式统一,这里返回的是字符串,如果不返回到jsp也可以返回一个实际的对象。

下面看测试结果,

请求:http://localhost:8081/springmvc/mul/simple2/1212.json

请求:http://localhost:8081/springmvc/mul/simple2/1212.xml

请求:http://localhost:8081/springmvc/mul/simple2/1212

最后一个jsp的视图,本来是要在jsp页面中输出内容的,我这里没做,只是输出了一段话。请谅解!

从上边的测试结果来看,我们分别使用了三种不同的请求方式去请求同一个资源,返回了各自的形式,这种方式很适合用在不同的系统调用同一个系统时,可能别的系统处理数据的方式不一样,我们使用上边的配置可以实现一套代码,返回不同的形式。

最后

在配置默认的jsp解析器的时候也可以照下面的配置方式,

<!--springmvc中根据后缀不同返回不同格式的配置
如,XXX.json 返回json格式
XXX.xml 返回xml格式
xxx 返回jsp
-->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!--这里是解析器的执行顺序,如果有多个的话,配置的数值越小,则越早执行-->
<property name="order" value="1" />
<!--
这里是是否启用扩展名支持,默认就是true
例如 /user/{userid}.json
-->
<property name="favorPathExtension" value="true"></property> <!--这里是是否启用参数支持,默认就是true
例如 /user/{userid}?format=json
-->
<property name="favorParameter" value="false"></property>
<!--这里是否忽略掉accept header,默认就是false
例如 GET /user HTTP/1.1
Accept:application/json
--> <property name="ignoreAcceptHeader" value="true"></property>
<!-- 这里是扩展名到mimeType的映射,
例如 /user/{userid}.json 中的 .json 就会映射到 application/json
-->
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" /> <entry key="xml" value="application/xml" />
</map>
</property> <!--视图解析器-->
<property name="viewResolvers">
<list> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
</list> </property>
<!--视图-->
<property name="defaultViews">
<list>
<!--json视图-->
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></bean>
<!--xml视图-->
<bean class="org.springframework.web.servlet.view.xml.MarshallingView"
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.cn.my.entity.Course</value>
<value>com.cn.my.entity.CourseList</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
</list>
</property>
</bean>

声明:我这里的环境是spring4.1

参考:

http://blog.csdn.net/z69183787/article/details/41654603

上边有很好的解释。

有不正之处欢迎指正,谢谢!

springmvc<一>一种资源返回多种形式【ContentNegotiatingViewResolver】的更多相关文章

  1. SpringMVC,3种不同的URL路由配置方法

    1. 先说说一种比较常见的: <servlet> <servlet-name>theDispatcher</servlet-name> <servlet-cl ...

  2. SpringMVC,3种不同的URL路由配置方法(这根本不是一个小问题)

    转载自:http://blog.csdn.net/fansunion/article/details/41149287?utm_source=tuicool&utm_medium=referr ...

  3. spring-mvc不拦截静态资源的配置

    spring-mvc不拦截静态资源的配置 标签: spring 2015-03-27 23:54 11587人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. &qu ...

  4. springmvc、springboot静态资源访问配置

    如何访问项目中的静态资源? 一.springmvc springmvc中访问静态资源,如果DispatcherServlet拦截的为"",那么静态资源的访问也会交给Dispatch ...

  5. SpringMVC-方法四种类型返回值总结,你用过几种?

    SpringMVC 现在算是 Java 领域的一个基础性框架了,很多人天天用,可是对于 SpringMVC 方法的返回值,你又是否完全清楚呢?今天松哥就来和大家聊一聊 SpringMVC 中四种不同类 ...

  6. SpringMVC,3种不同的URL路由配置方法 [转]

    SpringMVC中配置URL拦截,非常简单.网上找个示例,就能通过.但是,在我做了好几个Web项目,又参与了别人主导的Web项目时,发现URL配置也非常有学问. 1. 先说说一种比较常见的: < ...

  7. Java学习-013-文本文件读取实例源代码(两种数据返回格式)

    此文源码主要为应用 Java 读取文本文件内容实例的源代码.若有不足之处,敬请大神指正,不胜感激! 1.读取的文本文件内容以一维数组[LinkedList<String>]的形式返回,源代 ...

  8. SpringMVC+FreeMarker实现静态资源文件自动添加版本号(md5)

    近日切换java开发,开始学习springframework.在实现静态资源文件自动计算版本号的实例时,因为不熟悉框架,走了不少弯路,好在最终解决了问题.这里写篇文章记录一下实现,也希望对大家有些用处 ...

  9. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

随机推荐

  1. BPM配置故事之案例11-操作外部数据源

    小明:可以获取ERP数据了-- 老李:哦,这么快?小伙子,我非常看好你,来来,别急着走,再陪我聊会-- 小明:--您老人家不是又要改流程吧? 老李:没有没有,哎嘿嘿嘿,我们这不都是为公司效率着想嘛,这 ...

  2. GitHub管理代码-随笔

    公司一直用的SVN进行项目管理,平时便自己折腾了下Git,这里做下GitHub的最简单的记录... 在git上创建仓库等就免谈了,网上也有好多教程,直接从创建之后记录: 在github的readme文 ...

  3. date命令

    GNU的date提供+%s(小写s), 能打印出自1970-01-01 00:00:00到当前时间的秒数. 这可能大家都不陌生,但有两点需要注意: 1. %s存在于GNU扩展版本.像在solaris等 ...

  4. 【python之路5】学习小结

    一.编程语言 java C语言 C++ C# Python 二.python语言的种类 Cpython:python的官方版本,使用最为广泛,实现将python(py文件)转换为字节码文件(pyc文件 ...

  5. MEF学习

    一.   什么是MEF MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库. 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置. 扩 ...

  6. C#中实现并发的几种方法的性能测试

    C#中实现并发的几种方法的性能测试 0x00 起因 去年写的一个程序因为需要在局域网发送消息支持一些命令和简单数据的传输,所以写了一个C/S的通信模块.当时的做法很简单,服务端等待链接,有用户接入后开 ...

  7. C#与C++的发展历程第四 - C#6的新时代

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  8. 关于bug分析与异常处理的一些思考

    前言:工作三年了,工作内容主要是嵌入式软件开发和维护,用的语言是C,毕业后先在一家工业自动化控制公司工作两年半,目前在一家医疗仪器公司担任嵌入式软件开发工作.软件开发中,难免不产生bug:产品交付客户 ...

  9. ASP.NET MVC Model绑定(四)

    ASP.NET MVC Model绑定(四) 前言 前面的篇幅对于Model绑定器IModelBinder以及实现类型.Model绑定器提供程序都作了粗略的讲解,可以把Model绑定器想象成一个大的容 ...

  10. C#委托使用详解(Delegates)

    摘要 委托是C#编程一个非常重要的概念,也是一个难点.本文将系统详细讲解委托. 1. 委托是什么? 其实,我一直思考如何讲解委托,才能把委托说得更透彻.说实话,每个人都委托都有不同的见解,因为看问题的 ...