从“A”到“Web应用程序”:用Java构建API
我写这篇教程是为了填补我发现的一个空白。对于学习后端开发的人来说,构建 Web 应用程序是首要任务,但我还没有看到任何 Java 或 Spring Boot 教程能够提供清晰的路径,帮助读者快速、轻松地掌握 Web 应用程序。现有的教程要么过于浅显(例如“Hello World API”),无法帮助读者理解所需知识;要么过于复杂,假设读者已经掌握了太多基础,令初学者感到不知所措。
你只需要掌握Java的中级水平,其他内容我会在课程中逐步讲解。如果你已经熟悉某个主题,可以直接跳过。这样可以确保你的知识体系完整,学习路径上没有盲点。
我将使用 Spring Boot 构建一个简单的 Web API,这是向构建企业级应用程序迈出的一大步。
- 什么是API?
- Twitter API 示例
- Spring和Spring Boot是什么?
- 我们将建造什么
- 这是最新的方法吗?
- 开始之前我应该知道些什么吗?
- 完成本教程所需材料
- 如何设置您的项目
- 编写代码
- 如何测试你的应用程序
- 源代码
- 后续步骤
什么是API?
现在,企业通过API(应用程序编程接口)提供数据访问权限已成为一种普遍做法。API是应用程序编程接口的缩写,它提供了一系列方法,使我们能够通过互联网与企业的后端系统进行交互。这些方法通常被称为Web服务。
让我们来看一个 API 的例子,以更清楚地了解它到底是什么!
Twitter API 示例
我猜你已经知道推特是什么了,但为了以防万一,我们还是简单介绍一下:推特是一个社交微博网站。随着时间的推移,它已经不仅仅是一个微博网站了,现在它成了唐纳德·特朗普发泄情绪的地方!✍😡
Twitter 的 API 参考文档提供了详尽的分类方法列表。您可以对推文、私信、个人账户设置等执行各种操作。几乎所有在网站上能做的事情,都可以通过 API 实现。如果您愿意,还可以使用 API 为 Twitter 构建一个完全不同的前端界面,或者创建一个 Twitter 机器人。
让我们举个使用 API 的例子,假设我们想要获取@spiderman时间线上的所有推文。
查看方法列表后,GET statuses/user_timeline方法似乎符合我们的需求。以下是该方法的描述:
我们需要一个客户端应用程序来执行这些方法。我喜欢用Insomnia,但其他流行的应用程序还有:cURL(一个命令行工具)、Postman(一个用于 API 开发的协作平台)和Postwoman(一个精简的开源 Postman 替代方案)。
如果您对 HTTP 完全不熟悉,可以直接跳到HTTP 基础知识部分快速了解。查看方法描述,我们需要在 HTTP 请求中提供一个参数才能获取所需数据,这个参数是screen_name。
要使用 Twitter 的 API,您必须拥有一个 Twitter 帐户,并注册一个应用程序以获取开发者密钥。当您与 API 交互时,您需要提供这些开发者密钥来验证您的身份。这确保只有您才能对您自己的帐户数据执行操作,并确保您以公平的方式使用该平台。
你需要对 Twitter 帐户设置进行一些配置才能获取开发者密钥。不过,这个设置的位置并不显眼!这里我就不详细讲解了,重点是向你展示 API 的概念。下图左侧是请求,右侧是收到的响应。
您可以看到,我们的screen_name参数被附加到请求的 URL 中。我们使用问号来标记参数的开头,然后提供参数名称和值。如有需要,您可以提供参数列表,每个参数之间用 & 符号分隔。
响应返回一个包含推文的 JSON 数组。推文的内容包含在 `<td>`text字段中。正如你所看到的,蜘蛛侠的最新推文是:“在这节由艺术家 @MikeHawthorne 带来的特别西班牙语课程中,学习如何绘制迈尔斯·莫拉莱斯,也就是蜘蛛侠……https://t.co/RdvzWVzJ4o。 ” 🕸️🎨
Spring和Spring Boot是什么?
Spring是一个开源应用程序框架。你可以把它想象成一把用于创建企业应用程序的瑞士军刀,它拥有不同的模块,提供一系列功能,例如:身份验证、数据访问、控制反转、消息传递、Web服务等等。
春天的理念是:
- 好的设计比底层技术更重要。
- 通过接口松耦合的类是一个很好的模型。
- 代码应该易于测试。
Spring 遵循约定优于配置的原则。通过遵循某些约定,例如以特定方式命名事物和实现特定接口,它可以避免编写大量重复代码(样板代码)。它还会为你处理一些繁琐的工作,有些事情会在后台神奇地自动完成!
Spring Boot 让创建独立的、基于 Spring 的应用程序变得更加轻松。它预配置了 Spring 团队对 Spring 平台和第三方库的最佳配置方案,让您能够快速上手。它内置了 Web 服务器,因此无需手动部署应用程序,您可以直接运行。
我们将建造什么
我们将为用户构建一个网络服务。我们都希望有人使用我们的应用,对吧?😅🙏
我们不会像实际应用程序那样使用数据库。我们会使用一些虚拟数据来模拟这种情况。
下表总结了我们的用户 API。
| HTTP 方法 | 地址 | 行动 |
|---|---|---|
| 得到 | /用户 | 获取所有用户 |
| 得到 | /users/{id} | 按ID获取用户 |
| 得到 | /users?name=rob+oleary | 按名称获取用户 |
| 邮政 | /用户 | 添加新用户 |
| 放 | /用户 | 更新用户 |
| 删除 | /users/{id} | 删除用户 |
当我们运行应用程序时,Spring Boot 应用程序的默认本地地址应该是:http://localhost:8080,因此,要获取所有用户的地址http://localhost:8080/users例如应该是。
这是最新的方法吗?
Spring 框架一直在不断迭代更新,因此不同示例之间可能会存在一些差异,这可能会让人感到困惑。大多数选择都与风格有关,有些则基于框架本身随时间推移而发生的变化。Spring 的当前稳定版本是 5.25,Spring Boot 的当前稳定版本是 2.3.0。
我始终建议查看你能找到的最新教程,并选择符合你学习偏好的教程风格。
开始之前我应该知道些什么吗?
刚开始学习如何使用 Spring Boot 构建 API 时,一个常见的问题是,教程要么默认你已经了解Spring 隐式使用的设计模式,要么把它当作一个机械的流程:把这段代码放在这里,写一个这样的方法,添加这个注解,等等。这并不是一个好的学习方法。我会帮助你理解为什么要以特定的方式做事。
简单介绍一下设计模式
设计模式是针对常见问题的通用、可重用的解决方案。
设计模式能够提供经过测试和验证的解决方案,从而加快开发过程。重用设计模式有助于避免一些小错误,这些错误可能会在后期引发重大问题。
大型应用程序会被划分成多个层,每个层负责特定的职责,这样更容易维护。Spring 使用模型-视图-控制器 (MVC)设计模式来构建 Web 应用程序。
模型-视图-控制器(MVC)
MVC 的核心理念是代码的每一层都有其特定的用途。
每一层的作用是什么?
- 模型:模型捕捉应用程序所关注的现实世界事物,它对现实世界进行建模。模型中的类用于存储和操作应用程序的状态。
- 视图:视图是用户界面,它将模型渲染给用户。在 Web 应用程序中,它指的是我们用 HTML 编写的网页,涵盖了应用程序的“前端”。在我们的示例应用程序中,我们没有编写视图部分。
- 控制器:控制器层是模型层和视图层之间的桥梁,它接收用户输入并决定如何处理。Web 应用程序中的控制器包含两部分。第一部分是 Web 服务器,它将传入的 HTTP 请求匹配到特定的处理方法,这是 Spring Boot 的内置部分。第二部分是处理方法本身,有时也会被误称为“控制器”,这部分是我们编写的。处理方法负责从模型返回数据。
这种方法的优势在于,我们的应用程序耦合度更低。您可以更改视图,但模型可以保持不变。这种职责分离使我们的应用程序更易于维护。
如果您想了解更深入的解释,可以阅读这篇MVC 文章。
更高级示例中使用的其他模式
在我们的示例中,我们只是隐式地使用了 MVC 模式。
在更高级的示例中,您可能还会遇到或需要使用以下设计模式:
- 数据访问对象层/存储库层:使用数据库时,您很可能会用到这些模式之一。该层控制对存储数据的访问,并将应用程序的其他部分与数据源隔离开来——它们无需知道数据是数据库、电子表格还是文本文件!Spring 提供了一系列Spring Data 库来支持数据存储库。
- 服务层:这一层承载着我们常用的业务逻辑。服务使用存储库来执行任务。例如,图书服务可以使用用户存储库和图书存储库来提供“搜索我的书籍”等功能。
HTTP基础知识
超文本传输协议 ( HTTP ) 是万维网数据通信的基础。它是一种控制客户端应用程序(例如 Web 浏览器)和 Web 服务器之间数据传输的协议。客户端和服务器通过交换消息进行通信。客户端发送的消息称为请求,服务器回复的消息称为响应。
HTTP 请求的目标被称为资源。通常,Web 资源是指 Web 服务器上的文件,例如文档或照片;但现在它的含义已经扩展到任何可唯一标识的“事物”。现在,它甚至可以包含抽象资源,例如类和属性。每个资源都由一个统一资源标识符 (URI) 来标识。
统一资源定位符(URL)
URI最常见的形式是统一资源定位符(URL),也就是我们常说的网址。这就是你在Web浏览器中输入以加载网页的内容。
URL由不同的部分组成,有些是必需的,有些是可选的。
- 方案或协议:它指示必须使用的协议。通常是 HTTP 或其安全版本 HTTPS。这是必需的。
- 域名或授权名称:这表示所请求的 Web 服务器的名称。也可以直接使用 IP 地址,但由于不太方便,因此在 Web 上并不常用。这是必需的。
- 端口:端口是用于定位 Web 服务器上特定进程或服务的逻辑标识符。如果 Web 服务器使用 HTTP 协议的标准端口(HTTP 使用 80 端口,HTTPS 使用 443 端口)来授予对其资源的访问,则通常会省略端口。端口是可选的。
- 路径:是指向 Web 服务器上资源的路径。该路径可以表示 Web 服务器上的物理文件位置,也可以是 Web 服务器用于查找资源的抽象概念。
- 查询:它是一个参数列表。这些参数是键值对列表,键值对之间用 & 符号分隔
&。Web 服务器可以使用这些参数执行一些条件逻辑。这是可选的。 - 片段:它是指向资源本身某个部分的锚点。锚点就像资源内部的“书签”,指示浏览器显示位于该位置的内容。例如,在 HTML 文档中,浏览器会滚动到锚点所在的位置;对于视频,浏览器会尝试跳转到锚点所代表的时间点。此功能是可选的。
HTTP 请求
HTTP 请求包含以下内容:
- 请求行。例如,
GET http://localhost:8080/users/1 HTTP/1.1它想要/users/1从服务器检索由路径标识的资源。 - 请求头字段
- 空行
- 以及可选的消息正文。
GET http://localhost:8080/users/1 HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
HTTP 定义了一组请求方法,用于定义对给定资源执行的操作。它们有时也被称为 HTTP 动词。以下 HTTP 请求方法常用于 Web 应用程序:
- GET:检索资源的数据。
- POST:创建新资源。
- PUT:更新或替换资源。
- PATCH:更新或修改资源。
- 删除:删除资源。
您经常会看到 Web 应用程序的核心功能被称为 CRUD,它代表:创建、读取、更新、删除。
HTTP 响应
HTTP响应包含以下内容:
- 包含状态码和原因消息的状态行,
- 响应头字段
- 空行
- 可选的消息正文。
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json
Date: Mon, 01 Jun 2020 15:16:54 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunkedtes
Connection: close
{"id":1,"name":"Rob OLeary","age":21}
以下是方法响应中典型内容的摘要。
| HTTP 方法 | 增删改查 | 整个集合(例如 /users)的响应 | 针对特定项目的响应(例如 /users/{id}) |
|---|---|---|---|
| 邮政 | 创造 | 状态码:成功则返回 201(已创建),如果资源已存在则返回 404(未找到)或 409(冲突)。 “Location”标头包含指向 /users/{id} 的链接,其中 {id} 为新 ID。 |
状态码:成功时为 201(已创建),如果资源已存在则为 404(未找到)或 409(冲突)。 |
| 得到 | 读 | 状态码:200(正常)。 响应体中包含用户列表。 使用分页、排序和筛选功能,方便浏览大型列表。 |
状态码:成功则返回 200(OK),未找到或 ID 无效则返回 404(未找到)。 如果成功,则在正文中返回客户数据。 |
| 放 | 更新/替换 | 状态码:405(方法不允许),除非您想更新/替换整个集合中的每个资源。 | 状态码:成功时为 200(OK)或 204(无内容);如果找不到 ID 或 ID 无效,则为 404(未找到)。 |
| 修补 | 更新/修改 | 状态码:405(方法不允许),除非您想修改集合本身。 | 状态码:成功时为 200(OK)或 204(无内容);如果找不到 ID 或 ID 无效,则为 404(未找到)。 |
| 删除 | 删除 | 状态码:405(方法不允许),除非您想删除整个集合,但这很少是可取的。 | 状态码:成功则为 200(OK),未找到或 ID 无效则为 404(未找到)。 |
关于HTTP的更多阅读
如需更完整的 HTTP 指南,您可以阅读Mozilla 的 HTTP 参考文档。
关于 JSON 的一些知识
JSON 代表 JavaScript 对象表示法,是一种用于存储和交换数据的语法。JSON 已成为 Web 服务首选的数据格式,而XML 的使用频率则有所下降。
JSON 之所以流行,其中一个原因是我们可以将从服务器接收的任何 JSON 转换为 JavaScript 对象,而无需任何复杂的解析和转换。由于 JavaScript 是 Web 浏览器的语言,这使得构建 Web 应用程序变得更加简单。
语法规则很简单:
- 数据以名称-值对的形式存在,
- 字符串包含在引号中。
- 数据之间用逗号分隔。
- 花括号用于括起对象,
- 方括号用于表示数组。
例如,用户对象可以写成:
{ "name": "John", "age": 31 }
用户数组可以写成:
[
{ "name": "John", "age": 31 },
{ "name": "Mary", "age": 30 }
]
关于 JSON 的更多阅读
了解这些应该足以应对 Web 服务,但如需了解更多信息,W3schools 提供了一系列关于 JSON 的简短教程。
关于 REST 的一点介绍
您可能已经注意到,我在本文中几乎没有提到 REST,那是因为我认为这个术语被滥用得太频繁了。
表述性状态转移(REST)是一种架构风格,它定义了一组在创建Web服务时可以遵循的约束条件,并建议使用许多Web约定。它由Roy Fielding于2000年在其博士论文中提出。
我建议阅读Stack Overflow 上关于“什么是 RESTful 编程”的讨论帖,以便更好地了解它,您还可以看到人们对 REST API 在实际应用中的各种不同看法。
如果你使用像 Spring Boot 这样的框架构建 Web 服务,默认情况下你会遵循一些 RESTful API 设计的约定,但有些人会认为它是基于 HTTP 的 Web 服务,而不是 RESTful Web 服务。当人们通过与学术定义进行比较来讨论 Web 应用程序的 RESTful 程度时,问题很快就会变得模糊不清,我认为这样做并无益处。
REST 的一个约束是使用超媒体作为应用程序状态引擎 (HATEOS),这在 Spring Boot 中可以通过使用Spring Data Rest starter 依赖项来实现。实际上,大多数 API 并不遵循这个约束,这导致一些人认为“既然如此,那就不是 REST API 了”。😅 遵循这个约束固然有其价值,但对于客户端来说,使用起来会更加复杂,我想这就是人们不常使用它的原因。
对我来说,关键在于开发 Web 服务时要务实,使其易于使用且易于扩展。大多数人认同并遵循的做法是将应用程序组织成资源,我们在模型中也采用了这种方式,并利用 HTTP 方法来实现资源的功能。约定是使用统一的资源路径,例如 `<resource_path>` ,它是资源名称的复数形式。如果您想深入了解这些约定,可以阅读这篇关于务实 RESTful API 设计的/users优秀文章。
完成本教程所需材料
- 大约1小时。
- 你最喜欢的文本编辑器或集成开发环境。
- JDK 1.8 或更高版本。
- Gradle 或 Maven。根据你使用的 IDE,你可以跳过这一步,例如 IntelliJ 内置了 Maven。我个人使用 Maven。
如何设置您的项目
您可以使用Spring Initializr创建项目。它提供了一种快速创建项目框架的方法。
该项目仅需要一个依赖项,那就是 Spring Web。
要使用Spring Initializr,请填写相关字段,然后单击“生成”。之后,您可以将项目下载为 zip 文件。
解压缩文件,然后在您选择的集成开发环境(IDE)中打开。
当您导入/打开项目时,IDE 可能会自动下载依赖项,或者您可能需要手动触发下载:
- 在 IntelliJ 中,您可以通过
File > Synchronise菜单中的相应选项来触发下载。 - 在命令行中:
- 对于 Maven,运行命令
mvn install。 - 对于 Gradle,运行该命令
gradle build。
- 对于 Maven,运行命令
Spring Initializr 会创建一个名为UserApplication.java的默认类来运行你的 Web 应用程序。你可以运行它来验证配置是否正确。它会为你运行一个 Web 服务器,仅此而已,因为我们还没有编写任何代码!如果配置正确,你应该会在命令行看到类似这样的输出:
你可以跟着我的步骤一起编写代码,也可以从 github 下载完整的代码。
编写代码
获取所有用户
让我们先来编写代码,获取所有用户。
创建模型类
我们的应用一切都以用户为中心,这才是所有应用都应该有的样子!😉
我们想要创建一个User具有以下属性的类:id、name和age。
在后台,Spring 在创建或更新用户(响应 POST 和 PUT 请求)时可能需要创建空对象。因此,如果您想要支持这些操作,则始终需要包含一个无参构造函数。
我们添加了一些常规方法,使之成为一个标准的 Java 类。setter 和 getter 方法用于获取和修改属性。我们还必须包含比较Userequals对象的方法。我使用 IntelliJ 生成了所有这些方法。hashCode
public class User {
private long id;
private String name;
private int age;
//you must include a no-args constructor when you have a POST or PUT method
public User(){ }
public User(long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
//getters and setters, equals() and hashCode() generated by IDE
}
创建控制器
请记住,控制器负责将 HTTP 请求与返回响应的 Java 方法进行匹配。
我们向 Controller 添加注解来实现功能。` @RestController@RestController` 将类标记为 Rest Controller,以便 Spring 可以链接一些功能。我们指定 Controller 应该解释所有指向指定路径的/users请求@RequestMapping ("/users")。
我们添加了处理不同请求的方法,并使用注解来指示它们响应的 HTTP 方法。我们从方法中返回数据,Spring 会将数据转换为 JSON 格式,并将其作为响应返回。
我创建了一个ArrayList用户列表,以便返回一些数据。
该getUsers方法(你可以随意命名)返回 URL http://localhost:8080/users 的@RequestMapping所有用户。我们使用 `@Users`或 `@Users`注解将 URL 与我们的方法关联起来@GetMapping。我们从该方法中返回该用户ArrayList。
import com.roboleary.model.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController
@RequestMapping ("/users")
public class UserController {
List<User> users = new ArrayList<User>();
public UserController(){
users.add(new User(1, "Rob OLeary", 21));
users.add(new User(2, "Angela Merkel", 20));
users.add(new User(3, "Tamer Osman", 20));
}
//for GET to http://localhost:8080/users
@GetMapping
public List<User> getUsers(){
return users;
}
}
@RequestMapping 变体
Spring 4.3 引入了快捷注解,其作用与注解相同@RequestMapping,但名称中包含 HTTP 方法。
您可能也见过它们。它们是:
@GetMapping@PostMapping@PutMapping@DeleteMapping@PatchMapping
所以,你可以这样为你的方法添加注解:
@GetMapping
或者这样:
@RequestMapping(method=GET)
创建一个类来启动应用程序
如果您使用了 Spring Initialzr,那么这个类已经为您创建好了!
这是启动 Web 应用程序打包的主类,然后启动一个嵌入式 Web 服务器来为我们运行 Web 服务。
package com.spiderman.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
最难的部分已经完成了!
运行应用程序
它能正常运行吗?运行该类,您可以在浏览器中UserApplication测试该方法。GET
通过 ID 获取用户
为了通过 ID 获取用户,我们希望能够在 URL 中指定 ID。
例如,我们访问http://localhost:8080/users/2获取 ID 为 2 的用户,我们期望得到以下响应:
[{ id: 2, name: "Angela Merkel", age: 20 }];
我们将变量名放在花括号内作为@GetMapping注解的一部分,并在方法签名中使用注解声明它@PathVariable。我们搜索数据库ArrayList以找到第一个具有该 ID 的用户。
如果找到用户,则返回OK状态码 (200)。如果未找到用户,则返回Not Found状态码 (404)。
@GetMapping(value="/{id}")
public ResponseEntity getUsersById(@PathVariable("id") long id){
User userFound = null;
for(User user: users){
if(user.getId() == id){
userFound = user;
break;
}
}
if (userFound == null) {
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
//found
return new ResponseEntity(userFound, HttpStatus.OK);
}
按名称获取用户
为了按名称获取用户,我们希望能够在 URL 的末尾指定一个参数。
例如,我们访问http://localhost:8080/users?name=rob oleary
获取名为“rob oleary”的用户。
浏览器可能会在地址栏中添加“+”号来代替空格,例如:http://localhost:8080/user?name=rob+oleary,但
URL 中的空格被认为是不安全的。您无需进行任何特殊处理,两种方式都能正常工作!我们预期会收到以下响应:
[{ id: 1, name: "Rob OLeary", age: 21 }];
我们需要params在@GetMapping注解中添加参数名称。这样做是为了定义一个唯一的路径,以便 Spring 能够准确地将请求映射到正确的方法。
我们@RequestParam在方法签名中指定了该变量,以便在方法内部使用该变量来搜索具有该名称的用户。我们equalsIgnoreCase()接受客户端返回的任何大小写字母组合。
我们根据是否找到用户返回相应的状态。
@GetMapping(params = "name")
public ResponseEntity getUsersByName(@RequestParam(value="name") String name){
List<User> filteredUsers = new ArrayList<User>();
for(User user: users){
if(user.getName().equalsIgnoreCase(name)) {
filteredUsers.add(user);
}
}
if (filteredUsers.isEmpty() == true) {
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
//found
return new ResponseEntity(filteredUsers, HttpStatus.OK);
}
添加新用户
我们将用户添加到我们的ArrayList. 我们使用ResponseEntity作为我们的方法返回类型,它是一个包装类,我们可以选择性地包含以下内容:状态码(操作结果)和标头,以便向客户端提供有关结果的信息。
这次我们的参数带有注释@RequestBody,这是因为数据是在 HTTP 请求的主体中提供的。
我们返回的状态码为HttpStatus.CREATED,即 HTTP 状态码 201。添加新用户到我们的系统中不会出现失败的情况ArrayList,但如果您使用数据库,则应考虑这一点。
@PostMapping
public ResponseEntity add(@RequestBody User u) {
users.add(u);
return new ResponseEntity(u, HttpStatus.CREATED);
}
更新用户
更新用户信息,如果找不到用户,则添加新用户。
PUT 方法是幂等的,这意味着如果多次执行该操作,结果都相同。
我们的参数再次被标注@RequestBody。
根据我们是更新用户还是添加用户,我们会返回不同的状态码。
@PutMapping
public ResponseEntity addOrUpdate(@RequestBody User u) {
ResponseEntity response;
if(users.contains(u)){
//update by setting it at the specified position
int index = users.indexOf(u);
users.set(index, u);
response = new ResponseEntity(u, HttpStatus.OK);
}
else{
users.add(u);
response = new ResponseEntity(u, HttpStatus.CREATED);
}
return response;
}
我们的 Web 应用程序不使用 PATCH 请求。PATCH 请求用于局部更新。
当您使用数据库时,这种方法可能更有效,因为仅更新已更改的部分比替换整个对象更高效。但由于我们使用内存进行所有操作ArrayList,因此这种方法没有优势。
删除用户
我们将用户从我们的数据库中移除ArrayList,并返回一个状态码以指示是否找到该用户。
@DeleteMapping(value="/{id}")
public ResponseEntity delete(@PathVariable("id") long id) {
boolean found = false;
for(User user: users){
if(user.getId() == id){
users.remove(user);
found = true;
break;
}
}
if (found == false) {
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
//found
return new ResponseEntity(HttpStatus.OK);
}
如何测试你的应用程序
如果你想为你的代码创建自动化测试,这是一个值得花更多时间讨论的独立话题。
目前,为了验证功能是否正常,您可以在浏览器中执行 GET 请求。您可以使用像Insomnia这样的客户端应用程序来执行其他请求。
以下是一个使用 Insomnia 添加新用户的简单示例。我们发送一个如下所示的 POST 请求,将新用户的 JSON 对象放在请求体中,并将请求体类型设置为 JSON(这通常会将Content-Type标头设置为“application/json”)。状态码 201 表示用户创建成功。
源代码
您可以从 GitHub 下载完整代码。
robole / spring-boot-api-for-beginners
Spring Boot Web 服务入门指南
下一步
- 学习如何为你的Web应用程序编写(集成)测试。
- 添加数据库以长期存储您的数据。
- 构建一个完整的、符合你兴趣的API。
- 了解如何添加身份验证来控制对数据的访问。
- 学习如何编写 API 文档。您可以使用 AsciiDoctor 和 Swagger 等库来自动化部分文档编写工作。
如果你觉得这篇文章有用,请点个赞❤。如果你对以上某个主题的后续文章感兴趣,请告诉我!🙂
祝您编程愉快!👩💻🙌
图表中的图标来自 Noun Project:Mobile 由 Rainbow Designs 设计,Cloud 由 James Kopina 设计,Database 由 Kimmi Studios 设计,User 由 Adrian Coquet 设计,Twitter 由 Acid Beast 设计。
文章来源:https://dev.to/robole/from-a-to-web-app-build-an-api-in-java-4he5











