spring接口通过配置支持返回多种格式(xml,json,html,excel)
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通过三种方式来识别用户想要返回什么样的数据
- 通过请求URL后缀:http://myserver/myapp/accounts/list.html 返回html格式
- 通过请求的参数:http://myserver/myapp/accounts/list?format=xls 该设置默认不开启,默认key是format。
- 通过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")
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
- 51Nod 1091 线段的重叠(贪心+区间相关,板子题)
- 51Nod 1016 水仙花数 V2(组合数学,枚举打表法)
- Selenium2+python自动化67-用例失败自动截图
- Codeforces Round #404 (Div. 2)(A.水,暴力,B,排序,贪心)
- hihoCoder #1053 : 居民迁移(贪心,二分搜索,google在线技术笔试模拟)
- php开发文章发布示例(正则表达式实例开发)
- Codeforces Round #408 (Div. 2)(A.水,B,模拟)
- php实现文件上传
- Selenium2+python自动化69-PhantomJS使用
- Selenium2+python自动化70-unittest之跳过用例(skip)
- 用php做个简单的日历
- Selenium2+python自动化71-多个浏览器之间的切换
- 总结:JDK1.5-JDK1.8各个新特性
- hihoCoder #1094 : Lost in the City(枚举,微软苏州校招笔试 12月27日 )
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MFC实现的Socket通信
- 128-在线翻译
- C语言CGI编程二 - 编写cmd后门
- android 获取视频第一帧作为缩略图的方法
- Flutter利用注解生成可自定义的路由的实现
- Android实现随意拖动View效果的实例代码
- Kotlin的枚举与异常示例详解
- Android自定义View的使用及其原理知识点总结
- Android中Window的管理深入讲解
- Android UI绘制流程及原理详解
- flutter 轮播图动态加载网络图片的方法
- Kotlin如何捕获上下文中的变量与常量详解
- Android使用webView长按保存下载网络图片
- Android实现万能自定义阴影控件实例代码
- 浅析android studio3.5中使用recycleview的包