Spring Boot 项目开发全流程实战指南

Spring Boot 项目开发全流程实战指南:从 0 到 1 实现 CURD(含面试题)

📅 发布时间 :2026-01-11

🏷️ 标签 :Java, Spring Boot, 教程, 后端开发, RESTful

💡 摘要:本文专为 Java 初学者量身打造,手把手带你理解 Spring Boot 项目的标准开发流程。从 Entity 实体类定义,到 Controller 接口开放,全链路打通。包含超详细的代码注释、核心概念图解以及高频面试题。


📖 一、 引言:Spring Boot 开发在做什么?

很多新手在刚接触 Spring Boot 时,会被各种层级搞晕:Controller, Service, Mapper, Entity... 到底先写谁?谁调谁?

其实,Web 开发的核心流程就像餐厅的点餐流程:

  1. Controller (服务员):直接面对客人(前端),拿着菜单(接口文档),记录客人的需求(接收请求参数),把菜端给客人(返回响应数据)。
  2. Service (大厨):负责核心烹饪(业务逻辑)。比如把肉切好、炒熟。如果发现菜没了(异常),就告诉服务员。
  3. Mapper/Repository (采购员):只负责去仓库(数据库)拿原材料(增删改查数据),不负责烹饪。
  4. Entity (食材):就是在各个环节传递的数据对象(比如红烧肉)。

今天我们就来演示如何制作一道 "用户管理" 的菜。


🏗️ 二、 项目结构与开发顺序

一个标准的 Spring Boot 项目,通常包含以下层级(建议按此顺序编写):

  1. 📄 Entity (实体层):定义数据库表结构对应的 Java 类。
  2. 💾 Mapper/DAO (持久层):操作数据库的接口(MyBatis 或 JPA)。
  3. 🧠 Service (业务层):编写复杂的业务逻辑。
  4. 🌐 Controller (控制层):对外暴露 URL 接口。

💻 三、 代码实战:实现用户增删改查

我们将实现一个简单的用户管理功能。

3.1 第一步:Entity (食材准备)

实体类是数据的载体,直接对应数据库中的表。我们分两步来写:

1. 类定义与主键配置

首先定义类的主体结构,并配置好主键生成策略。

java 复制代码
package com.example.demo.entity;

import lombok.Data; // Lombok 插件,自动生成 getter/setter/toString
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

/**
 * 用户实体类
 * 对应数据库表:t_user
 */
@Data // Lombok 注解:自动生成 Getter, Setter, ToString, HashCode 等方法,省去手动编写
@Entity // JPA 注解:声明这是一个实体类,与数据库表映射
@Table(name = "t_user") // 指定对应的数据库表名为 t_user
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键 ID
     * @Id: 标识该属性为主键
     * @GeneratedValue: 指定主键生成策略,IDENTITY 表示使用数据库自增 (Auto Increment)
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // ... 下面继续添加其他字段

2. 业务字段定义

接下来,在 User 类中补充用户名、密码等业务字段。

java 复制代码
    /**
     * 用户名
     * @Column: 映射数据库字段属性
     * nullable = false: 数据库这一列不能为空
     * unique = true: 用户名必须唯一
     */
    @Column(nullable = false, unique = true, length = 50)
    private String username;

    /**
     * 密码 (实际开发中不能存明文,要存加密后的哈希值)
     */
    @Column(nullable = false, length = 100)
    private String password;

    /**
     * 邮箱
     */
    @Column(length = 100)
    private String email;

    /**
     * 创建时间
     * 用于记录这一条数据是什么时候插入生成的
     */
    @Column(name = "create_time")
    private Date createTime;
}

3.2 第二步:Mapper/Repository (仓库采购)

这里演示使用 Spring Data JPA,它非常强大,只需继承 JpaRepository 接口,基本的增删改查代码都不用自己写!

java 复制代码
package com.example.demo.repository;

import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * 用户持久层接口
 * 继承 JpaRepository<实体类类型, 主键类型>
 * 
 * 作用:这就是那个"采购员",Spring Boot 自动帮你实现好了去数据库拿数据的方法:
 * - save(User user): 保存或更新
 * - findById(Long id): 根据ID查询
 * - findAll(): 查询所有
 * - deleteById(Long id): 根据ID删除
 */
@Repository // 标记这是持久层组件,Spring 会把它放入容器管理
public interface UserRepository extends JpaRepository<User, Long> {

    /**
     * 自定义查询方法
     * JPA 的神奇之处:只要按照规则命名方法,SQL 语句自动生成!
     * 
     * 翻译:select * from t_user where username = ?
     */
    User findByUsername(String username);
    
    /**
     * 翻译:select * from t_user where email = ?
     */
    User findByEmail(String email);
}

3.3 第三步:Service (大厨烹饪)

业务逻辑都在这里。我们将代码拆分为两个部分:基础注入和核心业务逻辑。

1. 依赖注入与类结构

首先,我们需要把 UserRepository (采购员) 注入进来,方便后续调用。

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.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service // 标记这是业务层组件
public class UserService {

    @Autowired // 依赖注入:告诉 Spring,我要用这个采购员(Repository),请帮我送进来
    private UserRepository userRepository;

2. 核心业务:注册逻辑

这是最复杂的逻辑,包含参数校验、重名检查和数据补全。

java 复制代码
    /**
     * 新增用户 (注册)
     * 业务逻辑:
     * 1. 检查用户名是否存在
     * 2. 补全创建时间
     * 3. 保存到数据库
     */
    @Transactional // 开启事务:保证一系列操作要么全成功,要么全失败
    public User register(User userData) {
        // 1. 简单校验
        if (userData.getUsername() == null) {
            throw new RuntimeException("用户名不能为空");
        }

        // 2. 检查是不是重名了
        User existUser = userRepository.findByUsername(userData.getUsername());
        if (existUser != null) {
            throw new RuntimeException("用户名已存在,换一个吧");
        }

        // 3. 补全系统字段 (创建时间)
        userData.setCreateTime(new Date());

        // 4. 调用持久层保存
        return userRepository.save(userData);
    }

3. 其他业务逻辑

查询和删除相对简单,直接调用 Repository 的方法即可。

java 复制代码
    /**
     * 查询所有用户列表
     */
    public List<User> findAllUsers() {
        return userRepository.findAll();
    }

    /**
     * 根据 ID 删除用户
     */
    @Transactional
    public void deleteUser(Long id) {
        if (!userRepository.existsById(id)) {
            throw new RuntimeException("要删除的用户不存在!");
        }
        userRepository.deleteById(id);
    }
}

3.4 第四步:Controller (服务员接客)

这是对外的窗口,通常遵循 RESTful 风格设计。为了清晰,我们按功能模块拆分代码。

1. 控制器初始化

定义 API 的基础路径 /api/users,并注入 Service。

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.*;

import java.util.List;

/**
 * 用户管理控制器
 * @RestController = @Controller + @ResponseBody
 */
@RestController // 声明这是一个 REST 风格的控制器
@RequestMapping("/api/users") // 定义统一的基础路径
public class UserController {

    @Autowired
    private UserService userService; // 注入大厨 (Service)

2. 查询接口 (GET)

对应 HTTP GET 请求,用于获取资源。

java 复制代码
    /**
     * 获取用户列表
     * URL: GET /api/users
     */
    @GetMapping 
    public List<User> list() {
        return userService.findAllUsers();
    }

3. 新增接口 (POST)

对应 HTTP POST 请求,用于创建资源。注意 @RequestBody 的使用,它负责接收 JSON 数据。

java 复制代码
    /**
     * 注册新用户
     * URL: POST /api/users
     * @RequestBody: 读取请求体中的 JSON 数据转为 User 对象
     */
    @PostMapping
    public String add(@RequestBody User user) {
        try {
            userService.register(user);
            return "注册成功!"; 
        } catch (Exception e) {
            return "注册失败: " + e.getMessage();
        }
    }

4. 删除接口 (DELETE)

对应 HTTP DELETE 请求。注意 @PathVariable 用于从 URL 中提取 ID。

java 复制代码
    /**
     * 删除用户
     * URL: DELETE /api/users/{id} (例如 /api/users/5)
     * @PathVariable: 从 URL 路径中提取 {id} 的值
     */
    @DeleteMapping("/{id}")
    public String delete(@PathVariable Long id) {
        try {
            userService.deleteUser(id);
            return "删除成功";
        } catch (Exception e) {
            return "删除失败: " + e.getMessage();
        }
    }
}

🧐 四、 核心概念名词解释(小白必看)

1. IoC (控制反转) 与 DI (依赖注入)

  • IoC :以前我们需要对象,必须自己 new UserService()。现在我们把创建对象的权利交给 Spring 容器(管家)。
  • DI :我们需要用对象时,在属性上加个 @Autowired,Spring 就会帮我们把创建好的对象注入进来。

2. Spring Bean

  • 被 Spring 容器管理的对象就叫 Bean。
  • 只要加上 @Controller, @Service, @Repository, @Component 这些注解,类就会变成 Bean。

3. JSON

  • 前后端交互的"普通话"。Controller 返回的 Java 对象会被自动转换成 JSON 字符串格式(比如 {"name": "张三", "age": 18}),前端 JS 能轻松看懂。

🙋‍♂️ 五、 高频面试题 QA

Q1:@RestController@Controller 有什么区别?

A

  • @Controller:通常用于传统的 Web 开发,方法默认返回的是视图名字 (比如 index.html 的文件名),用于跳转页面。如果要返回 JSON 数据,需要在方法上额外加 @ResponseBody
  • @RestController:是 @Controller@ResponseBody 的组合注解。用它标记的类,所有方法默认都返回 数据 (JSON/XML),主要用于前后端分离开发。

Q2:Post 请求和 Get 请求的区别?(RESTful 视角)

A

  • GET :用于获取资源。它是幂等的(查一次和查很多次结果一样),参数拼接在 URL 后面,不安全且长度有限。
  • POST :用于新建资源(比如提交表单)。参数放在 Request Body 中,相对安全且无大小限制。

Q3:Service 层和 Controller 层的区别?代码写在一个层行不行?

A

  • 从技术上讲,所有代码写在 Controller 甚至直接写在 JSP 里都能跑,但这不仅难以维护,也没法复用。
  • Controller :负责接收请求参数校验
  • Service :负责业务逻辑(比如转账计算、逻辑判断)。这样如果其他 Controller 或者定时任务也需要用到这个逻辑,直接注入 Service 即可,实现了复用。

Q4:@Autowired@Resource 都可以注入,有什么区别?

A

  • @Autowired:是 Spring 提供的注解。默认按类型 (Type) 装配(只要你是 UserService 类我就注入)。
  • @Resource:是 JDK (Java标准) 提供的注解。默认按名称 (Name) 装配(找 ID 叫 userService 的 bean)。

🎯 六、 总结

Spring Boot 开发其实就是一场流水线作业:

  1. 定义实体:确定数据长什么样。
  2. 写 Repository:解决怎么存取数据。
  3. 写 Service:处理复杂的业务规则。
  4. 写 Controller:把功能暴露出去给别人用。

掌握了这个套路,90% 的后端业务开发你都能上手了!如果觉得文章对你有帮助,欢迎点赞收藏! 🚀


相关推荐
f***28142 小时前
Springboot中使用Elasticsearch(部署+使用+讲解 最完整)
spring boot·elasticsearch·jenkins
你怎么知道我是队长2 小时前
C语言---文件读写
java·c语言·开发语言
咕白m6253 小时前
通过 C# 快速生成二维码 (QR code)
后端·.net
踏浪无痕3 小时前
架构师如何学习 AI:三个月掌握核心能力的务实路径
人工智能·后端·程序员
小毅&Nora3 小时前
【后端】【SpringBoot】① 源码解析:从启动到优雅关闭
spring boot·后端·优雅关闭
嘻哈baby3 小时前
从TIME_WAIT爆炸到端口耗尽:Linux短连接服务排查与优化
后端
wszy18093 小时前
外部链接跳转:从 App 打开浏览器的正确姿势
java·javascript·react native·react.js·harmonyos
开心就好20253 小时前
iOS应用性能监控全面解析:CPU、内存、FPS、卡顿与内存泄漏检测
后端
期待のcode3 小时前
认识Java虚拟机
java·开发语言·jvm
raining_peidx3 小时前
xxljob源码
java·开发语言