学习 Spring Boot
简介
现在,制作一个能够满足你需求的应用程序变得比以往任何时候都更容易了。在你当前使用的任何编程语言中,都有成千上万的应用程序开发框架可供使用。Spring 是其中一个你可以使用的框架,用于开发你的梦想应用程序、网站或服务器。
更新的视频教程
我已经制作了一个使用 Spring Boot 和 Java 进行登录和注册的更新视频教程。如果你更喜欢阅读旧教程,请继续往下看。
本文最初发表于 Simple Coding
Spring 是一个流行的应用程序开发框架,专为 Java 编程语言的企业版开发而设计。
根据 Spring 网站 的说法:“Spring 使 Java 编程更快、更容易、更安全。Spring 的速度、简单性和生产力使其成为世界上最流行的 Java 框架。”
MySQL 是一种开源的关系型数据库管理系统。这是我们将使用的数据库,用于存储我们注册的用户。Swagger 是一个开源项目,用于描述和记录我们的 API。
这样一个大而流行的框架的副作用是,有时会让人望而生畏,难以接近和开始学习它的工作方式。通常情况下,如果你对想要使用框架做什么有一些想法,那么跟随一步步的指南也同样有用。
所以,今天我们将会构建一个非常基本的用户认证 API,它将允许用户注册新用户并进行登录。这个项目并不是你可以用来构建你的新业务或个人项目的后端,但它会让你进入 Spring 框架的门槛。
关注我的 Twitter,获取最新的博客文章和有趣的算法和 Web 开发内容的通知。
查看我们的网站和我们的 YouTube 频道,了解更多全栈开发信息。
开始之前,你需要在你的电脑上安装以下几个东西:
- 你需要安装 Java JDK。你可以在这里找到 JDK 的安装说明。
- 你需要安装一个集成开发环境(IDE)。我个人推荐使用 IntelliJ IDEA Community Edition。
- 你需要一个终端和 Curl CLI。如果你使用的是 MacOS 或者 Linux,那么你应该已经有了。如果你使用的是 Windows,那么你可以尝试安装 Curl 或者使用 Windows 子系统 for Linux,在 Windows 上使用 Linux 终端。
- 最后,我们需要安装 MySQL。你可以按照他们网站上的步骤进行安装。
配置
当你的开发环境准备好后,你可以转到 Spring Initializr 页面。这个网站用于创建应用程序的基本启动包,以便你可以更少地进行操作就能实现更多。如果你想要精确地按照我的步骤进行操作,那么你应该按照以下方式设置你的项目:
我将我的项目设置如下:
- 项目:Maven 项目。
- 语言:Java。
- Spring Boot:2.4.0
- 组:(留空)。
- 构件:教程。
- 名称:教程。
- 描述:使用 Spring 和 Spring Boot 制作的基本用户认证应用程序。
- 包名称:.tutorial
- 打包:Jar
- Java:8
- 依赖项:Spring Web、MySQL Driver、Spring Data JPA
依赖项并不是很重要,因为我会给你提供我们将使用的依赖项列表,以确保我们在项目上保持一致。选择好所有内容后,点击“Generate”按钮。这将创建一个 zip 文件,你应该下载并解压到你的开发文件夹中。将项目导入你选择的 IDE 中。如果你使用的是 IntelliJ,导入项目的步骤如下:
- 打开 IntelliJ。
- 点击“打开或导入”。
- 转到你刚才解压的文件。
- 单击一次以突出显示,然后单击“确定”。
项目将被导入到你的 IDE 中,并开始下载依赖项并索引文件,以便它知道如何设置你的项目。随意探索一下,查看所有文件夹并打开一些文件,但一定要注意不要意外更改任何文件,因为这可能导致你的项目无法编译。
打开名为“TutorialApplication”的文件。这是你的主文件。当你运行程序时,它将从这里开始,然后运行其他文件。花一些时间看看文件,看看你能否理解其中发生了什么。
不要忘记意识到,你已经创建了你的第一个 Spring 应用程序。在运行程序之前,我们必须先编辑一些文件。所以进入“src/main/resources”,双击“application.properties”。这是你的应用程序属性所在的地方。在文件中输入以下内容:
spring.datasource.url = jdbc:mysql://localhost:3306/users
spring.datasource.username = USERNAME
spring.datasource.password = PASSWORD
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = updatespringdoc.api-docs.path=/api-docs
所以这一段代码块将数据库路径设置为“jbdc:mysql://localhost:3306/users”(数据库托管在计算机的端口 3306 上,我们特别关注“users”数据库)。我们设置用户名,你需要设置你的用户名,通常为“root”。
接下来,我们设置数据库的密码,你需要在这里输入你的密码。在接下来的两行中,我们只是说明了 Spring 框架应该如何与数据库交互,以及我们希望在处理它时能够更新数据库。最后一行则不太重要,它只是指向我们 API 文档的新路径。看,这并不难,虽然也不是很有趣。现在你可以关闭那个文件了,在本教程中我们不会再用到它。接下来,打开你主文件夹中的“pom.xml”文件。这是另一个处理项目设置的文件,也是我们声明将要使用哪些依赖项的地方。我不会解释每个依赖项的作用,因为如果这样做的话,我们会在这里呆上一整天。
找到“<dependencies></dependencies>”括号,它应该在第21到41行之间。找到它后,你可以用以下代码块替换它:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.2.32</version>
</dependency>
</dependencies>
保存项目后会弹出一个带有重新加载图标的“m”。点击它,它将下载依赖项并确保一切有效。我们需要做的最后一件事是创建“users”数据库。打开终端并键入以下命令:
mysql -u root -p
它会要求你输入密码,请输入密码。现在你应该能看到类似于这样的东西:
接下来输入以下命令以显示所有活动数据库:
SHOW DATABASES;
记得在末尾添加分号,否则它会继续到下一行,我已经犯了这样的错误很多次了。现在你应该可以看到一个表格,其中包含所有数据库。接下来让我们创建“users”数据库。输入以下命令:
CREATE DATABASE users;
这将创建新的“users”数据库。这应该是我们设置数据库的全部工作。现在你可以输入
exit
退出MySQL终端。回到你的IDE并打开“TutorialApplication”,它在“src/main/java/tutorial”下。在文件中右键单击并单击旁边带有“Run TutorialApplic…main()”的绿色三角形。底部的终端将打开,你将看到很多文本被打印出来。
你做到了!你创建了基础,可以在其上构建更好的应用程序。花点时间欣赏你为完成基础所做的工作。接下来我们需要创建其余的应用程序,所以让我们开始吧。
设置文件
在左侧的项目选项卡上,右键单击“tutorial”包,然后单击“new”,然后单击“package”。将此新包命名为“user”。右键单击新创建的包“user”,然后单击“new”和“Java Class”。第一个类将被称为“User”:
现在你应该有一个新的文件,Java类,在你的用户包下,叫做User,其内容类似于以下内容:
package tutorial.user;public class User {
}
我们还需要另一个Java类,叫做“UserController”
,因此请按照之前的步骤创建Java类。接下来,我们需要创建一个名为“UserRepository”的接口。步骤与创建类类似,但你将点击接口而不是类:
我们拼图的最后一块是一个名为“Status”的Enum。因此,如前所述,在“user”包下创建Enum。我们将从编辑“User”类开始。我将先放代码,然后再解释它,这样你就可以将其复制粘贴到IDE中,并通过注释做笔记。
添加代码到项目中
tutorial/src/main/java/tutorial/user/User.java:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import java.util.Objects;@Entity
@Table(name = "users")
public class User {
private @Id @GeneratedValue long id;
private @NotBlank String username;
private @NotBlank String password;
private @NotBlank boolean loggedIn; public User() {
} public User(@NotBlank String username,
@NotBlank String password) {
this.username = username;
this.password = password;
this.loggedIn = false;
} public long getId() {
return id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public boolean isLoggedIn() {
return loggedIn;
} public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return Objects.equals(username, user.username) &&
Objects.equals(password, user.password);
} @Override
public int hashCode() {
return Objects.hash(id, username, password,
loggedIn);
} @Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", loggedIn=" + loggedIn +
'}';
}
}
从头开始:
@Entity:
此注释允许我们的类被序列化和反序列化为JSON。它还允许我们在之前创建的数据库中创建表。@Table(name = “users”)
: 此注释告诉程序调用表“users”。- 变量:每个变量代表我们数据库中的一个字段。因此,在我们的数据库表中将包含记录。每个记录都将有一个id字段(long)、一个用户名字段(String)、一个密码字段(String)和一个loggedIn字段(boolean)。
- @Id: 这将id变量设置为数据库中的id字段。数据库记录使用id。
- @GeneratedValue: 这告诉程序在添加新记录时生成id值,这样我们就不必担心意外覆盖数据库中的记录。
- @NotBlank: 这确保我们无法将不具有名称、密码或loggedIn值的记录添加到数据库中。
- User(@NotBlank String username, @NotBlank String password): 这是一个构造函数。它是在创建此类对象时运行的函数。它需要一个用户名和密码,然后将用户名和密码设置为所给定的用户名和密码,并将loggedIn的值设置为false,这样当用户的个人资料被添加时,用户不会自动登录。
- Getter和Setter:这些用于设置和返回我们类中的各种变量。这些的原因与Java和数据处理的首选方法有关,与Spring框架无关。
equals(Object o)
: 当我们想要将传递给程序的对象与来自我们的数据库的对象进行比较时,将使用此函数。hashCode()
: 此函数用于生成对象的哈希值。toString():
此函数,正如名称所暗示的那样,用于以字符串形式返回有关我们类对象的某些信息。这在调试期间特别有用。我在最初创建这个程序时经常使用它,因为我在将对象彼此比较时遇到了问题。接下来我们将要处理的文件是UserRepository。
tutorial/src/main/java/tutorial/user/UserRepository.java:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
我承认这个文件看起来有些空洞,特别是与User.java文件相比,但不要让简单的外表欺骗你,它是一个非常强大的文件。框架在幕后做了很多工作,所以你不一定能看到它,但是这个文件将允许我们与我们的数据库进行接口交互。
- @Repository: 这告诉Spring这是用于我们的数据库管理功能的接口。
- JpaRepository<user, long="">: 这将接口链接到我们的数据库表。我们告诉它查看我们的User表,并告诉它我们id字段的值是Long类型。 </user,>
接下来是我们的Status枚举:
tutorial/src/main/java/tutorial/user/Status.java:
public enum Status {
SUCCESS,
USER_ALREADY_EXISTS,
FAILURE
}
这个枚举没有什么特别之处,它将用作向用户提供反馈,以告知他们当前的操作是成功还是失败。
最后是UserController类:
tutorial/src/main/java/tutorial/user/UserController.java:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.List;@RestController
public class UserController {
@Autowired
UserRepository userRepository; @PostMapping("/users/register")
public Status registerUser(@Valid @RequestBody User newUser) {
List<User> users = userRepository.findAll(); System.out.println("New user: " + newUser.toString()); for (User user : users) {
System.out.println("Registered user: " + newUser.toString()); if (user.equals(newUser)) {
System.out.println("User Already exists!");
return Status.USER_ALREADY_EXISTS;
}
} userRepository.save(newUser);
return Status.SUCCESS;
} @PostMapping("/users/login")
public Status loginUser(@Valid @RequestBody User user) {
List<User> users = userRepository.findAll(); for (User other : users) {
if (other.equals(user)) {
user.setLoggedIn(true);
userRepository.save(user);
return Status.SUCCESS;
}
} return Status.FAILURE;
} @PostMapping("/users/logout")
public Status logUserOut(@Valid @RequestBody User user) {
List<User> users = userRepository.findAll(); for (User other : users) {
if (other.equals(user)) {
user.setLoggedIn(false);
userRepository.save(user);
return Status.SUCCESS;
}
} return Status.FAILURE;
} @DeleteMapping("/users/all")
public Status deleteUsers() {
userRepository.deleteAll();
return Status.SUCCESS;
}
}
这是你的程序的业务类。在这里,我们处理发送到我们程序的请求。
- @RestController: 这告诉Spring这将用于控制我们API的功能和发送到我们程序的任何请求。
- @Autowired: 这只是处理我们的UserRepository的代码注入,以便我们不必设置构造函数。
- @PostMapping(“/users/register”): 这告诉Spring,每当我们的程序接收到一个Post请求到/users/register,就应该调用registerUser函数,然后将接收到的数据传递给registerUser函数。
- registerUser(@Valid @RequestBody User newUser): 这个函数需要一个类似于我们的User类的有效的json对象,这样我们就可以确保我们接收到的对象在我们的程序中是可用的。该函数首先创建了一个名为users的用户列表,用于在我们的数据库中存储用户。请注意“userRepository.findAll()”的部分,它查询我们的数据库并返回我们当前保存的所有用户。然后函数遍历数据库中的所有用户并将其与我们刚刚获得的用户进行比较,这样可以确保用户尚未成为我们数据库的一部分。如果它发现该用户已经在我们的数据库中,则返回Status.USER_ALREADY_EXITS。否则,它将新用户添加到我们的数据库中,并返回状态SUCCESS。
- loginUser(@Valid @RequestBody User user): 与前面一样,此函数接收一个用户对象,然后将其与我们数据库中的用户进行比较。如果发现该用户在我们的数据库中,则将其loggedIn变量设置为true,以表示我们的用户刚刚登录。如果用户成功登录,则返回状态SUCCESS。如果失败,则返回状态FAILURE。
- logUserOut(@Valid @RequestBody User user): 此函数类似于loginUser,只是这次我们将用户的loggedIn变量设置为false,以表示该用户当前未登录。如果注销成功,我们将返回状态SUCCESS,否则返回状态FAILURE。
- @DeleteMapping(“/users/all”): 这告诉Spring,每当发出Delete请求到/users/all时,就调用以下函数。
- deleteAll(): 此函数只是删除我们数据库中的所有用户。在测试期间拥有此函数非常有用。
这就是我们程序的全部内容,现在你应该能够运行程序并通过终端与其进行交互。
测试我们的程序
让我们首先测试是否可以将新用户注册到我们的数据库中,打开终端并将以下代码粘贴到终端中:
curl -H "Content-Type: application/json" -X POST -d '{
"username": "test",
"password": "test"
}' http://localhost:8080/users/register
这个命令向我们的程序发送一个带有json包的Post请求。json包含用户名和密码,你可能已经注意到,在我们的User类构造函数中,我们特别要求用户名和密码。我们特别将此Post请求发送到http://localhost:8080/users/register.我们的程序正在本地主机上运行,端口为8080,并且我们有一个PostMapping在监听“/users/register”时发送的数据。如果我们在终端中运行这个命令(同时我们的应用程序在后台运行),我们将看到类似于这样的东西:
请注意,我们收到了一个字符串,内容为“SUCCESS”,这意味着我们的应用程序接收到了新用户并将其添加到了我们的数据库中。当我们再次运行相同的命令时会发生什么?
这次我们收到了一个“USER_ALREADY_EXISTS”的消息,所以我们的程序确保不会将同一用户添加到我们的数据库中。接下来,让我们看看是否可以登录我们的新用户,你可以在终端中运行以下命令:
curl -H "Content-Type: application/json" -X POST -d '{
"username": "test",
"password": "test"
}' http://localhost:8080/users/login
与之前一样,它向“/users/login”发送一个带有我们用户凭据的json对象,我们程序的一个专门处理用户登录的部分。当我们运行该命令时,它看起来像这样:我们收到了“SUCCESS”的消息,所以现在我们的用户已经登录了,但如果我们发送了错误的用户凭据会发生什么?通过运行此命令来测试:
curl -H "Content-Type: application/json" -X POST -d '{
"username": "hello",
"password": "world"
}' http://localhost:8080/users/login
我们从未注册该用户,因此该用户不应该在我们的数据库中,因此不应该能够登录我们的应用程序。就像这样:
如上所示,我们的程序发送回“FAILURE”消息,表示它能够阻止未注册的用户登录。这就是我们的整个程序。我们使用Java和Spring创建了用户注册和身份验证系统。如果你想清理自己的数据库,可以使用此命令清除数据库:
curl -X DELETE http://localhost:8080/users/all
清理
如果你还想从系统中删除用户数据库,那么可以这样做。打开终端并键入
mysql -u root -p
然后输入你的密码。现在,你应该回到MySQL终端,现在如果你想删除“users”数据库,可以运行此命令:
DROP DATABASE users;
在我们结束本教程之前,还有一件事要做,你可以查看你的API设置,如果打开浏览器选项卡,然后转到:http://localhost:8080/api-docs 这将打开一些有关你的API的JSON。
此项目的完整代码可在bitbucket中找到。
译自:https://medium.com/javarevisited/a-simple-user-authentication-api-made-with-spring-boot-4a7135ff1eca
评论(0)