第一章 构建Restful开放API的两种常用方式

7 篇文章 1 订阅
5 篇文章 0 订阅

第一章 构建Restful开放API的两种常用方式

随着近几年微服务这种架构风格的火热,很多人都对Restful API有了一定的认识,Martin Folwer发表的论文中关于微服务中服务间的通讯需采用轻量级通信机制,这种轻量级的通信机制必须是能够跨语言、跨平台的,通常采用Http资源API作为微服务的通信机制。下面就会为大家带来关于如何构建Restful API提供两种常用方式,在介绍如何构建Restful API的常用方式之前,先跟大家介绍和学习一下关于Restful的相关知识,为后面打下一定的基础。

1.Restful是什么?
1.1.Restful的定义

Representational State Transfer,中文翻译过来是“表现层状态转化”,对于Restful的定义百度百科是这么描述的:“一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件”。

1.1.1.资源

面向资源是REST最明显的特征,”资源”是一种信息实体,所谓”资源”,就是网络上的一个实体,或者说是网络上的一个具体信息,它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。

1.1.2.表现层

“资源”是一种信息实体,它可以有多种外在表现形式。我们把”资源”具体呈现出来的形式,叫做它的”表现层”。

比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。

URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的”.html”后缀名是不必要的,因为这个后缀名表示格式,属于”表现层”范畴,而URI应该只代表”资源”的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对”表现层”的描述。

1.1.3.状态转化

访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生”状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是”表现层状态转化”。

客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

1.1.4.总结

综合上面的解释,我们总结一下什么是RESTful架构:

(1)每一个URI代表一种资源;

(2)客户端和服务器之间,传递这种资源的某种表现层;

(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。

1.2.Restful API

对Restful API的定义是:符合REST设计标准的API

1.3.Restful API最佳实践

(1)使用名词而不是动词

正例:
/employees       返回employees集合
/employees/711    返回指定的employee

反例:
/getAllEmployees
/createNewEmployee

(2)Get方法和查询参数不应该涉及状态改变
使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态,不要使用GET 进行状态改变:

GET /users/711?activate
GET /users/711/activate

(3)使用复数名词

/foods代替/food
/users代替/user

(4)使用子资源来表述资源间的关系

GET /cars/711/drivers 查询711号car所有的driver列表
GET /cars/711/dirvers/4 查询711号car的4号driver

(5)使用Http头声明序列化格式

在客户端和服务端,双方都要知道通讯的格式,格式在HTTP-Header中指定
Content-Type 定义请求格式
Accept 定义了接收相应的格式列表

(6)使用HATEOAS约束
HATEOAS(Hypermedia as the engine of application state)是REST架构风格中最复杂的约束,也是构建成熟REST服务的核心。它的重要性在于打破了客户端与服务器之间严格的契约,使得客户端能够自适应。

{
    "content": "dev-0.0.6",
    "user": {
        "name": "sxp",
        "age": 12,
        "_links": {
            "item": {
                "href": "http://localhost:8080/data-acquisition/greeting/sxp/sxp"
            }
        }
    }
}

(7)提供过滤、排序、字段选择、分页

GET /cars?color=red 返回红色的cars
GET /cars?seats<=2 返回小于两座位的cars集合

(8)API版本化

使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.

/blog/api/v1

(9)充分使用HTTP状态码来处理错误
HTTP状态码是用来表示网页服务器HTTP响应状态的3为数字码。在设计API处理错误时,应该充分使用HTTP状态码,而不是简单的抛出一个”500-服务器错误”。

所有的异常都应该有一个错误的payload作为映射,下面是一个例子:

{
  "errors": [
   {

    "userMessage": "Sorry, the requested resource does not exist",
    "internalMessage": "No car found in the database",
    "code": 34,
    "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
   }
  ]
}
1.4.构建Restful API常用方式

由于Spring Boot能够快速构建项目,所以本书所有的项目都是基于Spring Boot开发的工程,如果读者对Spring Boot不太了解,请自行阅读相关资料学习。

首先新建一个Spring Boot项目,命名为:restful-project, 本书所有的项目使用Spring Boot 1.5.8.RELEASE版本构建。

1.4.1.Spring MVC构建Restful API

(1)在工程中引入web starter pom maven构建

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

(2)新建一个controller包,在该包中创建一个Controller类叫做GreetingController

@Controller
public class GreetingController {
    /**
     * The constant TEMPLATE.
     */
    private static final String TEMPLATE = "Hello, %s!";

    /**
     * Greeting http entity.
     *
     * @param name the name
     * @return the http entity
     */
    @GetMapping("/api/greeting", produces = {"application/json"})
    public HttpEntity<Greeting> greeting(
            @RequestParam(value = "name") String name) {
        Greeting greeting = new Greeting(String.format(TEMPLATE, name));
        GreetUser greetUser = new GreetUser();
        greetUser.setName("sxp");
        greetUser.setAge(25);
        greeting.setUser(greetUser);
        return new ResponseEntity<>(greeting, HttpStatus.OK);
    }

(3)这样一个Restful api就构建完成了。

备注:大家看到上面是不是觉得使用Spring MVC构建就是这么简单,其实这里得要多亏于Spring Boot的自动配置和起始依赖功能,否则并不会这么简单。由于Spring Boot的快速部署、快速构建等特点的突显,在现今的微服务中通常都会使用它作为项目基础来开发。

下面来讲解一下Spring MVC常用构建Restful的注解以及注解中的属性
- @Controller — 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象
- @RestController — 是@ResponseBody和@Controller组合注解,返回某种形式的文本信息,比如json、xml,配置的视图解析器InternalResourceViewResolver不起作用

  • @RequestMapping — 用来处理请求地址映射的注解,可用于类或方法上
① value, method

value:指定请求的实际地址

method:指定请求的method类型, GETPOSTPUTDELETE等;

② consumesproduces

consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

produces:  指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

③ params,headers

params: 指定request中必须包含某些参数值是,才让该方法处理。

headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。

备注:现在也可以不指定method,直接使用GetMapping、PostMapping、PutMapping以及DeleteMapping

  • @PathVariable — 用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数

  • @RequestParam — 主要用于在Spring MVC后台控制层获取参数,类似一种是request.getParameter(“name”),它有三个常用参数:defaultValue = “0”, required = false, value = “isApp”;defaultValue 表示设置默认值,required 通过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。

  • @ResponseBody — 用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区

1.4.2.Spring Boot整合Jersey构建Restful API

(1)在项目中引入jersey start pom maven构建

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jersey</artifactId>
</dependency>

(2)在Spring的启动类中,加入如下代码,注入Servlet Bean,配置Jersey的拦截url和相关配置类,这个ServletContainer其实就是一个HttpServlet类,跟Spring中的DispatcherServlet作用一样,是用来作为请求分发的入口:

@Bean
public ServletRegistrationBean jerseyServlet() {
    ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/rest/*");
    // our rest resources will be available in the path /rest/*
    registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfiguration.class.getName());
    return registration;
}

(3)Jersey相关配置类,配置扫描路径与Spring 请求范围

public class JerseyConfiguration extends ResourceConfig {

    /**
     * Instantiates a new Jersey configuration.
     */
    public JerseyConfiguration() {
        register(RequestContextFilter.class);
        //配置restful package.
        packages("com.happygo.dataacquisition.controller");
    }
}

(4)创建一个Restful API的Resource类

@Path("/")
public class RestJerseyResource {

    /**
     * Hello map.
     *
     * @return the map
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/hello")
    public Map<String, Object> hello() {
        Map<String, Object> map = new HashMap<>();
        map.put("code", "1");
        map.put("codeMsg", "success");
        return map;
    }
}

下面对Jersey注解作简单介绍:
- @Path — ①标注class,表明该类是个资源类。凡是资源类,必须使用@Path注解,不然jersey无法扫描到该资源类。
②标注method,表示具体的请求资源的路径

  • @GET — @GET、@POST、@PUT、@DELETE指明http请求的方式属于get,post,put,delete中的哪一种。具体的指定请求方式,需要在客户端发起请求指定

  • @Consumes — 指定http请求的MIME类型,表示任意的MIME类型。该注解的值是个数组类型,支持多个MIME类型,可以使用MediaType来指定MIME类型

  • @Produces — 指定http响应的MIME类型,表示任意的MIME类型。该注解的值是个数组类型,支持多个MIME类型,可以使用MediaType来指定MIME类型

  • @PathParam — 配合@Path来使用的,使用方式在@Path用{}来指定路径中匹配的参数,这种匹配是通过正则表达式来实现的。比如PersonResource使用@Path(“/{id}”)

  • @QueryParam — @QueryParam获取的参数,实际就是url中拼接在?后面的参数

  • @FormParam — 客户端以form(MIME为application/x-www-form-urlencoded)的方式提交表单,服务端使用@FormParam解析form表单中的参数

  • @FormDataParam — 通常在上传文件的时候,需要@FormDataParam。客户端提交form(MIME为multipart/form-data)的方式提交表单,服务端使用@FormDataParam来解析form表单中的参数

  • @HeaderParam — 获取http请求头中的参数值

  • @CookieParam — 获取http请求头中cookie中的参数值

    关于jersey的详细文档请查阅Jersey官网文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值