使用spring mvc创建REST API

1. REST基础知识

 

什么是REST,与SOAP Web 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提供了一个更简单的可选方案”

 

常规风格与restful风格对比

restful风格:

  1. 用URL来描述资源

  2. 使用HTTP方法描述行为。使用HTTP状态码来表示不同的结果。

  3. 使用json交互数据。

  4. restful只是一种风格,并不是强制的标准

REST成熟度模型模型

 

2. Spring创建REST端点

 

Spring对REST的支持

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

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

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

4. @RequestBody注解以及HttpMessageConverter实现可以将传入的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对象的方式来处理资源。控制器完成了它的工作之后,资源才会被转化成最适合客户端的形式。

 

在响应体中返回资源状态

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

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

谈及Accept头部信息,请注意@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()方法来处理异常。

 

3. 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更简单好用

 

补充:关于JSON VIEW的一个实践

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

而如果不限定JSON的格式,比如项目中的一个场景。

前端需要显示一个办事事项的内容,包括基本信息,实施依据,受理条件,办事流程,业务申报材料,常见问题六个方面

后端需要如何与前端协商这样一个格式呢?从而保证前端可以根据后端的返回内容,动态的进行渲染(类似于前端H5页面)

方案就是前端根据后端的结果,后端有多少项,其就展示多少项

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

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

name 权力事项类型

value 行政许可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值