- 作者简介
- 内容提要
- 关于本书
- 路线图
- 代码规范与下载
- 作者在线
- 封面插图简介
- 前言
- 译者序
- 致谢
- 第1部分 Spring 的核心
- 第1章 Spring 之旅
- 第2章 装配 Bean
- 第3章 高级装配
- 第4章 面向切面的 Spring
- 第2部分 Web 中的 Spring
- 第5章 构建 Spring Web 应用程序
- 第6章 渲染 Web 视图
- 第7章 Spring MVC 的高级技术
- 第8章 使用 Spring Web Flow
- 第9章 保护 Web 应用
- 第3部分 后端中的 Spring
- 第10章 通过 Spring 和 JDBC 征服数据库
- 第11章 使用对象-关系映射持久化数据
- 第12章 使用 NoSQL 数据库
- 第13章 缓存数据
- 第14章 保护方法应用
- 第4部分 Spring 集成
- 第15章 使用远程服务
- 第16章 使用 Spring MVC 创建 REST API
- 第17章 Spring消息
- 第18章 使用 WebSocket 和 STOMP 实现消息功能
- 第19章 使用 Spring 发送 Email
- 第20章 使用 JMX 管理 Spring Bean
- 第21章 借助 Spring Boot 简化 Spring 开发
16.3.2 在响应中设置头部信息
在saveSpittle()方法中,我们在处理POST请求的过程中创建了一个新的Spittle资源。但是,按照目前的写法(参考程序清单16.3),我们无法准确地与客户端交流。
在saveSpittle()处理完请求之后,服务器在响应体中包含了Spittle的表述以及HTTP状态码200(OK),将其返回给客户端。这里没有什么大问题,但是还不是完全准确。
当然,假设处理请求的过程中成功创建了资源,状态可以视为OK。但是,我们不仅仅需要说“OK”。我们创建了新的内容,HTTP状态码也将这种情况告诉给了客户端。不过,HTTP 201不仅能够表明请求成功完成,而且还能描述创建了新资源。如果我们希望完整准确地与客户端交流,那么响应是不是应该为201(Created),而不仅仅是200(OK)呢?
根据我们目前所学到的知识,这个问题解决起来很容易。我们需要做的就是为saveSpittle()方法添加@ResponseStatus注解,如下所示:
这应该能够完成我们的任务,现在状态码能够精确反应发生了什么情况。它告诉客户端我们新创建了资源。问题已经得以解决!
但这只是问题的一部分。客户端知道新创建了资源,你觉得客户端会不会感兴趣新创建的资源在哪里呢?毕竟,这是一个新创建的资源,会有一个新的URL与之关联。难道客户端只能猜测新创建资源的URL是什么吗?我们能不能以某种方式将其告诉客户端?
当创建新资源的时候,将资源的URL放在响应的Location头部信息中,并返回给客户端是一种很好的方式。因此,我们需要有一种方式来填充响应头部信息,此时我们的老朋友ResponseEntity就能提供帮助了。
如下的程序清单展现了一个新版本的saveSpittle(),它会返回ResponseEntity用来告诉客户端新创建的资源。
程序清单16.4 当返回ResponseEntity时,在响应中设置头部信息
在这个新的版本中,我们创建了一个HttpHeaders实例,用来存放希望在响应中包含的头部信息值。HttpHeaders是MultiValueMap<String, String>的特殊实现,它有一些便利的Setter方法(如setLocation()),用来设置常见的HTTP头部信息。在得到新创建Spittle资源的URL之后,接下来使用这个头部信息来创建ResponseEntity。
哇!原本简单的saveSpittle()方法瞬间变得臃肿了。但是,更值得关注的是,它使用硬编码值的方式来构建Location头部信息。URL中“localhost”以及“8080”这两个部分尤其需要注意,因为如果我们将应用部署到其他地方,而不是在本地运行的话,它们就不适用了。
我们其实没有必要手动构建URL,Spring提供了UriComponentsBuilder,可以给我们一些帮助。它是一个构建类,通过逐步指定URL中的各种组成部分(如host、端口、路径以及查询),我们能够使用它来构建UriComponents实例。借助UriComponentsBuilder所构建的UriComponents对象,我们就能获得适合设置给Location头部信息的URI。
为了使用UriComponentsBuilder,我们需要做的就是在处理器方法中将其作为一个参数,如下面的程序清单所示。
程序清单16.5 使用UriComponentsBuilder来构建Location URI
在处理器方法所得到的UriComponentsBuilder中,会预先配置已知的信息如host、端口以及Servlet内容。它会从处理器方法所对应的请求中获取这些基础信息。基于这些信息,代码会通过设置路径的方式构建UriComponents其余的部分。
注意,路径的构建分为两步。第一步调用path()方法,将其设置为“/ spittles/”,也就是这个控制器所能处理的基础路径。然后,在第二次调用path()的时候,使用了已保存Spittle的ID。我们可以推断出来,每次调用path()都会基于上次调用的结果。
在路径设置完成之后,调用build()方法来构建UriComponents对象,根据这个对象调用toUri()就能得到新创建Spittle的URI。
在REST API中暴露资源只代表了会话的一端。如果发布的API没有人关心和使用的话,那也没有什么价值。通常来讲,移动或JavaScript应用会是REST API的客户端,但是Spring应用也完全可以使用这些资源。我们换个方向,看一下如何编写Spring代码实现RESTful交互的客户端。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论