使用spring mvc创建REST API

REST基础知识

什么是REST,与SOAPWeb Service以及其他RPC有什么区别?

以信息为中心的表述性状态转移REST(Representational State Transfer)已成为替换传统SOAP Web service的流行方案。

Spring对REST的支持是构建在Spring MVC之上,使用Spring MVC来开发处理RESTful资源的控制器

当谈论REST时,有一种常见的错误就是将其视为“基于URL的Web service”——将REST作为另一种类型的远程过程调用(remote procedure call,RPC)机制,就像SOAP一样,只不过是通过简单的HTTP URL来触发,而不是使用SOAP大量的XML命名空间。

恰好相反,REST与RPC几乎没有任何关系。RPC是面向服务的。知乎上有一个问题,既然有http请求,为什么还要用RPC调用?

参考:既然有http 请求,为什么还要用rpc调用?

成熟的RPC库相对于http容器,更多的是封装了“服务发现”、“错误重试”一类面向服务的高级特性,RPC框架是面向服务的更高级的封装。如果把一个http server容器上封装上一层服务发现和函数代理调用,那就可以做一个rpc框架了

这也就是书上所说的“对于许多应用程序而言,使用SOAP可能会有些大材小用了,而REST提供了一个更简单的可选方案”

而REST是面向资源的,强调描述应用程序的事物和名词。

Representational:REST资源可以用各种形式来进行表述,包括XML,JSON,甚至HTML

State:当使用REST的时候,我们更关注资源的状态

Transfer:REST涉及到转移资源数据,它以某种表述性形式从一个应用转移到另一个应用

REST就是将资源的状态以最适合客户端的形式从服务器端转移到客户端

Spring支持REST

1. @PathVariable注解,处理参数化URL(获取GET请求后面的参数)

2. 借助Spring的视图和视图解析器,资源能够以多种方式进行表述,包括将模型数据渲染为XML、JSON、Atom以及RSS的View实现(JSON以及JSONVIEW)

关于JSON VIEW,要进行说明:

如果限定了JSON的格式,那么只要后台JSON的格式发生了变化,前端都要进行对应的修改,这样会密集地发布新版本。

而如果不限定JSON的格式,比如说core使用的ItemView为app端展示用的item视图,包括基本信息,实施依据,受理条件,办事流程,业务申报材料,常见问题六个方面

基本信息basicInfoTab是一个Map<String,Map>

<”QL_KIND”,Map<String,String>>

name 权力事项类型

value 行政许可

3. @ResponseBody注解和各种HttpMethodConverter实现,能够替换基于视图的渲染方式

4. @RequestBody注解以及HttpMethodConverter实现可以将传入的HTTP数据转化为传入控制器处理方法的java对象

5. 借助RestTemplate,Spring应用能够方便地使用REST资源

表述Representation是REST中很重要的一个方面。它是关于客户端和服务器端针对某一资源是如何通信的。任何给定的资源都几乎可以用任意的形式来进行表述。

如果资源的使用者愿意使用JSON,那么资源就可以用JSON格式来表述。

如果使用者喜欢尖括号,那相同的资源可以用XML来进行表述。

同时,如果用户在浏览器中查看资源的话,可能更愿意以HTML的方式来展现(或者PDF、Excel及其他便于人类阅读的格式)。资源没有变化——只是它的表述方式变化了。

尽管Spring支持多种资源表述形式,但是在定义REST API的时候,不一定要全部使用它们。对于大多数客户端来说,用JSON和XML来进行表述就足够了。

当然,如果内容要由人类用户来使用的话,那么我们可能需要支持HTML格式的资源。根据资源的特点和应用的需求,我们还可能选择使用PDF文档或Excel表格来展现资源。

对于非人类用户的使用者,比如其他的应用或调用REST端点的代码,资源表述的首选应该是XML和JSON。借助Spring同时支持这两种方案非常简单,所以没有必要做一个非此即彼的选择。

需要了解的是控制器本身通常并不关心资源如何表述。控制器以Java对象的方式来处理资源。控制器完成了它的工作之后,资源才会被转化成最适合客户端的形式。

Spring创建REST端点

在响应体中返回资源状态

正常情况下,当处理方法返回Java对象(除String外或View的实现以外)时,这个对象会放在模型中并在视图中渲染使用。但是,如果使用了消息转换功能的话,我们需要告诉Spring跳过正常的模型/视图流程,并使用消息转换器。有不少方式都能做到这一点,但是最简单的方法是为控制器方法添加@ResponseBody注解。

举例来讲,假设客户端的Accept头部信息表明它接受“application/json”,并且Jackson JSON库位于应用的类路径下,那么将会选择MappingJacksonHttpMessageConverter或MappingJackson2HttpMessageConverter(这取决于类路径下是哪个版本的Jackson)。消息转换器会将控制器返回的Spittle列表转换为JSON文档,并将其写入到响应体中

谈及Accept头部信息,请注意getSpitter()的@RequestMapping注解。在这里,我使用了produces属性表明这个方法只处理预期输出为JSON的请求。也就是说,这个方法只会处理Accept头部信息包含“application/json”的请求。其他任何类型的请求,即使它的URL匹配指定的路径并且是GET请求也不会被这个方法处理。这样的请求会被其他的方法来进行处理(如果存在适当方法的话),或者返回客户端HTTP 406(Not Acceptable)响应。

在请求体中接收资源状态

@ResponseBody能够告诉Spring在把数据发送给客户端的时候,要使用某一个消息器,与之类似,@RequestBody也能告诉Spring查找一个消息转换器,将来自客户端的资源表述转换为对象。例如,假设我们需要一种方式将客户端提交的新Spittle保存起来。我们可以按照如下的方式编写控制器方法来处理这种请求:

例如,如果客户端发送的Spittle数据是JSON表述形式,那么ContentType头部信息可能就会是“application/json”。在这种情况下,DispatcherServlet会查找能够将JSON转换为Java对象的消息转换器。如果Jackson2库在类路径中,那么MappingJackson2HttpMessageConverter将会担此重任,将JSON表述转换为Spittle,然后传递到saveSpittle()方法中。--我们项目里面这个转换器是什么?是spring相关包中自带的jackson2

@RequestMapping有一个consumes属性,我们将其设置为“application/json”。consumes属性的工作方式类似于produces,不过它会关注请求的ContentType头部信息。它会告诉Spring这个方法只会处理对“/spittles”的POST请求,并且要求请求的ContentType头部信息为“application/json”

Spring 4.0引入了@RestController注解,能够在这个方面给我们提供帮助。如果在控制器类上使用@RestController来代替@Controller的话,Spring将会为该控制器的所有处理方法应用消息转换功能。我们不必为每个方法都添加@ResponseBody了。

使用异常处理器提供错误信息

异常处理器ErrorHandler能够应对错误场景,这样处理器方法就能关注于正常的状况。

首先,定义能够对应SpittleNotFoundException的错误处理器

@ExceptionHandler注解能够用到控制器方法中,用来处理特定的异常。这里,它表明如果在控制器的任意处理方法中抛出SpittleNotFoundException异常,就会调用spittleNotFound()方法来处理异常。

在我们的代码中就是通过code和value来说明错误状态的

有一个ErrorCode的enum,在service中,如果出了错误,会thrownew ZhantaiException,设置好ErrorCode,一个新的错误要在ErrorCode中添加一条记录。

spring编写REST客户端

在REST API中暴露资源只代表了会话的一端。通常来讲,移动或JavaScript应用会是REST API的客户端,但是Spring应用也完全可以使用这些资源。我们换个方向,看一下如何编写Spring代码实现RESTful交互的客户端。

在实践中有三种方式来访问RESTAPI

1. 使用传统的Apache Http Client

2. 使用org.apache.httpcomponents的fluent-hc

3. 使用RestTemplate

使用 fluent-hc 是自己进行解析 JSON 解析和对象映射的,但实际上如果 @RequestBody 注解可用的话,说明 jackson 至少是有的,那么 RestTemplate 应该是可以直接进行使用的,说明 RestTemplate 更简单好用

猜你喜欢

转载自blog.csdn.net/u013905744/article/details/80539261