这是我们对 REST 的概述的最后一部分。在前面的部分中,我们介绍了:
单击“Next”按钮。在下一个窗口中,指定“Maven Project”作为项目类型,指定“Group”和“Artifact”:
单击“Next”按钮。在下一个窗口中,我们需要选择项目所需的 Spring Framework 组件。Spring Web 对我们来说已经足够了:
单击“下一步”按钮。现在剩下的就是指示项目的名称及其在文件系统中的位置:
单击“完成”按钮。项目创建完成,现在我们可以看到它的结构:
IDEA
单击左上角的“新建”按钮。接下来,选择“Request”:
接下来,为其命名并保存。现在让我们尝试向服务器发送 POST 请求并创建第一个客户:
我们以这种方式创建了多个客户。然后我们将请求类型改为GET,向服务器发送请求:

创建项目
在本节中,我们将使用 Spring Boot 创建一个小型 RESTful 应用程序。我们的应用程序将对概述前一部分示例中的客户实施 CRUD(创建、读取、更新、删除)操作。首先,我们将通过菜单创建一个新的 Spring Boot 应用程序:File -> New -> Project... 在打开的窗口中,选择 Spring Initializr 并指定 Project SDK:




RestExampleApplication
为我们生成了一个Maven部署描述符(pom.xml)和应用程序的主类()。这是它们的样子:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.codegym.lessons/groupId>
<artifactId>rest_example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rest_example</name>
<description>REST example project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
休息示例应用程序:
@SpringBootApplication
public class RestExampleApplication {
public static void main(String[] args) {
SpringApplication.run(RestExampleApplication.class, args);
}
}
创建 REST 功能
我们的应用程序是一个客户管理系统。因此,我们需要做的第一件事是创建一个客户实体。它将是一个 POJO(普通旧 Java 对象)类。在包内创建一个model
包com.codegym.lessons.rest_example
。在包内model
,创建Customer
:
public class Customer {
private Integer id;
private String name;
private String email;
private String phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
该服务将对客户实施 CRUD 操作。下一步是创建将实现这些操作的服务。在com.codegym.lessons.rest_example
包中,创建一个service
包。在里面,创建一个CustomerService
界面。下面是带注释的接口代码:
public interface CustomerService {
/**
* Creates a new customer
* @param customer - Customer to be created
*/
void create(Customer customer);
/**
* Returns a list of all existing customers
* @return List of customers
*/
List<Customer> readAll();
/**
* Returns a customer based on its ID
* @param id - Customer ID
* @return - Customer object with the given ID
*/
Customer read(int id);
/**
* Updates the customer with the given ID,
* according to the passed customer
* @param customer - Customer to use to update the data
* @param id - ID of the customer you want to update
* @return - true if the data has been updated, otherwise false
*/
boolean update(Customer customer, int id);
/**
* Deletes the customer with the given ID
* @param id - ID of the customer to be deleted
* @return - true if the customer was deleted, otherwise false
*/
boolean delete(int id);
}
接下来,我们需要实现这个接口。现在一个Map<Integer, Customer>
将存储我们的客户。地图的键是客户 ID,值是客户本身。这样做是为了不让这个例子因使用真实数据库的细节而超载。但是,将来我们将能够编写该接口的另一个实现,这将使连接到真实数据库成为可能。在service
包中,创建接口的实现CustomerService
:
@Service
public class CustomerServiceImpl implements CustomerService {
// Customer repository
private static final Map<Integer, Customer> CUSTOMER_REPOSITORY_MAP = new HashMap<>();
// Variable for generating a customer ID
private static final AtomicInteger CUSTOMER_ID_HOLDER = new AtomicInteger();
@Override
public void create(Customer customer) {
final int customerId = CUSTOMER_ID_HOLDER.incrementAndGet();
customer.setId(customerId);
CUSTOMER_REPOSITORY_MAP.put(customerId, customer);
}
@Override
public List<Customer> readAll() {
return new ArrayList<>(CUSTOMER_REPOSITORY_MAP.values());
}
@Override
public Customer read(int id) {
return CUSTOMER_REPOSITORY_MAP.get(id);
}
@Override
public boolean update(Customer customer, int id) {
if (CUSTOMER_REPOSITORY_MAP.containsKey(id)) {
customer.setId(id);
CUSTOMER_REPOSITORY_MAP.put(id, customer);
return true;
}
return false;
}
@Override
public boolean delete(int id) {
return CUSTOMER_REPOSITORY_MAP.remove(id) != null;
}
}
注解@Service
告诉 spring 这个类是一个服务。这是一种特殊类型的类,用于实现某些业务应用程序逻辑。随后,由于这个注解,Spring 将使用依赖注入在所有需要它的地方为我们提供这个类的实例。现在是创建控制器的时候了。这是一个特殊的类,我们将在其中实现处理发送到端点 (URI) 的客户端请求的逻辑。为了使这一切更清楚,我们将逐步创建此类。首先,创建类本身并添加对以下内容的依赖CustomerService
:
@RestController
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
}
让我们解释一下注解: @RestController告诉 Spring 这个类是一个 REST 控制器。换句话说,这个类实现了处理客户端请求的逻辑。 @Autowired告诉 Spring 需要在这里添加一个依赖。我们将CustomerService
接口传递给构造函数。早些时候,我们用注释标记了这个服务的实现@Service
,现在 Spring 将能够将这个实现的实例传递给控制器的构造函数。接下来,我们将实现每个控制器方法来处理 CRUD 操作。让我们从创建操作开始。为此,我们编写了一个create
方法:
@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
customerService.create(customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
我们来分析一下这个方法: @PostMapping(value = "/customers")
意思是这个方法处理发送到地址“/customers”的POST请求。该方法返回一个ResponseEntity<?>
. AResponseEntity
是用于返回响应的特殊类。稍后,我们将使用它向客户端返回 HTTP 状态代码。该方法有一个@RequestBody Customer customer
参数。该参数的值来自请求体。注释@RequestBody
表明了这一点。在方法体内,我们调用create()
之前创建的服务的方法,并将其传递给接收到的参数中的客户控制器。ResponseEntity
然后我们通过创建一个新对象并将相应的HttpStatus
枚举字段传递给它来返回“201 Created”状态。接下来,我们将实现read
操作:首先,我们将实施操作以获取所有可用客户的列表:
@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
final List<Customer> customers = customerService.readAll();
return customers != null && !customers.isEmpty()
? new ResponseEntity<>(customers, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
让我们深入研究: @GetMapping(value = "/customers")
— 这里的一切都与注解相似@PostMapping
,但现在我们正在处理 GET 请求。这次我们返回一个ResponseEntity<List<Customer>>
,除了 HTTP 状态之外,我们还将返回一个响应主体,这将是客户列表。在 Spring 的 REST 控制器中,一切都是 POJO 对象和 POJO 对象的集合,它们作为响应主体返回并自动序列化为 JSON,除非另有说明。这非常适合我们。在方法内部,我们使用我们的服务来获取所有客户的列表。接下来,如果列表不为 null 且不为空,则我们使用ResponseEntity
返回客户列表和“200 OK”HTTP 状态代码的类。否则,我们简单地返回“404 Not Found”HTTP 状态代码。现在我们将实现使用其 ID 获取客户的能力:
@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
final Customer customer = customerService.read(id);
return customer != null
? new ResponseEntity<>(customer, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
这里的一个新事物是路径变量。该变量在 URI 中定义:value = "/customers/{id}"
。我们用花括号表示它。我们int
使用@PathVariable(name = "id")
注释将其作为方法参数接收。此方法将接受以 形式发送到 URI 的请求/customers/{id}
,其中{id}
代表任何数值。该值随后通过变量传递int id
给方法参数。在正文中,我们Customer
使用我们的服务和接收到的id
. 然后,通过类比列表,我们返回“200 OK”状态和对象Customer
本身,或者如果系统没有客户,则返回“404 Not Found”状态id
。我们还需要实现两个操作:更新和删除。以下是这些方法的代码:
@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
final boolean updated = customerService.update(customer, id);
return updated
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
final boolean deleted = customerService.delete(id);
return deleted
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
这些方法本质上没有什么新东西,所以我们将跳过详细描述。唯一值得一提的是update()
方法处理PUT请求(@PutMapping
注解),delete()
方法处理DELETE请求(DeleteMapping
注解)。这是控制器的完整代码:
@RestController
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
customerService.create(customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
final List<Customer> customers = customerService.readAll();
return customers != null && !customers.isEmpty()
? new ResponseEntity<>(customers, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
final Customer customer = customerService.read(id);
return customer != null
? new ResponseEntity<>(customer, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
final boolean updated = customerService.update(customer, id);
return updated
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
final boolean deleted = customerService.delete(id);
return deleted
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
}
因此,我们项目的结构如下: 
启动和测试
要启动我们的应用程序,只需运行类main()
中的方法即可RestExampleApplication
。但是要测试 RESTful Web 服务,我们需要下载额外的软件。事实上,从普通浏览器发送 GET 请求非常简单,但普通浏览器无法发送 POST、PUT 和 DELETE 请求。别担心:您可以使用一个名为 Postman 的程序来发送任何 HTTP 请求。你可以在这里下载。下载并安装 Postman 后,我们开始测试我们的应用程序。为此,打开程序并创建一个新请求: 



概括
恭喜!我们已经充分介绍了 REST。有大量的材料,但希望它对你有用:-
我们了解了 REST 是什么。
-
我们了解了 REST 是如何产生的。
-
我们谈到了这种架构风格的局限性和背后的原则:
- 客户端-服务器架构
- 无国籍的
- 缓存
- 统一接口
- 图层
- 按需代码(可选)
-
我们探索了 REST 提供的好处
-
我们详细检查了服务器和客户端如何通过 HTTP 协议相互交互。
-
我们仔细研究了请求和响应。我们剖析了它们的组成部分。
-
最后,我们通过使用 Spring Boot 编写自己的小型 RESTful 应用程序获得了一些实践经验。我们甚至学会了如何使用 Postman 对其进行测试。
家庭作业
尝试以下操作:- 按照上面的描述,创建您自己的 Spring Boot 项目并实现与课程中相同的逻辑。完全重复一切。
- 启动应用程序。
- 下载并配置 Postman(或任何其他用于发送请求的工具,例如 curl)。
- 按照课程中描述的相同方式测试 POST 和 GET 请求。
- 自己测试 PUT 和 DELETE 请求。
GO TO FULL VERSION