Spring 接口支持返回多种格式

2017 年 12 月 24 日 ImportNew

(点击上方公众号,可快速关注)


来源:xiagn ,

xiagn825.github.io/2017/06/23/blog/


1. 简介


本文介绍使用SpringMVC的后端服务如何通过配置来支持多种返回值类型(xml,json,html,excel)


这里的代码使用的是springboot,下载地址:


https://github.com/xiagn825/springboot-todolist/tree/springboot-ContentNegotiation


2. 基础概念


2.1 HttpHeader中Content-Type和Accept设置的区别


Accept:接口要返回给客户端的数据格式


curl --header 'Accept:application/json' http://localhost:8080/todo


Content-Type:客户端发送给服务器端的数据格式


curl -X PUT --header 'Content-Type:application/json' -d '{"title":"周

末日程","content":"睡觉"}' http://localhost:8080/todo


2.2 SpringMVC生成输出的两种方式


1) 当服务端使用Restful的方式,只为客户端的ajax或其他服务端请求提供数据时,通常会使用@ResponseBody来标识你的返回,这时候Spring使用HttpMessageConverter来把返回的对象格式化成所需的格式。


2) 当你需要提供表现层(比如:HTML),这时候SpringMVC使用ViewResolver来将处理你的返回。


有时候你的应用程序这两者都要提供


2.3 SpringMVC输出格式判定


很多时候为了支持多个系统或多个终端,你需要让相同的数据已不同的表现形式输出。


SpringMVC使用ContentNegotationStrategy来判定用户请求希望得到什么格式的数据。


ContentNegotationStrategy通过三种方式来识别用户想要返回什么样的数据


  1. 通过请求URL后缀:http://myserver/myapp/accounts/list.html 返回html格式

  2. 通过请求的参数:http://myserver/myapp/accounts/list?format=xls 该设置默认不开启,默认key是format。

  3. 通过HTTP Header的Accept:Accept:application/xml 优先级由上至下


请看如下配置


@Override

public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {

    configurer.favorPathExtension(false)

            .favorParameter(true)

            .parameterName("mediaType")

            .defaultContentType(MediaType.APPLICATION_JSON)

            .mediaType("xml", MediaType.APPLICATION_XML)

            .mediaType("html", MediaType.TEXT_HTML)

            .mediaType("json", MediaType.APPLICATION_JSON);

}


在你工程的WebMvcConfig中加入以上配置,表示关闭URL后缀的规则,打开请求参数规则并设置请求参数为’mediaType’,默认的返回格式是json,还支持返回xml,html。


这三个组件是用来处理返回不同格式输出的关键


  • Request Mappings: 决定不同的请求到不同的方法并返回不同的格式.

  • View Resolution: 根据类型返回合适的表示层.

  • HttpMessageConverters: 将request中的参数转换成java对象,将java对象转换成相应的输出格式到response.


2.4 RequestMappings


2.4.1 RequestMappingHandlerMapping


我们在spring中通常使用的就是RequestMappingHandlerMapping,根据RequestMappingInfo,细化匹配条件,整体的查找过程如下:


AbstractHandlerMethodMapping实现接口getHandlerInternal


1. 使用UrlPathHelper查找request对应的path


2. 查找path对应的HandlerMethod


2.1 从urlMap中直接等值匹配查找匹配条件RequestMappingInfo


2.2 如果等值查找到匹配条件,将其添加到match条件中


2.3 如果没有找到匹配条件,使用所有的handlerMethod的RequestMappingInfo进行匹配


2.4 对匹配到的Match进行排序,取出最高优先级的Match,并核对是否是唯一的最高优先级


2.5 对匹配到条件,没有匹配到条件的两种情况,分别进行封装


3. 封装HandlerMethod,确保bean中存的是实例    ContentNegotiationManager其中提供了针对miniType的match条件比较,使框架可以匹配到最合适的处理方法。


2.5 HttpMessageConverter


2.5.1 The Default Message Converters


SpringMvc默认会加载下列HttpMessageConverters:


ByteArrayHttpMessageConverter – converts byte arrays

StringHttpMessageConverter – converts Strings

ResourceHttpMessageConverter – converts org.springframework.core.io.Resource for any type of octet stream

SourceHttpMessageConverter – converts javax.xml.transform.Source

FormHttpMessageConverter – converts form data to/from a MultiValueMap<String, String>.

Jaxb2RootElementHttpMessageConverter – converts Java objects to/from XML (added only if JAXB2 is present on the classpath)

MappingJackson2HttpMessageConverter – converts JSON (added only if Jackson 2 is present on the classpath)

MappingJacksonHttpMessageConverter – converts JSON (added only if Jackson is present on the classpath)

AtomFeedHttpMessageConverter – converts Atom feeds (added only if Rome is present on the classpath)

RssChannelHttpMessageConverter – converts RSS feeds (added only if Rome is present on the classpath)


我们如果返回的是使用@ResponseBody来标识的,那么框架会使用HttpMessageConverter来处理返回值,默认的xmlCoverter不是特别好用,依赖返回实体对象上的@XmlRootElement注解,不是很方便所以引入辅助类库,并自定义MessageConverter这样可以直接将返回的对象处理成xml格式。


Gradle import library


compile group: 'org.springframework', name: 'spring-oxm', version: '4.3.9.RELEASE'

compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.10'


configuration


@Override

public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

    converters.add(createXmlHttpMessageConverter());

    super.configureMessageConverters(converters);

}

private HttpMessageConverter<Object> createXmlHttpMessageConverter() {

    MarshallingHttpMessageConverter xmlConverter =

            new MarshallingHttpMessageConverter();

    XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();

    xmlConverter.setMarshaller(xstreamMarshaller);

    xmlConverter.setUnmarshaller(xstreamMarshaller);

    return xmlConverter;

}


2.6 View Resolution


2.6.1 页面render(freemarker)


当需要返回页面时就需要由合适的viewResolver来绘制画面,这里采用freemarker作为页面引擎。


Gradle import library


compile("org.springframework.boot:spring-boot-starter-freemarker")


看完本文有收获?请转发分享给更多人

关注「ImportNew」,看技术干货

登录查看更多
1

相关内容

Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的MVC架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1,Struts2等。
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
一份简明有趣的Python学习教程,42页pdf
专知会员服务
76+阅读 · 2020年6月22日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
161+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【ICMR2020】持续健康状态接口事件检索
专知会员服务
17+阅读 · 2020年4月18日
【SIGMOD2020-腾讯】Web规模本体可扩展构建
专知会员服务
29+阅读 · 2020年4月12日
【ICLR2020-哥伦比亚大学】多关系图神经网络CompGCN
专知会员服务
49+阅读 · 2020年4月2日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
通过Docker安装谷歌足球游戏环境
CreateAMind
11+阅读 · 2019年7月7日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
搭建自己的searx搜索引擎
黑白之道
13+阅读 · 2019年5月31日
PHP使用Redis实现订阅发布与批量发送短信
安全优佳
7+阅读 · 2019年5月5日
使用 C# 和 Blazor 进行全栈开发
DotNet
6+阅读 · 2019年4月15日
支持多标签页的Windows终端:Fluent 终端
Python程序员
7+阅读 · 2019年4月15日
比Selenium快100倍的方法爬东方财富网财务报表
程序人生
8+阅读 · 2018年10月31日
用Python调用百度OCR接口实例
数据挖掘入门与实战
16+阅读 · 2018年1月29日
Rapid Customization for Event Extraction
Arxiv
7+阅读 · 2018年9月20日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
3+阅读 · 2018年4月9日
Arxiv
3+阅读 · 2018年4月5日
Arxiv
3+阅读 · 2017年7月6日
VIP会员
相关VIP内容
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
一份简明有趣的Python学习教程,42页pdf
专知会员服务
76+阅读 · 2020年6月22日
干净的数据:数据清洗入门与实践,204页pdf
专知会员服务
161+阅读 · 2020年5月14日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
117+阅读 · 2020年5月10日
【ICMR2020】持续健康状态接口事件检索
专知会员服务
17+阅读 · 2020年4月18日
【SIGMOD2020-腾讯】Web规模本体可扩展构建
专知会员服务
29+阅读 · 2020年4月12日
【ICLR2020-哥伦比亚大学】多关系图神经网络CompGCN
专知会员服务
49+阅读 · 2020年4月2日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
相关资讯
通过Docker安装谷歌足球游戏环境
CreateAMind
11+阅读 · 2019年7月7日
用Now轻松部署无服务器Node应用程序
前端之巅
16+阅读 · 2019年6月19日
搭建自己的searx搜索引擎
黑白之道
13+阅读 · 2019年5月31日
PHP使用Redis实现订阅发布与批量发送短信
安全优佳
7+阅读 · 2019年5月5日
使用 C# 和 Blazor 进行全栈开发
DotNet
6+阅读 · 2019年4月15日
支持多标签页的Windows终端:Fluent 终端
Python程序员
7+阅读 · 2019年4月15日
比Selenium快100倍的方法爬东方财富网财务报表
程序人生
8+阅读 · 2018年10月31日
用Python调用百度OCR接口实例
数据挖掘入门与实战
16+阅读 · 2018年1月29日
Top
微信扫码咨询专知VIP会员