写点什么

搭建 Restful Web 服务

作者:信码由缰
  • 2022 年 3 月 09 日
  • 本文字数:3865 字

    阅读完需:约 13 分钟

搭建 Restful Web 服务

1. 理解 REST

  REST 全称是 Representational State Transfer,中文意思是表征性状态转移。它首次出现在 2000 年 Roy Fielding 的博士论文中,Roy Fielding 是 HTTP 规范的主要编写者之一。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。如果一个架构符合 REST 的约束条件和原则,我们就称它为 RESTful 架构。

  理论上 REST 架构风格并不是绑定在 HTTP 上,只不过目前 HTTP 是唯一与 REST 相关的实例。

1.1. REST 原则

  • 资源 可通过目录结构样式的 URIs 暴露

  • 表述 可以通过 JSON 或 XML 表达的数据对象或属性来传递

  • 消息 使用统一的 HTTP 方法(例如:GET、POST、PUT 和 DELETE)

  • 无状态 客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息

1.2. HTTP 方法

  使用 HTTP 将 CRUD(create, retrieve, update, delete <创建、获取、更新、删除—增删改查>)操作映射为 HTTP 请求。如果按照 HTTP 方法的语义来暴露资源,那么接口将会拥有安全性和幂等性的特性,例如 GET 和 HEAD 请求都是安全的, 无论请求多少次,都不会改变服务器状态。而 GET、HEAD、PUT 和 DELETE 请求都是幂等的,无论对资源操作多少次, 结果总是一样的,后面的请求并不会产生比第一次更多的影响。

1.2.1. GET

  • 安全且幂等

  • 获取信息

1.2.2. POST

  • 不安全且不幂等

  • 使用请求中提供的实体执行操作,可用于创建资源或更新资源

1.2.3. PUT

  • 不安全但幂等

  • 使用请求中提供的实体执行操作,可用于创建资源或更新资源

1.2.4. DELETE

  • 不安全但幂等

  • 删除资源


      POST 和 PUT 在创建资源的区别在于,所创建的资源的名称(URI)是否由客户端决定。 例如为我的博文增加一个 java 的分类,生成的路径就是分类名/categories/java,那么就可以采用 PUT 方法。不过很多人直接把 POST、GET、PUT、DELETE 直接对应上 CRUD,例如在一个典型的 rails 实现的 RESTful 应用中就是这么做的。

1.3. HTTP status codes

  状态码指示 HTTP 请求的结果:

  • 1XX:信息

  • 2XX:成功

  • 3XX:转发

  • 4XX:客户端错误

  • 5XX:服务端错误

1.4. 媒体类型

  HTTP 头中的 Accept 和 Content-Type 可用于描述 HTTP 请求中发送或请求的内容。如果客户端请求 JSON 响应,那么可以将 Accept 设为 application/json。相应地,如果发送的内容是 XML,那么可以设置 Content-Type 为 application/xml 。

2.11. 如何创建 Rest API URL

  推荐使用下面格式的 URL:

http(s)://{域名(:端口号)}/{表示 REST API 的值}/{API 版本}/{识别资源的路径}

http(s)://{表示 REST API 的域名(:端口号)}/{API 版本}/{识别资源的路径}

  如下所示:

http://example.com/api/v1/members/M000000001http://api.example.com/v1/members/M000000001

3. 开发基于 Spring Boot 的 Restful Web 服务

  Spring Boot 提供了构建企业应用中 RESTful Web 服务的极佳支持。

3.1. 引入依赖

  要构建 RESTful Web 服务,我们需要在构建配置文件中加上 Spring Boot Starter Web 依赖。

  对于 Maven 用户,使用以下的代码在 pom.xml 文件中加入依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>    
</dependency>
复制代码

  对于 Gradle 用户,使用以下的代码在 build.gradle 文件中加入依赖:

compile('org.springframework.boot:spring-boot-starter-web')
复制代码

3.2. Rest 相关注解

  在继续构建 RESTful web 服务前,建议你先要熟悉下面的注解:

Rest Controller

  @RestController 注解用于定义 RESTful web 服务。它提供 JSON、XML 和自定义响应。语法如下所示:

@RestController
public class ProductServiceController {
}
复制代码

Request Mapping

  @RequestMapping 注解用于定义请求 URI 以访问 REST 端点。我们可以定义 Request 方法来消费 produce 对象。默认的请求方法是 GET:

@RequestMapping(value = "/products")
public ResponseEntity<Object> getProducts() { }
复制代码

Request Body

@RequestBody 注解用于定义请求体内容类型。

public ResponseEntity<Object> createProduct(@RequestBody Product product) {
}
复制代码

Path Variable

  @PathVariable 注解被用于定义自定义或动态的请求 URI,Path variable 被放在请求 URI 中的大括号内,如下所示:

public ResponseEntity<Object> updateProduct(@PathVariable("id") String id) {
}
复制代码

Request Parameter

  @RequestParam 注解被用于从请求 URL 中读取请求参数。缺省情况下是必须的,也可以为请求参数设置默认值。如下所示:

public ResponseEntity

POST API

  HTTP POST 请求用于创建资源。这个方法包含请求体。我们可以通过发送请求参数和路径变量来定义自定义或动态 URL。

  下面的示例代码定义了 HTTP POST 请求方法。在这个例子中,我们使用 HashMap 来存储 Product,这里产品是一个 POJO 类。

  这里,请求 URI 是 /products,在产品被存入 HashMap 仓储后,它会返回字符串。

package com.tutorialspoint.demo.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.demo.model.Product;
@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   @RequestMapping(value = "/products", method = RequestMethod.POST)
   public ResponseEntity<Object> createProduct(@RequestBody Product product) {
      productRepo.put(product.getId(), product);
      return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
   }
}
复制代码

PUT API

  HTTP PUT 请求用于更新已有的资源。这个方法包含请求体。我们可以通过发送请求参数和路径变量来定义自定义或动态 URL。

  下面的例子展示了如何定义 HTTP PUT 请求方法。在这个例子中,我们使用 HashMap 更新现存的产品。此处,产品是一个 POJO 类。

  这里,请求 URI 是 /products/{id},在产品被存入 HashMap 仓储后,它会返回字符串。注意我们使用路径变量 {id} 定义需要更新的产品 ID:

package com.tutorialspoint.demo.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.demo.model.Product;
@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
   public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) {
      productRepo.remove(id);
      product.setId(id);
      productRepo.put(id, product);
      return new ResponseEntity<>("Product is updated successsfully", HttpStatus.OK);
   }   
}
复制代码

DELETE API

  HTTP Delete 请求用于删除存在的资源。这个方法不包含任何请求体。我们可以通过发送请求参数和路径变量来定义自定义或动态 URL。

  下面的例子展示如何定义 HTTP DELETE 请求方法。这个例子中,我们使用 HashMap 来移除现存的产品,用 POJO 来表示。

  请求 URI 是 /products/{id} 在产品被从 HashMap 仓储中删除后,它会返回字符串。 我们使用路径变量 {id} 来定义要被删除的产品 ID。

package com.tutorialspoint.demo.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.demo.model.Product;
@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE)
   public ResponseEntity<Object> delete(@PathVariable("id") String id) {
      productRepo.remove(id);
      return new ResponseEntity<>("Product is deleted successsfully", HttpStatus.OK);
   }
}
复制代码


发布于: 1 小时前阅读数: 4
用户头像

信码由缰

关注

分享程序人生。 2019.07.04 加入

“码”界老兵,分享程序人生。

评论

发布
暂无评论
搭建 Restful Web 服务_REST API_信码由缰_InfoQ写作平台