CodeGym /Java 博客 /随机的 /REST 概述。第 3 部分:在 Spring Boot 上构建 RESTful 服务
John Squirrels
第 41 级
San Francisco

REST 概述。第 3 部分:在 Spring Boot 上构建 RESTful 服务

已在 随机的 群组中发布
这是我们对 REST 的概述的最后一部分。在前面的部分中,我们介绍了: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 1

创建项目

在本节中,我们将使用 Spring Boot 创建一个小型 RESTful 应用程序。我们的应用程序将对概述前一部分示例中的客户实施 CRUD(创建、读取、更新、删除)操作。首先,我们将通过菜单创建一个新的 Spring Boot 应用程序:File -> New -> Project... 在打开的窗口中,选择 Spring Initializr 并指定 Project SDK: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 2单击“Next”按钮。在下一个窗口中,指定“Maven Project”作为项目类型,指定“Group”和“Artifact”: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 3单击“Next”按钮。在下一个窗口中,我们需要选择项目所需的 Spring Framework 组件。Spring Web 对我们来说已经足够了: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 4单击“下一步”按钮。现在剩下的就是指示项目的名称及其在文件系统中的位置: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 5单击“完成”按钮。项目创建完成,现在我们可以看到它的结构: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 6IDEARestExampleApplication为我们生成了一个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 对象)类。在包内创建一个modelcom.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);
   }
}
因此,我们项目的结构如下: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 7

启动和测试

要启动我们的应用程序,只需运行类main()中的方法即可RestExampleApplication。但是要测试 RESTful Web 服务,我们需要下载额外的软件。事实上,从普通浏览器发送 GET 请求非常简单,但普通浏览器无法发送 POST、PUT 和 DELETE 请求。别担心:您可以使用一个名为 Postman 的程序来发送任何 HTTP 请求。你可以在这里下载。下载并安装 Postman 后,我们开始测试我们的应用程序。为此,打开程序并创建一个新请求: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 9单击左上角的“新建”按钮。接下来,选择“Request”: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 10接下来,为其命名并保存。现在让我们尝试向服务器发送 POST 请求并创建第一个客户: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 11我们以这种方式创建了多个客户。然后我们将请求类型改为GET,向服务器发送请求: REST 概述。 第 3 部分:在 Spring Boot 上构建 RESTful 服务 - 12

概括

恭喜!我们已经充分介绍了 REST。有大量的材料,但希望它对你有用:
  1. 我们了解了 REST 是什么。

  2. 我们了解了 REST 是如何产生的。

  3. 我们谈到了这种架构风格的局限性和背后的原则:

    • 客户端-服务器架构
    • 无国籍的
    • 缓存
    • 统一接口
    • 图层
    • 按需代码(可选)
  4. 我们探索了 REST 提供的好处

  5. 我们详细检查了服务器和客户端如何通过 HTTP 协议相互交互。

  6. 我们仔细研究了请求和响应。我们剖析了它们的组成部分。

  7. 最后,我们通过使用 Spring Boot 编写自己的小型 RESTful 应用程序获得了一些实践经验。我们甚至学会了如何使用 Postman 对其进行测试。

呸。那是很多,但是您仍然需要做一些功课。

家庭作业

尝试以下操作:
  1. 按照上面的描述,创建您自己的 Spring Boot 项目并实现与课程中相同的逻辑。完全重复一切。
  2. 启动应用程序。
  3. 下载并配置 Postman(或任何其他用于发送请求的工具,例如 curl)。
  4. 按照课程中描述的相同方式测试 POST 和 GET 请求。
  5. 自己测试 PUT 和 DELETE 请求。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION