从零到跑通:Spring Boot 入门实战全记录
去年公司要做一个内部管理平台,时间紧任务重。作为后端组的主力开发之一,我被指派用 Spring Boot 搭建后端服务。当时我们团队里对 Spring Boot 了解不深,虽然都知道它“简化了 Spring 配置”、“内嵌 Tomcat”,但真要上手时还是遇到不少困惑。
作为一个有五年经验的后端工程师,我经历过从传统 XML 配置的 Spring MVC 项目一步步过渡到 Spring Boot 的过程。这篇分享是我亲身经历的一次快速上手实践,希望能帮你在 60 分钟内真正理解 Spring Boot 是怎么一回事,并搭建起自己的第一个工程。
开始前的准备:我们需要做什么?

目标是搭建一个简单的 API 服务:支持用户注册、登录和查看个人信息的功能。数据存储使用 MySQL。我们的重点在于:
- 快速初始化 Spring Boot 工程
- 基本结构与注解使用
- 数据库操作(JPA)
- 接口开发与测试
- 踩坑点及解决方案
工具链:
- Java 17
- IntelliJ IDEA 2023.x
- Maven 3.8.x
- MySQL 8.x
- Postman 测试接口
环境初始化:第一次用 Spring Initializr 创建项目


一开始我去了 start.spring.io 页面,这是最推荐的官方入口。选择以下选项:
- Project: Maven
- Language: Java
- Spring Boot Version: 3.x(建议当前稳定版本)
- Group & Artifact: 自定义(比如 com.example.demo)
- Dependencies:
- Spring Web
- Spring Data JPA
- MySQL Driver
- Lombok(可选)
点击 "Generate" 后下载 zip 包,导入到 IDE 中就可以开始写了。
这里有个小插曲:刚开始同事说他之前用 Spring Boot 2.x 创建的项目没问题,但我这边用上了 3.x 结果连 MySQL 依赖都要自己手动配驱动类名(因为 Spring Boot 3 升级了 Jakarta EE 9,默认去掉了 javax 包名)——这点我们在后面配置时会提到。
项目结构初探:简单但很规范
引入后的结构非常干净:
src/
└── main/
├── java/
│ └── com.example.demo/
│ ├── DemoApplication.java
│ └── controller/
│ └── model/
│ └── repository/
│ └── service/
└── resources/
├── application.properties
└── data.sql
这个结构遵循的是典型的 Spring Boot 多层架构风格:
- Controller 层处理 HTTP 请求
- Service 层业务逻辑
- Repository 是数据访问层
- Model 映射实体类
- resources 用于放配置和初始化 SQL
接下来我们先搭数据库。
数据库设计:简约而不简单
我们只需要一张用户表来实现基本功能,字段包括:
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY,
`username` varchar(50) NOT NULL UNIQUE,
`password` varchar(255) NOT NULL,
`created_at` datetime DEFAULT CURRENT_TIMESTAMP
);
注意几点:
- 用户名唯一性通过数据库层面保证
- 密码建议哈希加密,我们暂时先存明文做演示
- created_at 使用默认值减少代码处理负担
接着,在 resources 目录下创建 data.sql 文件,用于插入初始数据:
INSERT INTO user (username, password) VALUES ('admin', '123456');
这样启动应用的时候会自动执行这个文件,可以方便调试。
配置数据库连接:Spring Boot 真的省事了吗?
打开 application.properties 文件,添加以下配置:
spring.datasource.url=jdbc:mysql://localhost:3306/your_db_name?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

⚠️ 如果你也是 Spring Boot 3.x 的用户,一定要指定 driver-class-name!不然会提示找不到 JDBC 类。
然后加上 JPA 的自动建表设置(可选):
spring.jpa.hibernate.ddl-auto=update
这个时候我犯了一个错误:之前习惯写成 hibernate.hbm2ddl.auto=update,结果发现没生效。这提醒我们要以 Spring Boot 提供的属性优先为准。
编写实体类:Lombok 救命
在 model 包下新建 User 实体:
@Entity
@Table(name = "user")
@Data // 来自 Lombok,自动提供 getter/setter/toString
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
private String password;
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
}
用到了几个关键注解:
@Entity: 声明这是一个持久化实体@Table: 对应数据库表名@Id,@GeneratedValue: 主键策略@Column: 字段映射,可以配置是否唯一、是否可空等- Lombok 的
@Data和构造方法注解让代码简洁很多
数据访问层:JPA 让你少些一半代码
Repository 接口继承 JpaRepository 就行:
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
JPA 支持方法命名规则自动生 SQL 查询,比如这里的 findByUsername 方法就不用手动写 SQL。
⚠️ 注意返回值用了 Optional,这样在调用时能有效规避 NPE 问题。我在早期开发时就因为忽视 null 检查出过 bug。
Service 层:别急着写,先想清楚职责
Service 层主要封装业务逻辑,比如用户注册流程中的验证、密码加密等。这里先做个简单示例:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Optional<User> getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
public User registerUser(String username, String password) {
if (userRepository.findByUsername(username).isPresent()) {
throw new RuntimeException("用户名已存在");
}
User user = new User();
user.setUsername(username);
user.setPassword(password); // 这里应该加盐加密
return userRepository.save(user);
}
}
这段代码可能你会觉得太简单,但它其实包含了几个值得思考的设计点:
- 是否该在 Service 中抛异常?答案是肯定的,业务异常要有统一处理方式
- 密码直接保存明文不可取,生产环境应该用 BCryptPasswordEncoder 加密
- 返回类型为 Entity 是否合适?后续考虑封装 DTO 减少暴露敏感字段
控制器层:RESTful API 设计原则
现在我们来编写控制器:
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{username}")
public ResponseEntity<?> getUser(@PathVariable String username) {
Optional<User> user = userService.getUserByUsername(username);
return user.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
@PostMapping("/register")
public ResponseEntity<User> registerUser(@RequestBody RegisterRequest request) {
User savedUser = userService.registerUser(request.getUsername(), request.getPassword());
return ResponseEntity.ok(savedUser);
}
}
对应的请求体:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RegisterRequest {
private String username;
private String password;
}
有几个注意事项:
- 使用 RESTful 风格设计 URL,资源名词复数形式
- GET 和 POST 动词准确体现语义
- 统一响应格式?这个看团队规范,初期可以直接返回对象
- 控制器中尽量不要出现复杂逻辑,转而交给 Service
启动项目:别忘了检查日志
运行 DemoApplication 启动类之后,控制台输出一堆信息。正常情况下你应该能看到类似如下内容:
Tomcat started on port(s): 8080 (http)
Started DemoApplication in 3.2 seconds (process running for 3.8)
这个时候我们可以用 Postman 测试一下接口。
示例请求:
注册新用户
POST /api/users/register
{
"username": "testuser",
"password": "123456"
}
获取用户信息
GET /api/users/testuser
踩过的坑和解决办法总结
这一路上踩了不少坑,都是实际开发中最常见的:
1. Spring Boot 启动慢
- 问题现象:首次运行特别慢,等好久才启动成功
- 解决方案:
- 设置
debug=true查看具体阻塞步骤 - 升级内存配置
-Xms512m -Xmx1024m - 拆分大项目为多个模块
- 设置
2. JPA 自动建表失败
- 问题现象:表没有自动生成或更新
- 解决方案:
- 检查 DDL-AUTO 配置是否正确
- 检查实体字段是否都有正确注解
- 确保数据库有足够权限
3. MySQL 时区报错
- 问题现象:连接数据库时报错,提示时区未设置
- 解决方案:
- 在 JDBC URL 中显式加上
serverTimezone=UTC - 或者改为
Asia/Shanghai(根据本地时区)
- 在 JDBC URL 中显式加上
4. No session found in request 异常
- 出现场景:在懒加载字段读取时报错
- 解决方案:
- 不要在 Controller 层直接返回含懒加载字段的实体
- 用 DTO 手动封装需要的数据,避免引发 Hibernate LazyInitializationException
总结:这套方案带来了什么收益?
从项目上线到现在已经三个月了,这套基于 Spring Boot 的架构帮助我们实现了以下几个核心价值:
快速迭代能力提升
- 新增接口平均只需 30 分钟完成开发+测试
- 模块化清晰,代码易维护
良好的可扩展性
- 日后可以轻松接入 Redis 缓存、定时任务、日志监控等功能
- 完全具备向微服务迁移的能力
运维成本低
- 内嵌 Tomcat 省去了部署中间件的麻烦
- 只需打个 jar 包就能跑,便于 CI/CD
我的 Spring Boot 学习建议
如果你是刚入门的新手,或者正在考虑转型后端,下面是我的一些建议:
✅ 初学者建议:
- 不要一开始追求完美架构,先把基础功能跑起来
- 多动手改代码,别只看文档不实操
- 遇到错误时多看日志,培养定位问题的能力
🚧 中进阶方向:
- 熟悉 Spring Boot 的自动化配置原理
- 掌握 Actuator 监控、Swagger 文档生成
- 理解自动装配机制,尝试写一个 Starter
🔐 安全与性能:
- 生产环境务必启用 HTTPS
- 接口参数校验要用 Bean Validation 注解
- 关键路径考虑限流、防止暴力破解
结语:Spring Boot 的魅力在于“恰到好处”
写到这里,突然想起最初用 XML 配置 Spring 的时候,每次新增一个 bean 就要改好几个 xml 文件,而现在只需一个 @Service 注解即可。
Spring Boot 最大的价值不是让你少写代码,而是帮你屏蔽了冗余配置,把注意力集中在真正的业务开发上。
如果你能在 60 分钟内跟着这篇文章从头到尾跑一遍,相信你会发现,所谓“框架”,不过是让我们专注解决问题的方式而已。
下次我们还可以聊聊如何在 Spring Boot 中优雅地写单元测试、使用 AOP、整合 Kafka 等话题。希望我们能一起成长!
作者:张工 | 5年Java后端工程师 | 当前专注于企业级系统架构
如果你喜欢这类实战导向的技术文章,欢迎点赞收藏,也可以留言告诉我你想学的内容~

评论 0