- 浏览: 941461 次
- 性别:
- 来自: 江西上饶
文章分类
- 全部博客 (460)
- p.spring (56)
- p.maven (20)
- p.ant (17)
- p.jee (18)
- p.jse (33)
- p.ofbiz (31)
- p.软件工程 (8)
- p.struts2 (5)
- p.hibernate (5)
- linux (25)
- 设计模式 (2)
- p.javascript (11)
- 硬件 (1)
- p.jsp (2)
- p.windows批处理 (1)
- 操作系统问题 (5)
- 算法 (1)
- p.mysql (7)
- p.sql (5)
- p.c (1)
- google产品 (0)
- 内存 (1)
- p.struts (1)
- p.freemarker (7)
- p.css (4)
- p.log4j (10)
- p.html (3)
- 淘宝产品 (0)
- 其他 (3)
- 编译器 (0)
- svn (4)
- p.spring.security (11)
- 图形 (0)
- p.xml (1)
- p.ssh (0)
- p.jquery (4)
- p.jdbc (3)
- p.flex (0)
- p.c++ (0)
- p.c#Net (0)
- p.assembly (0)
- p.sqlserver (0)
- p.其他 (3)
- p.webwork (21)
- p.wap (12)
- p.cglib (1)
- p.jee服务器 (11)
- windows (2)
- p.iphone (1)
- p.java.分布式与集群 (2)
- p.ibatis (16)
- p.eclipse (5)
- 架构 (2)
- http协议 (5)
- 我的个人标准 (2)
- 多线程 (1)
- 奇怪问题 (5)
- p.jira (13)
- p.httpclient (1)
- 服务器.apache (11)
- 安全防范 (1)
- p.PODAM (1)
- p.junit (16)
- fop (2)
- 硬盘安装 (1)
- powerdesigner (0)
- 单元测试 (1)
- apache commons (4)
- tomcat+apache集群 (10)
- 各类诡辩 (1)
- 安卓 (8)
- qvod (1)
- java编程基础知识考试考点及答案 (0)
- 工作总结 (4)
- oracle (0)
- spring的util工具 (3)
- json (2)
- maven (3)
- jms (19)
- p.bat (3)
- hadoop (2)
- git (3)
- nginx (1)
- p.移动开发 (1)
- shiro (3)
- 游戏破解 (1)
- react-native (7)
- ios开发 (1)
- webmagic (6)
- socks5 (1)
最新评论
-
weituotian:
说的不好,没人看的
公司系统中的菜单功能和权限功能 -
石不易:
非常详细的注解~
绑定端口和IP,Listen 与VirtualHost指令 -
spring_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
spring mvc -
liyixing1:
PandaDONG 写道谢谢你啊,我已经下下来了,只是还有很多 ...
jira war安装 -
liyixing1:
PandaDONG 写道谢谢你啊,我已经下下来了,只是还有很多 ...
jira war安装
ContentNegotiatingViewResolver spring REST中的内容协商(同一资源,多种展现:xml,json,html)
- 博客分类:
- p.spring
本文参照badqiu的文章 http://badqiu.iteye.com/blog/552806
REST的详细可以查看我的一片REST的文章
RESTful服务中很重要的一个特性即是同一资源,多种表述.如 get put post delete head方式提交的请求,或者根据accept,参数,后缀等方式。
get
put
post
delete
head
方式不介绍。
Accept方式
chrome:
Accept:application/xml,application/xhtml+xml,textml;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
firefox:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
IE8:
Accept:image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
根据请求的accpet,来返回信息。
由于浏览器的差异,发送上来的Accept Header头将是不一样的. 将导致服务器不知要返回什么格式的数据给你.
其中本人的一篇关于StringHttpMessageConverter一文说到的@ResponseBody String返回类型,google chrome下会有问题就是这个原因。
firefox IE6-7由于第一个accept是text/html,StringHttpMessageConverter处理的还是text/html。
使用扩展名
/user/123.xml 将返回xml格式数据
/user/123.json 将返回json格式数据
/user/123.html 将返回html格式数据
丧失了同一url多种展现的方式。在rest架构中,user/123应该具有不同的展示。而/user/123.xml和/user/123.json则已经是不同的url了。
使用参数
现在很多open API是使用这种方式,但可能由于要编写的字符较多(占用更多带宽),所以较少使用.
ContentNegotiatingViewResolver
注意这个ContentNegotiatingViewResolver视图解析器只有在handler方法,
return(controller的返回值,经过处理后,最后会成为ModelAndView)值,
如果return值只是一个普通的bean,那么处理后的ModelAndView的内容如下图
不为null才会处理。而对于在方法前面写了ResponseBody注解的方法,
AnnotationMethodHandlerAdapter类会判断
else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) { handleResponseBody(returnValue, webRequest); return null; }
,如上,当有ResponseBody注解,会调用handleResponseBody,并把return null设置为空。
这个类它实现了ViewResolver。但它并不直接解析视图,而是委托给别人。默认情况,它是从spring 上下文,查找视图解析器,并调用这些解析器。也可以在初始化这个bean的时候,设置它的解析器属性(viewResolvers),这是个list类型的属性。
请注意,要让这个视图解析器正常工作,需要设置比别人更高的优先级(默认为Ordered.HIGHEST_PRECEDENCE)。
配置的例子
<!-- 根据客户端的不同的请求决定不同的view进行响应, 如 /rest/1.json /rest/1.xml /rest?format=json /rest?format=xml --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!-- 设置为true以忽略对Accept Header的支持--> <property name="ignoreAcceptHeader" value="true" /> <!-- true,开启扩展名支持,false关闭支持 --> <property name="favorPathExtension" value="false" /> <!-- 用于开启 /userinfo/123?format=json的支持 --> <property name="favorParameter" value="true" /> <!-- 在没有扩展名和参数时即: "/user/1" 时的默认展现形式 --> <property name="defaultContentType" value="text/html" /> <!-- 参数值至mimeType的映射,即 /rest?format=json json是key,application/json就是value 暂时只支持json和xml --> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <property name="viewResolvers"> <!-- 关闭所有的解析器,防止它在查找候选视图时多个解析器都运行 --> <list></list> </property> <property name="defaultViews"> <list> <!-- for application/json --> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> <!-- <property name="renderedAttributes">--> <!-- <set>--> <!-- <value>result</value>--> <!-- <value>user</value>--> <!-- <value>page</value>--> <!-- </set>--> <!-- </property>--> <!-- 重新设置 objectMapper--> <property name="objectMapper"> <bean class="org.codehaus.jackson.map.ObjectMapper"> <!-- 设置objectMapper的serializationConfig的serializationInclusion属性,以忽略null对象 --> <property name="serializationConfig.serializationInclusion"> <value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</value> </property> </bean> </property> </bean> <!-- for application/xml --> <bean class="org.springframework.web.servlet.view.xml.MarshallingView"> <property name="marshaller"> <bean class="org.springframework.oxm.castor.CastorMarshaller"> <property name="validating" value="false"></property> </bean> </property> </bean> </list> </property> </bean>
这个视图解析器根据请求类型来返回视图。就是上面说的三种方式。
1.如果设置了setFavorPathExtension(boolean)为true,会根据后缀来使用不同的数据格式。
2.如果设置了setFavorParameter(boolean)为true,会根据请求参数来设置不同的数据格式。参数名是通过属性parameterName设置的,默认private String parameterName = "format";
3.如果ignoreAcceptHeader未设置为false(未关闭),那么会通过accpet 来获得相应的信息。
在其内部中,是通过
protected List<MediaType> getMediaTypes(HttpServletRequest request) {
方法来根据请求过来的信息,返回对应的需要的回应的context-type的。首先判断的是扩展名是否开启,
if (this.favorPathExtension) {
如果开启,先获取扩展名,如果扩展名不为null,
查看是否有可以处理的扩展,这个是将扩展名作为key,来获取的
MediaType mediaType = this.mediaTypes.get(extension);
这里的mediaTypes就是刚才的配置
<property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property>
设置的值。
如果我们访问的是/127.0.0.1/daowole/rest.xml
扩展名就是xml,这个key对应的value就是application/xml。
有则返回媒体类型。扩展名得方式还会判断useJaf是否开启。开启的话会使用
jaf(Java Activation Framework)
来获取,也就是通过
String mediaType = fileTypeMap.getContentType(fileName);
来获取媒体类型。这里的fileTypeMap是一个静态常量。它里面建立了一张还算完整的根据文件名字的后缀,映射的媒体表格。
如(其中的一部分)
c++=MIMETypeEntry: text/plain,
bcpio=MIMETypeEntry: application/x-bcpio,
xwd=MIMETypeEntry: image/x-xwindowdump,
如果是从jaf取出来的,会自动往mediaTypes添加内容。
if (mediaType != null) {
this.mediaTypes.putIfAbsent(extension, mediaType);
}
否则进入下一个处理方式,
下一个处理方式是参数,判断favorParameter是否开启。处理类似
通过参数。只是将参数值,作为key从mediaTypes获取。
然后然后是accept方式,判断ignoreAcceptHeader是否开启。处理类似,但不需要从mediaTypes获取信息。
如果没有,查看defaultContentType是否为空,返回的是defaultContentType
否则返回return Collections.emptyList();一个空的内容。
其次根据返回的
List<MediaType> requestedMediaTypes,controller返回的viewname,以及locale,来生成多个候选的View(List<View>)
List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
/**发现候选的方式是遍历它的viewResolvers属性(这个类在构造的时候,会从spring上下文把所有的解析器取出来,当然我们也可以通过bean初始化的property元素设置它的viewResolvers属性),将每个viewResolver拿出来,调用它的resolveViewName,来获取view,如果view有值,表示这个视图解析器可以处理(可以处理不表示只有这一个是候选的,候选可能是多个的)。这个时候还没结束*/
for (ViewResolver viewResolver : this.viewResolvers) { View view = viewResolver.resolveViewName(viewName, locale); if (view != null) { //不为null,添加到候选视图 candidateViews.add(view); } //这里还需要遍历需要返回给客户端的媒体类型 for (MediaType requestedMediaType : requestedMediaTypes) { //根据媒体类型,返回扩展名,List<String> extensions = getExtensionsForMediaType(requestedMediaType);这部做的是和通过key获取value方式反了一下,而是通过value获取key了,也就是通过媒体,获取这个媒体在mediaType中的key,这里返回的key可能是多个,也就是说一种媒体可以对应各种文件格式,如json可以对应application/json text/json。 List<String> extensions = getExtensionsForMediaType(requestedMediaType); //遍历这个媒体,通过String viewNameWithExtension = viewName + "." + extension;操作后,生成新的逻辑视图,并查看这个逻辑是否也可以在当前的视图解析器处理出一个物理视图。如我们的action是/daowole/test.json 本来我们controller返回的逻辑视图是 order/addsuccess,它对应的物理视图是 order/addsuccess.ftl,而这个时候会增加逻辑视图, order/addsuccess.json 那么对应的物理视图就是 order/addsuccess.json.ftl for (String extension : extensions) { String viewNameWithExtension = viewName + "." + extension; view = viewResolver.resolveViewName(viewNameWithExtension, locale); //可以处理,将它也加入到候选视图。 if (view != null) { candidateViews.add(view); } } } } if (!CollectionUtils.isEmpty(this.defaultViews)) { //这里会把我们在上面设置的默认视图(视图不是视图解析器)也加入进去。我们这里设置的默认视图只有一个json candidateViews.addAll(this.defaultViews); } 当然这里的视图比较特殊,它不需要逻辑视图名,就可以直接返回responsebody了。 随后需要从候选视图查找一个唯一可以处理的视图,也就是 View bestView = getBestView(candidateViews, requestedMediaTypes); 代码如下 MediaType bestRequestedMediaType = null; View bestView = null; //首先是遍历需要回应给客户端的媒体信息 for (MediaType requestedMediaType : requestedMediaTypes) { //这里是遍历每个候选视图 for (View candidateView : candidateViews) { if (StringUtils.hasText(candidateView.getContentType())) { //获取当前候选时候的媒体信息 MediaType candidateContentType = MediaType.parseMediaType(candidateView.getContentType()); //判断这个候选视图媒体是否在位于需要回应的媒体中,至于怎么判断是否位于这个媒体中我们不做详细介绍,但候选视图的媒体刚好包含于回应视图中的,那么 if (requestedMediaType.includes(candidateContentType)) { bestRequestedMediaType = requestedMediaType; //baseView就确定了。 bestView = candidateView; break; } } } if (bestView != null) { if (logger.isDebugEnabled()) { logger.debug( "Returning [" + bestView + "] based on requested media type '" + bestRequestedMediaType + "'"); } break; } } return bestView; 这里返回后,也就是 View bestView = getBestView(candidateViews, requestedMediaTypes);执行后 if (bestView != null) { return bestView; } else { //这里生成是一个404 if (this.useNotAcceptableStatusCode) { if (logger.isDebugEnabled()) { logger.debug("No acceptable view found; returning 406 (Not Acceptable) status code"); } return NOT_ACCEPTABLE_VIEW; } else { if (logger.isDebugEnabled()) { logger.debug("No acceptable view found; returning null"); } //任何都不返回,这个useNotAcceptableStatusCode设置的时候要注意了,如果为true,而且没有找到任何可以处理的view,那么就会404,否则,它就return null。当spring mvc 的servlet接受到的view为null,那么就会交给下一个视图解析器处理,那么原来的解析器就依然可以起到效果了。这种情况是我们大多数应用所希望的。所以spring mvc在设计这个类得时候把它的默认值设置为false。 return null; } }
评论
9 楼
style2013
2014-12-09
liyixing1 写道
style2013 写道
顶顶 求楼主联系方式。。
联系方式?这是要约吗,你性别属性是啥呢
北京约啦。。
8 楼
liyixing1
2014-12-09
style2013 写道
顶顶 求楼主联系方式。。
联系方式?这是要约吗,你性别属性是啥呢
7 楼
style2013
2014-12-09
顶顶 求楼主联系方式。。
6 楼
liyixing1
2014-11-14
cpu0oop 写道
确实是好文章
多谢
5 楼
cpu0oop
2014-11-14
确实是好文章
4 楼
liyixing1
2012-05-16
wenxiang_tune 写道
必须要顶,这文章写得好,希望以后能多沟通
呵呵,谢谢夸奖
3 楼
wenxiang_tune
2012-05-15
必须要顶,这文章写得好,希望以后能多沟通
2 楼
liyixing1
2012-04-26
liheping17 写道
这么好的文章 怎么没人顶
呵呵,多谢多谢
1 楼
liheping17
2012-04-25
这么好的文章 怎么没人顶
发表评论
-
Spring 定时任务,cron表达式,@Scheduled cron表达式
2016-04-25 15:48 5267一个cron表达式有至少6 ... -
spring mvc list
2015-12-14 10:28 1253我使用这样无法传入 @requestMapping(" ... -
Unable to locate Spring NamespaceHandler for XML schema namespace
2015-09-23 14:00 2299org.springframework.beans.facto ... -
关于使用s.url jstl的上下文
2015-08-16 13:28 887比如 [@s.url '/'/]index.html?cote ... -
Spring 属性占位符配置器 PropertyPlaceholderConfigurer
2015-08-02 12:43 2050<!-- 属性配置文件读 ... -
FactoryBean接口
2014-09-30 14:05 876实现了FactoryBean接口的bean不是简单的一个bea ... -
国际化之MessageSourceAware和MessageSourceAccessor
2014-01-06 23:13 2821先看接口MessageSourceAware 该接口的注释中 ... -
spring 惯例优先原则
2013-07-22 09:46 1172惯例优先原则(convention over configur ... -
ant path匹配
2013-07-22 09:40 2136spring和ant path实现相关的主要类有两个 org. ... -
springmvc action方法中参数具有@ModelAttribute与不具有的区别
2012-12-14 09:36 4087在springmvc的参数解析中,发现具有@ModelAttr ... -
util包
2012-12-05 13:50 1074spring的util基本上都在springframework ... -
url,请求相关帮助类UrlPathHelper
2012-11-29 11:18 2492org.springframework.web.util.Ur ... -
整站国际化方案
2012-11-28 17:46 1078当前常见的实现方式,主要由两种方案实现 1.通过locale ... -
spring的三种注入方式
2012-11-20 17:30 18331.通过bean的property子元 ... -
spring AnnotationUtils 注解工具
2011-12-08 11:27 1275spring AnnotationUtils 注解工具 -
GenericCollectionTypeResolver,用于获取list或者map等元素的类型
2011-12-07 16:17 1278GenericCollectionTypeResolver,用 ... -
属性编辑器
2011-12-05 18:19 1057我自定义了一个类型,然后设置了一个属性编辑器,注册的class ... -
iframe下面的session问题
2011-12-04 19:52 5271在写iframe完成长连接获取上传状态的时候,有两次请求,一次 ... -
mvc之类的驱动原理
2011-12-01 09:34 1061<mvc:annotation-driven /> ... -
Couldn't access current invocation
2011-10-20 20:44 1861做了一个aop的日志记录器,但是在运行的时候出现了日志信息 服 ...
相关推荐
该实例展示了 spring3 REST 的使用方法,以及同一种内容,多种不同方式展示的实现,例如同一 User 信息,可以展示为:xml,json,html三种不同的格式。可以参考这篇文章:http://badqiu.javaeye.com/blog/552806
并且基于Spring MVC提供了一个完整功能:实现了生成验证码图片,以及验证输入是否匹配的两个接口,接口为Rest风格,符合内容协商原则(同一资源,多种展现:xml,json,html)。 另外,演示了注解(Annotation)的用法,实现...
CXF spring 提供rest服务输出xml或json等格式数据
我们将学习如何使用Spring 4与REST Web Service来获取JSON响应。Spring 4 Web Service类用@RestController 进行注释, 可以取代@Controller和@ResponseBody的使用。要映射REST Web服务URL,请使用注释@...
这是一个示例应用程序,演示了如何使用Spring Boot构建REST风格的服务,该服务可以使用单个控制器类同时为JSON和XML提供服务。 可以使用Gradle在本地构建和运行它。 2.执照 在以下许可条款下,此示例应用程序及其...
Restdocs规范生成支持用法首先转到项目,然后按照说明设置Spring REST Docs扩展。 该扩展名将为您记录的每个resource.json生成resource.json文件。 您还将注意到,该项目提供了gradle插件,可用于读取所有resource....
Spring MVC - REST Web 服务 对于相同的域对象,RestController 通过接受 application/json 或 application/xml 生成相应的响应。 设置标题 接受:application/json,或 接受:应用程序/xml 并将 GET 请求发送到
弹簧座控制器Spring 4 Rest 控制器脚手架示例项目展示了 Spring 4 的 RestController 来提供 XML 和 JSON。 注意 pom 文件中使用的 Jackson 版本,因为 Spring 似乎特别关注 Jackson 版本。 样品用途: curl -v -i -...
输出XML和JSON 使用HttpEntity<T>/ResponseEntity<T> 目录 数据绑定机理 数据类型转换 PropertyEditor依然有效 强大的ConversionService,让很多梦想成真 基于ConversionService体系,定义自定义的类型转换器 格式化...
输出XML和JSON 使用HttpEntity<T>/ResponseEntity<T> 目录 数据绑定机理 数据类型转换 PropertyEditor依然有效 强大的ConversionService,让很多梦想成真 基于ConversionService体系,定义自定义的类型转换器...
带有JSON有效负载的REST服务。 使用spring-test进行集成测试。 AngularJS 1.2。 极简主义者,专注于使用REST服务的演示。 嵌入式HSQL数据库。 此外,该项目不包含XML。 Spring配置完全由注释驱动,并且每个Servlet ...
数据传输器:XML,JSON。数据库:Mysql。版本控制:Git。构建工具:Maven。工具:SpringToolSuit,Mysql-Workbench,用于测试Restcontroller的Postman。 涵盖的技术方面: 使用过的Spring MVC。 Spring MVC控制器。...
8.7 视图和内容协商 309 8.7.1 问题 309 8.7.2 解决方案 309 8.7.3 工作原理 309 8.8 映射异常视图 312 8.8.1 问题 312 8.8.2 解决方案 312 8.8.3 工作原理 312 8.9 用@Value在控制器中赋值 314 ...
8.7 视图和内容协商 309 8.7.1 问题 309 8.7.2 解决方案 309 8.7.3 工作原理 309 8.8 映射异常视图 312 8.8.1 问题 312 8.8.2 解决方案 312 8.8.3 工作原理 312 8.9 用@Value在控制器中赋值 314 ...
Develop RESTful API applications for XML and JSON data transfers with non-blocking asynchronous capabilities Explore Spring's comprehensive transaction support for declarative Transaction Management ...
Spring MVC Restful 基础搭建 ,主要包括:采用 GET POST PUT DELETE 进行数据的 CRUD ,以及内容协商机制,通过不同的请求返回不同的数据格式,包括 JSON XML 以及 HTML
简单的Spring Rest MVC示例,以演示一个简单的bookservice示例,该示例允许通过Rest EndPoints获取和添加书籍。 本示例可以基于客户端的Accept-Header生成JSON或XML。 项目打包是war文件。 要运行此程序,请部署到...
Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...
您可以直接与基于呈现技术的模板 (如 JSP、 Velocity和 Freemarker )集成或直接生成 XML、 JSON、 Atom和许多其他类型的内容。模型map被转化为合适的格式,如JSP request attributes或是 Velocity template model。
项目框架: spring+springmvc+mybatis 是否使用maven: 使用 数据库:oracle 使用了cxf 同时实现了 RESTful WebService --项目启动后访问地址 ...