Spring Boot新手入门:从零搭建Java Web项目并连接MySQL数据库
2026/8/13 21:26:07 网站建设 项目流程

在实际开发中,很多新手开发者(常被戏称为“菜鸟”)在入门时,面对海量的技术栈、复杂的配置和层出不穷的报错信息,常常感到无从下手。一个看似简单的“Hello World”项目,背后可能涉及环境变量、依赖管理、构建工具、运行时配置等一系列环节,任何一个环节出错都可能导致程序无法运行。本文将以一个典型的Java Web项目为例,模拟一位新手从零开始搭建一个Spring Boot应用,并连接MySQL数据库的完整过程。我们将不假设任何前置知识,而是从一个空文件夹开始,逐步解释每一个命令、每一个配置项、每一个注解的作用,并重点拆解在这个过程中最可能遇到的“坑”及其排查思路。通过这篇教程,你将不仅学会如何搭建一个项目,更重要的是理解每一步背后的“为什么”,以及当程序不按预期运行时,应该从哪里开始“发问”和排查。

1. 理解项目骨架:Spring Boot 与 Maven 的核心作用

在开始写代码之前,我们需要先理解将要使用的工具链。很多新手会直接复制粘贴命令和配置,却不明白这些工具解决了什么问题,导致一旦出现版本冲突或配置错误就束手无策。

1.1 为什么选择 Spring Boot?

Spring Boot 的核心价值是“约定大于配置”。在传统的 Spring MVC 项目中,你需要手动配置大量的 XML 文件或 Java Config 来定义 DispatcherServlet、视图解析器、数据源、事务管理器等。Spring Boot 通过自动配置(Auto-Configuration)和起步依赖(Starter Dependencies)将这些繁琐的配置标准化。

  • 起步依赖:例如,当你引入spring-boot-starter-web,它不仅引入了 Spring MVC 的库,还内嵌了 Tomcat 服务器,你无需再单独下载和配置 Tomcat。
  • 自动配置:Spring Boot 会根据你引入的 jar 包,自动推断并配置你需要的 Bean。比如,当 classpath 下存在 MySQL 驱动和spring-boot-starter-data-jpa时,它会尝试自动配置一个DataSource

对于新手来说,这极大地降低了入门门槛,让你可以更专注于业务逻辑,而不是基础设施的搭建。

1.2 Maven 是做什么的?

Maven 是一个项目构建和依赖管理工具。你可以把它想象成一个项目的“管家”:

  1. 依赖管理:在pom.xml文件中声明你的项目需要哪些第三方库(如 Spring、MySQL驱动、Jackson等),Maven 会自动从中央仓库下载这些库及其依赖项,并解决版本冲突。
  2. 构建生命周期:它定义了一套标准的构建流程,如编译(compile)、测试(test)、打包(package)、安装(install)等。你只需要执行mvn clean package,它就会按顺序执行清理、编译、运行测试、打包成 jar/war 文件。
  3. 项目结构标准化:Maven 约定了一套标准的目录结构(如src/main/java,src/main/resources),这有利于团队协作和工具集成。

没有 Maven,你需要手动下载几十个 jar 包,并确保它们版本兼容,这几乎是不可能完成的任务。

2. 环境准备与项目初始化

这是最容易出错的阶段。环境没配好,后面所有步骤都可能失败。

2.1 基础环境检查清单

在开始之前,请确保你的机器上已经安装了以下软件,并且版本符合要求。打开你的终端(Windows 用 CMD 或 PowerShell,Mac/Linux 用 Terminal)逐一验证。

软件检查命令预期输出(示例)作用
Java JDKjava -versionopenjdk version “17.0.10” 2024-01-16项目的运行环境,Spring Boot 3.x 需要 JDK 17+。
Mavenmvn -vApache Maven 3.9.6项目构建和依赖管理工具。
MySQLmysql --versionmysql Ver 8.0.36 for Linux on x86_64本项目使用的数据库。你也可以使用 Docker 快速启动一个。
Git (可选)git --versiongit version 2.43.0版本控制,方便管理代码和回溯。

如果任何一条命令显示“不是内部或外部命令”或“command not found”,你需要先安装对应的软件。

常见坑点 1:JAVA_HOME 环境变量未配置或配置错误

  • 现象java -version可以运行,但mvn -v报错,提示JAVA_HOME未设置。
  • 原因:Maven 需要依赖JAVA_HOME环境变量来定位 JDK 的安装位置。
  • 解决
    1. 找到你的 JDK 安装路径(例如C:\Program Files\Java\jdk-17)。
    2. 在系统环境变量中新建一个变量,名称为JAVA_HOME,值为上述路径。
    3. Path变量中新增%JAVA_HOME%\bin
    4. 重新打开终端,再次执行mvn -v

2.2 使用 Spring Initializr 快速生成项目

手动创建pom.xml和目录结构容易出错,推荐使用 Spring 官方提供的 start.spring.io 来生成项目骨架。

  1. 访问网站:打开浏览器,进入https://start.spring.io
  2. 选择参数
    • Project: Maven
    • Language: Java
    • Spring Boot: 选择最新的稳定版(如 3.2.3)
    • Project Metadata:
      • Group:com.example(通常用公司域名倒写)
      • Artifact:demo(你的项目名)
      • Name:demo
      • Description:Demo project for Spring Boot
      • Package name:com.example.demo(会自动生成)
    • Packaging: Jar (Spring Boot 推荐的可执行 Jar)
    • Java: 17 (与你的 JDK 版本一致)
  3. 添加依赖:在 Dependencies 区域,点击 “ADD DEPENDENCIES”,搜索并添加:
    • Spring Web(用于构建 Web API)
    • Spring Data JPA(用于数据库操作)
    • MySQL Driver(MySQL 数据库连接驱动)
    • Lombok(可选,用于简化 Java Bean 的 Getter/Setter 代码)
  4. 生成项目:点击页面下方的 “GENERATE” 按钮,下载一个名为demo.zip的压缩包。
  5. 解压并导入:将压缩包解压到你的工作目录,然后用你熟悉的 IDE(如 IntelliJ IDEA 或 VS Code)打开这个文件夹。

关键文件结构预览

demo/ ├── pom.xml # Maven 项目核心配置文件,定义了依赖和构建方式 ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── demo/ │ │ │ └── DemoApplication.java # Spring Boot 主启动类 │ │ └── resources/ │ │ ├── application.properties # 配置文件(我们将在这里配置数据库) │ │ └── static/ # 存放静态资源(如 CSS, JS) │ └── test/ # 测试代码目录 └── target/ # Maven 编译输出目录(初始不存在)

3. 配置数据库与编写第一个实体类

项目骨架有了,接下来要让程序能连接到数据库,并定义我们的数据表结构。

3.1 配置 MySQL 数据库连接

打开src/main/resources/application.properties文件。这个文件是 Spring Boot 默认的配置文件。我们将使用application.yml,因为它结构更清晰。你可以将application.properties重命名为application.yml,或者直接新建一个application.yml文件。

application.yml中添加以下配置:

spring: datasource: url: jdbc:mysql://localhost:3306/springboot_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: your_password # 替换为你的 MySQL root 密码 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update # Hibernate 自动更新表结构 show-sql: true # 在控制台打印执行的 SQL 语句,便于调试 properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect

配置项解释

  • spring.datasource.url: 数据库连接字符串。localhost:3306是 MySQL 默认地址和端口。springboot_demo是数据库名,如果不存在,JPA 在首次连接时会尝试创建(取决于权限)。serverTimezone参数非常重要,不设置可能导致时间错误。
  • spring.jpa.hibernate.ddl-auto: 这个参数控制着表结构的自动生成策略。
    • create: 每次启动都会删除旧表,创建新表。(数据会丢失!
    • update: 启动时检查表结构,如果不同则更新,不会删除数据。(开发环境常用
    • validate: 仅验证表结构是否匹配,不修改。
    • create-drop: 类似create,但在 SessionFactory 关闭时删除表。
    • none: 不执行任何操作。(生产环境必须使用这个,并通过 Flyway/Liquibase 管理数据库变更

注意:在生产环境中,绝对不要使用update。表结构的变更必须通过数据库迁移脚本(如 Flyway)来管理,以保证变更的可控和可回滚。

常见坑点 2:数据库连接失败

  • 现象:启动应用时,控制台报错Access denied for user ‘root‘@‘localhost‘Unknown database ‘springboot_demo‘
  • 排查
    1. 检查密码:确认application.yml中的密码是否正确。
    2. 检查数据库是否存在:登录 MySQL (mysql -u root -p),执行SHOW DATABASES;查看是否有springboot_demo。如果没有,执行CREATE DATABASE springboot_demo;创建它。
    3. 检查用户权限:确保你使用的 MySQL 用户(如 root)有权限访问localhost和操作springboot_demo数据库。
    4. 检查 MySQL 服务:确保 MySQL 服务正在运行。

3.2 定义实体类 (Entity)

实体类对应数据库中的一张表。我们在src/main/java/com/example/demo/目录下新建一个entity包,并在其中创建User.java

package com.example.demo.entity; import jakarta.persistence.*; import lombok.Data; import java.time.LocalDateTime; @Entity // 标记这是一个 JPA 实体类,对应数据库中的一张表 @Table(name = “user”) // 指定表名,如果省略则默认使用类名 @Data // Lombok 注解,自动生成 getter, setter, toString, equals, hashCode 方法 public class User { @Id // 标记为主键 @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增策略(MySQL的AUTO_INCREMENT) private Long id; @Column(nullable = false, unique = true) // 对应数据库字段,非空且唯一 private String username; @Column(nullable = false) private String password; private String email; @Column(name = “created_at”) // 指定数据库中的列名 private LocalDateTime createdAt; @PrePersist // JPA 生命周期回调:在数据持久化(插入)之前执行 protected void onCreate() { createdAt = LocalDateTime.now(); // 自动设置创建时间 } }

代码解释

  • @Entity,@Table,@Id,@GeneratedValue,@Column都是 JPA(Java Persistence API)的标准注解,用于完成对象与关系数据库的映射(ORM)。
  • @Data是 Lombok 的注解。如果没有它,你需要手动为每个字段编写gettersetter方法。使用 Lombok 可以让代码更简洁。确保你的 IDE 安装了 Lombok 插件,否则编译时可能会报错找不到getter/setter
  • LocalDateTime是 Java 8 引入的日期时间 API,比旧的DateCalendar更好用。
  • @PrePersist是一个回调方法,在数据被插入数据库前,自动为createdAt字段赋值为当前时间。

4. 创建数据访问层与业务逻辑

有了实体,我们需要一个“仓库”来存取它。在 Spring Data JPA 中,这个“仓库”叫Repository

4.1 创建 Repository 接口

src/main/java/com/example/demo/下新建一个repository包,创建UserRepository.java接口。

package com.example.demo.repository; import com.example.demo.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository // 标记这是一个数据访问层组件,可省略,因为 JpaRepository 已经包含了 public interface UserRepository extends JpaRepository<User, Long> { // 根据用户名查找用户 Optional<User> findByUsername(String username); // 检查用户名是否存在 boolean existsByUsername(String username); // 根据邮箱查找用户 Optional<User> findByEmail(String email); }

神奇之处:你不需要实现这个接口!Spring Data JPA 会根据方法名(如findByUsername)在运行时自动生成实现。这遵循了“约定大于配置”的原则。

  • extends JpaRepository<User, Long>:继承的泛型中,User是实体类型,Long是主键类型。
  • Optional<T>:是 Java 8 引入的容器类,用于避免null检查。如果查不到数据,返回Optional.empty()而不是null,更安全。

4.2 创建服务层 (Service)

服务层负责业务逻辑。在src/main/java/com/example/demo/下新建service包,创建UserService.java

package com.example.demo.service; import com.example.demo.entity.User; import com.example.demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; @Service // 标记这是一个业务逻辑层组件 public class UserService { @Autowired // 自动注入 UserRepository 实例 private UserRepository userRepository; /** * 用户注册 * @param username 用户名 * @param password 明文密码 * @param email 邮箱 * @return 注册成功的用户对象 * @throws RuntimeException 如果用户名已存在 */ public User register(String username, String password, String email) { // 1. 检查用户名是否已存在 if (userRepository.existsByUsername(username)) { throw new RuntimeException(“用户名已存在”); } // 2. 创建用户对象 User user = new User(); user.setUsername(username); // 密码不应明文存储,这里使用简单的 MD5 哈希(生产环境应用更安全的算法,如 BCrypt) user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8))); user.setEmail(email); // createdAt 字段由 @PrePersist 自动设置 // 3. 保存到数据库 return userRepository.save(user); } /** * 用户登录(简单演示,生产环境需用安全框架) * @param username 用户名 * @param password 明文密码 * @return 登录成功的用户对象 * @throws RuntimeException 如果用户名或密码错误 */ public User login(String username, String password) { // 1. 根据用户名查找用户 User user = userRepository.findByUsername(username) .orElseThrow(() -> new RuntimeException(“用户不存在”)); // 2. 验证密码 String inputPasswordHash = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)); if (!inputPasswordHash.equals(user.getPassword())) { throw new RuntimeException(“密码错误”); } // 3. 返回用户信息(生产环境应返回 Token) return user; } }

业务逻辑要点

  1. 依赖注入@Autowired让 Spring 容器自动将UserRepository的实现实例赋值给userRepository字段。
  2. 密码处理绝对不要将明文密码存入数据库。这里使用了 Spring 自带的DigestUtils.md5DigestAsHex进行简单的哈希。注意:MD5 已被证明不安全,生产环境必须使用BCryptPasswordEncoder等加盐的强哈希算法。
  3. 异常处理:使用RuntimeException抛出业务异常。在真实的控制器层,我们需要捕获这些异常并转换为友好的 HTTP 状态码和错误信息返回给前端。

5. 创建 Web API 控制器

服务层写好了,现在需要暴露 HTTP 接口供前端调用。我们创建控制器(Controller)。

src/main/java/com/example/demo/下新建controller包,创建UserController.java

package com.example.demo.controller; import com.example.demo.entity.User; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController // 等同于 @Controller + @ResponseBody,直接返回 JSON 数据 @RequestMapping(“/api/users”) // 定义该控制器下所有接口的基础路径 public class UserController { @Autowired private UserService userService; @PostMapping(“/register”) public User register(@RequestBody RegisterRequest request) { // @RequestBody 表示从 HTTP 请求体中解析 JSON 数据 return userService.register(request.getUsername(), request.getPassword(), request.getEmail()); } @PostMapping(“/login”) public User login(@RequestBody LoginRequest request) { return userService.login(request.getUsername(), request.getPassword()); } // 内部静态类,用于接收请求体 static class RegisterRequest { private String username; private String password; private String email; // 省略 getter 和 setter (实际开发中需加上,或使用 Lombok @Data) public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } // ... 其他 getter/setter } static class LoginRequest { private String username; private String password; // ... getter/setter } }

控制器要点

  • @RestController:标记这个类是 Web 控制器,并且其所有方法的返回值都会直接写入 HTTP 响应体,通常转换为 JSON。
  • @RequestMapping(“/api/users”):为该控制器下的所有请求映射添加一个前缀/api/users。所以注册接口的完整路径是POST /api/users/register
  • @PostMapping:指定该方法处理 HTTP POST 请求。
  • @RequestBody:将请求体中的 JSON 数据绑定到方法参数对象上。

6. 运行与验证

所有代码都已就绪,现在是验证成果的时候了。

6.1 启动应用程序

找到主启动类DemoApplication.java,其内容应该类似:

package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication // 核心注解,开启组件扫描、自动配置等 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }

在你的 IDE 中,右键点击这个类,选择 “Run DemoApplication”。或者在项目根目录下打开终端,执行 Maven 命令:

mvn spring-boot:run

如果一切顺利,你将在控制台看到 Spring Boot 的启动日志,最后一行应该是类似这样的信息:

Started DemoApplication in 3.456 seconds (process running for 3.789)

同时,由于我们配置了show-sql: true,当 JPA 操作数据库时,你会在日志中看到生成的 SQL 语句。

6.2 使用 API 测试工具进行测试

Spring Boot 应用默认运行在8080端口。我们使用curl命令或 Postman 等工具来测试 API。

1. 测试用户注册

curl -X POST http://localhost:8080/api/users/register \ -H “Content-Type: application/json” \ -d ‘{ “username”: “testuser”, “password”: “mypassword123”, “email”: “test@example.com” }’

预期成功响应(JSON格式):

{ “id”: 1, “username”: “testuser”, “password”: “e10adc3949ba59abbe56e057f20f883e”, // MD5 哈希后的密码 “email”: “test@example.com”, “createdAt”: “2024-05-27T10:30:00” }

2. 测试重复注册: 再次发送相同的注册请求。预期错误响应:应用会抛出RuntimeException(“用户名已存在”),Spring Boot 默认会返回一个包含错误堆栈的 JSON(状态码 500)。在生产环境中,我们需要全局异常处理来返回更友好的错误信息。

3. 测试用户登录

curl -X POST http://localhost:8080/api/users/login \ -H “Content-Type: application/json” \ -d ‘{ “username”: “testuser”, “password”: “mypassword123” }’

预期成功响应:返回用户信息(不含密码哈希则更佳)。

4. 测试密码错误登录

curl -X POST http://localhost:8080/api/users/login \ -H “Content-Type: application/json” \ -d ‘{ “username”: “testuser”, “password”: “wrongpassword” }’

预期错误响应:抛出RuntimeException(“密码错误”)

6.3 验证数据库

登录 MySQL,查看数据是否真的被写入。

mysql -u root -p USE springboot_demo; SELECT * FROM user;

你应该能看到一条usernametestuser的记录,password字段是哈希值。

7. 常见问题深度排查指南

即使按照教程一步步操作,你也可能会遇到问题。以下是基于这个项目的系统性排查路径。

7.1 应用启动失败

问题现象可能原因检查点与解决方案
APPLICATION FAILED TO START1. 配置错误(如数据库连接失败)。
2. 依赖冲突。
3. 端口被占用。
1.仔细阅读控制台日志:Spring Boot 的启动失败信息通常非常详细,会直接指出哪个 Bean 创建失败、哪个配置项有问题。第一屏的红色错误信息是关键。
2.检查application.yml:缩进是否正确(YAML 对缩进敏感),数据库IP、端口、用户名、密码是否正确,数据库服务是否启动。
3.检查端口:如果报Port 8080 was already in use,可以修改server.port配置,或使用netstat -ano | findstr :8080(Windows) /lsof -i :8080(Mac/Linux) 找到占用进程并结束它。
ClassNotFoundExceptionNoClassDefFoundError1. 依赖未正确下载。
2. IDE 未正确导入 Maven 项目。
1. 在项目根目录执行mvn clean compile,观察是否下载依赖成功。
2. 在 IDE 中,右键点击pom.xml,选择 “Maven” -> “Reload Project”。
3. 检查本地 Maven 仓库(默认在~/.m2/repository)是否有损坏,可尝试删除相关依赖目录重新下载。
BeanCreationExceptionSpring 容器无法创建某个 Bean,通常是依赖注入失败或配置有误。1. 检查被@Autowired的字段对应的类是否被 Spring 管理(即是否有@Service,@Repository,@Component等注解)。
2. 检查是否存在多个同类型的 Bean 导致注入歧义(可使用@Qualifier指定)。

7.2 API 请求不通或报错

问题现象可能原因检查点与解决方案
404 Not Found1. 请求 URL 错误。
2. 控制器未扫描到。
1. 确认请求的 Method (GET/POST) 和 URL 与@RequestMapping,@GetMapping,@PostMapping定义的完全一致。
2. 确认控制器类所在的包在主启动类DemoApplication的同级或下级目录。Spring Boot 默认扫描主类所在包及其子包。
415 Unsupported Media Type请求头Content-Type不正确。对于接收@RequestBody的 POST 接口,必须设置Content-Type: application/json
400 Bad Request1. 请求体 JSON 格式错误。
2. 字段类型不匹配。
1. 使用 JSON 格式化工具检查 JSON 格式是否正确。
2. 检查请求体中的字段名和类型是否与控制器方法参数类中的定义一致。
500 Internal Server Error业务代码抛出未捕获的异常。1.查看控制台日志:这是最重要的线索,异常堆栈会打印出来。
2. 检查是否是数据库操作失败(如唯一约束冲突)。
3. 检查服务层UserService中抛出的RuntimeException

7.3 数据库相关问题

问题现象可能原因检查点与解决方案
表没有自动创建1.ddl-auto配置为nonevalidate
2. 数据库用户无建表权限。
3. 实体类@Entity注解缺失或包未被扫描。
1. 确认application.ymlddl-autoupdate
2. 检查 MySQL 用户权限。
3. 确认实体类在主启动类的扫描范围内。
字段名或类型与预期不符JPA 命名策略或@Column配置问题。1. 默认情况下,JPA 会将camelCase字段名转换为snake_case列名(如createdAt->created_at)。
2. 使用@Column(name = “my_column”)显式指定列名。
3. 查看控制台show-sql打印的建表语句。
中文乱码数据库、连接字符串或应用编码不统一。1. 确保数据库、表、字段的字符集为utf8mb4
2. 在 JDBC URL 中加上useUnicode=true&characterEncoding=utf-8
3. 确保应用代码文件编码为 UTF-8。

8. 从学习到生产:必须考虑的优化与安全

这个简单的 Demo 可以运行,但距离一个可上线的生产级应用还有很大差距。以下是几个关键的改进方向。

8.1 全局异常处理

目前业务异常直接抛出RuntimeException,会返回 500 错误和堆栈信息,这对用户不友好且不安全。我们需要一个全局异常处理器。

package com.example.demo.handler; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.HashMap; import java.util.Map; @RestControllerAdvice // 声明这是一个全局控制器异常处理类 public class GlobalExceptionHandler { @ExceptionHandler(RuntimeException.class) // 处理所有 RuntimeException @ResponseStatus(HttpStatus.BAD_REQUEST) // 返回 400 状态码 public Map<String, Object> handleBusinessException(RuntimeException e) { Map<String, Object> result = new HashMap<>(); result.put(“code”, 400); result.put(“message”, e.getMessage()); // 返回业务异常信息 result.put(“data”, null); // 生产环境不应返回堆栈信息 result.put(“error”, e.toString()); return result; } // 可以添加更多 @ExceptionHandler 来处理其他特定异常 }

8.2 密码安全升级

使用 BCrypt 替代 MD5。首先修改pom.xml,添加 Spring Security 的密码编码器依赖(即使你不用完整的 Security 功能)。

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>

然后在配置类或服务中创建PasswordEncoderBean。

package com.example.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }

最后修改UserService,注入并使用PasswordEncoder

@Service public class UserService { @Autowired private UserRepository userRepository; @Autowired private PasswordEncoder passwordEncoder; // 注入 BCrypt 编码器 public User register(String username, String password, String email) { // ... 检查用户名 ... User user = new User(); user.setUsername(username); // 使用 BCrypt 加密 user.setPassword(passwordEncoder.encode(password)); user.setEmail(email); return userRepository.save(user); } public User login(String username, String password) { User user = userRepository.findByUsername(username) .orElseThrow(() -> new RuntimeException(“用户不存在”)); // 使用 BCrypt 的 matches 方法验证 if (!passwordEncoder.matches(password, user.getPassword())) { throw new RuntimeException(“密码错误”); } return user; } }

8.3 配置分离与多环境

生产环境的数据库密码、密钥等敏感信息绝不能写在代码里。需要使用环境变量或外部配置文件。

  1. 创建多环境配置文件
    • application-dev.yml(开发环境)
    • application-prod.yml(生产环境)
  2. application.yml中指定激活的环境
    spring: profiles: active: @activatedProperties@ # 通常通过启动参数 -Dspring.profiles.active=prod 指定
  3. application-prod.yml中,使用环境变量或配置中心
    spring: datasource: url: ${DB_URL:jdbc:mysql://prod-db:3306/demo} username: ${DB_USER} password: ${DB_PASSWORD} # 从环境变量读取
  4. 启动时指定环境
    java -jar demo.jar --spring.profiles.active=prod

8.4 接口文档与单元测试

  • 接口文档:集成 Swagger/OpenAPI (springdoc-openapi-starter-webmvc-ui),自动生成 API 文档,便于前后端联调。
  • 单元测试:为UserService编写单元测试,使用@SpringBootTest@DataJpaTest,确保业务逻辑正确。这是保证代码质量的基础。

完成以上步骤,你不仅完成了一个 Spring Boot 应用的搭建,更走完了一个新手从“发问”到“入门”的完整认知闭环:理解了工具链的价值、掌握了配置的方法、实现了核心业务、学会了排查问题的路径,并了解了从演示代码到生产代码需要跨越的鸿沟。接下来,你可以尝试集成 Redis 做缓存、使用 MyBatis-Plus 简化 DAO 层、或者学习 Spring Security 构建完整的认证授权体系,每一步都遵循类似的“理解概念 -> 配置环境 -> 编写代码 -> 运行验证 -> 排查问题 -> 优化改进”的实践循环。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询