- 浏览: 958183 次
- 性别:
- 来自: 江西上饶
文章分类
- 全部博客 (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 5296一个cron表达式有至少6 ... -
spring mvc list
2015-12-14 10:28 1284我使用这样无法传入 @requestMapping(" ... -
Unable to locate Spring NamespaceHandler for XML schema namespace
2015-09-23 14:00 2322org.springframework.beans.facto ... -
关于使用s.url jstl的上下文
2015-08-16 13:28 917比如 [@s.url '/'/]index.html?cote ... -
Spring 属性占位符配置器 PropertyPlaceholderConfigurer
2015-08-02 12:43 2082<!-- 属性配置文件读 ... -
FactoryBean接口
2014-09-30 14:05 908实现了FactoryBean接口的bean不是简单的一个bea ... -
国际化之MessageSourceAware和MessageSourceAccessor
2014-01-06 23:13 2853先看接口MessageSourceAware 该接口的注释中 ... -
spring 惯例优先原则
2013-07-22 09:46 1211惯例优先原则(convention over configur ... -
ant path匹配
2013-07-22 09:40 2174spring和ant path实现相关的主要类有两个 org. ... -
springmvc action方法中参数具有@ModelAttribute与不具有的区别
2012-12-14 09:36 4114在springmvc的参数解析中,发现具有@ModelAttr ... -
util包
2012-12-05 13:50 1107spring的util基本上都在springframework ... -
url,请求相关帮助类UrlPathHelper
2012-11-29 11:18 2519org.springframework.web.util.Ur ... -
整站国际化方案
2012-11-28 17:46 1108当前常见的实现方式,主要由两种方案实现 1.通过locale ... -
spring的三种注入方式
2012-11-20 17:30 18671.通过bean的property子元 ... -
spring AnnotationUtils 注解工具
2011-12-08 11:27 1303spring AnnotationUtils 注解工具 -
GenericCollectionTypeResolver,用于获取list或者map等元素的类型
2011-12-07 16:17 1311GenericCollectionTypeResolver,用 ... -
属性编辑器
2011-12-05 18:19 1079我自定义了一个类型,然后设置了一个属性编辑器,注册的class ... -
iframe下面的session问题
2011-12-04 19:52 5320在写iframe完成长连接获取上传状态的时候,有两次请求,一次 ... -
mvc之类的驱动原理
2011-12-01 09:34 1097<mvc:annotation-driven /> ... -
Couldn't access current invocation
2011-10-20 20:44 1895做了一个aop的日志记录器,但是在运行的时候出现了日志信息 服 ...
相关推荐
该实例展示了 spring3 REST 的使用方法,以及同一种内容,多种不同方式展示的实现,例如同一 User 信息,可以展示为:xml,json,html三种不同的格式。可以参考这篇文章:http://badqiu.javaeye.com/blog/552806
并且基于Spring MVC提供了一个完整功能:实现了生成验证码图片,以及验证输入是否匹配的两个接口,接口为Rest风格,符合内容协商原则(同一资源,多种展现:xml,json,html)。 另外,演示了注解(Annotation)的用法,实现...
在IT行业中,构建RESTful服务...总结一下,通过CXF 2.6与Spring的集成,我们可以轻松地创建REST服务并支持多种数据格式的输出,如XML和JSON。这使得我们的应用程序更具有灵活性和互操作性,符合现代Web服务的设计原则。
在"Apache CXF + Spring3 + REST + JSON配置"中,我们主要探讨如何利用Apache CXF和Spring 3框架来构建RESTful服务,并使用JSON作为数据交换格式。以下是一些关键知识点: 1. **Spring 3集成CXF**: - 首先,你...
**Spring MVC + Velocity + REST Services (XML, JSON) 实例详解** 在当今的Web开发领域,Spring MVC、Velocity和RESTful服务是常见的技术栈。这个实例项目是一个基于Maven构建的无数据库操作的轻量级Web应用,它...
本文主要介绍了使用Spring框架构建REST API的全过程,内容包括了从基础的Spring Web应用搭建,到使用Java配置,再到通过Spring Security进行安全认证和授权,以及REST API的其他重要特性,例如:使用HTTP消息转换器...
Spring MVC 是一个强大的Java Web应用程序框架,用于构建高效、可维护的Web应用。它扩展了Spring框架的功能,提供了模型-视图-...在实际操作中,读者可以按照文件名"spring_mvc"中的内容逐步实践每个步骤,加深理解。
本项目实例“Rest输出Json的WebService项目”便是一个展示如何利用RESTful接口发送和接收JSON数据的实例,其中整合了MyBatis和Spring两大框架,提供了一个完整的解决方案。 1. RESTful API设计:REST的核心思想是...
【标题】"csh框架+cxf+spring+hibernate+mysql 注解 annotation xml json" 提到的是一个基于Java技术栈的Web服务开发架构,涵盖了多个关键组件和技术,这些技术在现代企业级应用中广泛应用。以下是这些知识点的详细...
在`servlet-context.xml`中,我们将配置Spring MVC的处理器映射器、视图解析器和其他相关组件: ```xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=...
"rest+spring+hibernate"这个主题结合了这三个关键技术,主要探讨如何在Spring框架中实现RESTful API,并利用Hibernate进行数据访问。 1. **RESTful API设计**:REST原则强调资源的表述和状态转移,通过HTTP动词...
`RestTemplate`支持多种数据格式的转换,如JSON、XML。默认情况下,它包含`MappingJackson2HttpMessageConverter`来处理JSON。如果需要其他格式,可以添加更多的转换器。 6. **自定义请求头** 可以使用`...
在本篇中,我们将深入探讨如何使用Spring MVC构建RESTful接口,主要关注的是在实际项目中创建第一个REST风格接口的源代码实现。REST(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,...
Spring4 MVC作为Java领域最流行的MVC框架之一,提供了一流的支持来构建RESTful API,尤其适合输出JSON格式的数据结构。本文将深入探讨如何使用Spring4 MVC实现这一目标。 首先,理解REST(Representational State ...
接下来,我们来看看如何在Spring MVC中实现RESTful接口并使用JSON: 1. **配置Spring MVC**:首先,你需要在Spring的配置文件中启用MVC支持,添加`<mvc:annotation-driven>`标签。这将自动配置必要的处理器,支持...
了解REST和Spring中的REST服务实现是现代Web开发的重要组成部分。通过REST,我们可以构建高效、可扩展的API,方便客户端进行数据交互。Spring框架提供了强大的工具,简化了REST服务的开发过程,使开发者能够快速、...
3. **资源表示**: 在RESTful设计中,每个URL被视为一个资源,资源的表示通常由JSON或XML提供。在Spring中,可以使用`@ResponseBody`注解将方法返回的对象转换为JSON格式发送到客户端。 4. **HTTP方法**: RESTful ...
标题中的“Spring MVC – Easy REST-Based JSON Services with @ResponseBody”是指使用Spring MVC框架构建基于REST的JSON服务,并通过使用`@ResponseBody`注解来简化这一过程。REST(Representational State ...
在本章中,我们将深入探讨Spring MVC框架中的RESTful风格URL设计以及如何处理静态资源。REST(Representational State Transfer)是一种软件架构风格,常用于Web服务设计,它强调通过HTTP方法(如GET、POST、PUT、...
标题中的"jersey+spring rest webservice web maven"是一个基于Java开发的RESTful Web服务架构,它结合了几个关键的技术组件。让我们深入探讨每个部分: 1. **Jersey**: Jersey是Java RESTful Web服务(JAX-RS)...