《Spring Boot 第一周:从0到第一个REST API》

前言

作为一名有着10年前端经验的开发者,我决定拓展自己的技术栈,学习 Java 后端开发。本文记录了我在第一周内从零开始搭建 Spring Boot 项目、理解核心概念并成功写出第一个 REST API 的全过程。希望能给同样从零开始的朋友一些参考。

一、环境准备

1.1 安装 JDK

我安装了 JDK 25(虽然计划是 JDK 17,但高版本完全向下兼容)。验证安装:

复制代码
java -version

输出类似:

1.2 安装 IntelliJ IDEA

下载并安装了 IntelliJ IDEA Ultimate(社区版也完全够用)。安装后首次启动选择"免费试用 30 天"即可。

1.3 了解 Maven

Maven 是 Java 世界的"依赖管理器 + 构建工具",类似于前端的 npm + webpack。它通过 pom.xml文件管理项目依赖和构建流程。

二、创建第一个 Spring Boot 项目

2.1 使用 Spring Initializr

在 IDEA 中点击 New Project→ 选择 Spring Initializr,配置如下:

配置项
Name hello-world
Language Java
Type Maven
JDK 21(与本地 JDK 25 兼容)
Java 21

如本电脑

2.2 添加依赖

在依赖选择界面,勾选 Spring Web(用于构建 REST API)。点击 Create完成项目创建。

2.3 首次运行

找到主类 Backend1Application.java,点击绿色三角形运行。控制台输出

复制代码
Tomcat started on port(s): 8080 (http)
Started HelloWorldApplication in 2.345 seconds

浏览器访问 http://localhost:8080,看到 Whitelabel Error Page(404)------ 这实际上是成功标志,说明服务器已启动,只是还没有写任何接口。

三、解决常见问题

3.1 端口被占用

如果启动时报 Port 8080 was already in use,可以在 application.properties中修改端口:

java 复制代码
server.port=8085

四、理解核心注解

4.1 @RestController------ 类级别的"控制器印章"

**作用:**​ 标记一个类是"控制器",专门处理 HTTP 请求,并直接把返回值(比如字符串、JSON)写回给浏览器,不经过视图模板。

类比: ​ 就像在 Vue 里给一个组件加上 @Component装饰器,告诉框架"这是我的一块积木"。

4.2 @GetMapping------ 方法级别的"GET 请求路由"

作用: ​ 标记一个方法,当浏览器发送 GET 请求​ 到指定的 URL 时,就执行这个方法。

例子:

复制代码
@GetMapping("/hello")
public String sayHello() { return "你好"; }

访问 http://localhost:8085/hello就会触发这个方法。

特点: ​ 它是 @RequestMapping(method = RequestMethod.GET)的缩写,专门处理 GET 请求。

4.3 @RequestMapping

作用: ​ 既可以放在类上 ,也可以放在方法上,用来指定 URL 路径和请求方法(GET、POST、PUT、DELETE 等)。

用法一:放在类上,给整个控制器加一个公共前缀
java 复制代码
@RestController
@RequestMapping("/api")  // 这个类里所有方法的 URL 都以 /api 开头
public class BookController {

    @GetMapping("/books")  // 实际路径是 /api/books
    public List<Book> getAllBooks() { ... }

    @GetMapping("/books/{id}")  // 实际路径是 /api/books/{id}
    public Book getBookById(@PathVariable Long id) { ... }
}

等价于 @PutMapping("/books/{id}")。这样做的好处是:当你有多个接口都归属同一模块(比如书籍相关),统一加 /api前缀,代码更整洁,也方便后期统一调整路径。

用法二:放在方法上,等同于 @GetMapping@PostMapping

java 复制代码
@RequestMapping(value = "/books", method = RequestMethod.GET)
// 等价于 @GetMapping("/books")

@RequestMapping(value = "/books", method = RequestMethod.POST)
// 等价于 @PostMapping("/books")

4.4 三者的关系图

我们来把这三个注解一次性讲清楚,它们是你写 Spring Boot 接口的"三大法宝"。


  1. @RestController------ 类级别的"控制器印章"

**作用:**​ 标记一个类是"控制器",专门处理 HTTP 请求,并直接把返回值(比如字符串、JSON)写回给浏览器,不经过视图模板。

类比: ​ 就像在 Vue 里给一个组件加上 @Component装饰器,告诉框架"这是我的一块积木"。


  1. @GetMapping------ 方法级别的"GET 请求路由"

作用: ​ 标记一个方法,当浏览器发送 GET 请求​ 到指定的 URL 时,就执行这个方法。

例子:

复制代码
@GetMapping("/hello")
public String sayHello() { return "你好"; }

访问 http://localhost:8085/hello就会触发这个方法。

特点: ​ 它是 @RequestMapping(method = RequestMethod.GET)的缩写,专门处理 GET 请求。


  1. @RequestMapping------ 更通用的"请求映射"

作用: ​ 既可以放在类上 ,也可以放在方法上,用来指定 URL 路径和请求方法(GET、POST、PUT、DELETE 等)。

用法一:放在类上,给整个控制器加一个公共前缀

复制代码
复制代码
复制代码
@RestController
@RequestMapping("/api")  // 这个类里所有方法的 URL 都以 /api 开头
public class BookController {

    @GetMapping("/books")  // 实际路径是 /api/books
    public List<Book> getAllBooks() { ... }

    @GetMapping("/books/{id}")  // 实际路径是 /api/books/{id}
    public Book getBookById(@PathVariable Long id) { ... }
}

这样做的好处是:当你有多个接口都归属同一模块(比如书籍相关),统一加 /api前缀,代码更整洁,也方便后期统一调整路径。

用法二:放在方法上,等同于 @GetMapping@PostMapping
复制代码
@RequestMapping(value = "/books", method = RequestMethod.GET)
// 等价于 @GetMapping("/books")

@RequestMapping(value = "/books", method = RequestMethod.POST)
// 等价于 @PostMapping("/books")

4.3三者的关系图

复制代码
@RestController(类级别:标记这是一个控制器)
       │
       ├── @RequestMapping("/api")(类级别:给所有方法加前缀)
       │
       └── 方法级别:
              ├── @GetMapping("/books")   → 等价于 @RequestMapping(value="/books", method=GET)
              ├── @PostMapping("/books")  → 等价于 @RequestMapping(value="/books", method=POST)
              └── @RequestMapping("/other", method=PUT)  → 直接使用通用注解

源码:helloworld​

五、编写第一个 REST API

5.1 创建数据模型

model包下创建 Book.java

java 复制代码
package com.example.helloworld.model;
// 这个 Book类就是一个"数据容器",用来存放一本书的信息(编号、书名、作者)。后面你会用 List 装好几个 Book 对象返回给前端。
public class Book {
    private Long id;
    private String title;
    private String author;
    private String status;

    // 构造方法
    public  Book(long id, String title, String author,String status) {
        this.id = id;
        this.title = title;
        this.status = status;

    }
    // Getter 方法(用于 Spring 自动转 JSON)
    public Long getId() {
        return id;
    }

    public String getAuthor() {
        return author;
    }

    public String getTitle() {
        return title;
    }
    public String getStatus() {
        return status;
    }
}

5.2 创建控制器

controller包下创建 BookController.java

java 复制代码
@RestController
@RequestMapping("/api")
public class BookController {

    private List<Book> books = new ArrayList<>();

    public BookController() {
        books.add(new Book(1L, "Spring Boot 实战", "张三", "可借阅"));
        books.add(new Book(2L, "Java 核心技术", "李四", "已借出"));
        books.add(new Book(3L, "微服务架构设计", "王五", "可借阅"));
    }

    @GetMapping("/books")
    public List<Book> getAllBooks() {
        return books;
    }

    @PostMapping("/books")
    public Book addBook(@RequestBody Book newBook) {
        newBook.setId((long) (books.size() + 1));
        books.add(newBook);
        return newBook;
    }

    @PutMapping("/books/{id}")
    public Book updateBook(@PathVariable Long id, @RequestBody Book updatedBook) {
        for (Book book : books) {
            if (book.getId().equals(id)) {
                book.setTitle(updatedBook.getTitle());
                book.setAuthor(updatedBook.getAuthor());
                return book;
            }
        }
        return null;
    }
}

5.3 测试接口

  • GET http://localhost:8085/api/books→ 返回书籍列表(JSON)

  • POST http://localhost:8085/api/books→ 添加新书(Body 传 JSON)

  • PUT http://localhost:8085/api/books/1→ 更新书籍


六、连接 MySQL 数据库

6.1 安装并启动 MySQL

确保 MySQL 服务已安装并运行(Windows 可通过 services.msc查看 MySQL80 服务状态)。

6.2 在 pom.xml 中添加 JPA 和 MySQL 依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

添加后点击 IDEA 右下角的 Load Maven Changes​ 下载依赖

6.3 创建 application.yml 配置文件

src/main/resources下新建 application.yml,内容如下:

复制代码
server:
  port: 8085

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/bookdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: root
    password: 你的MySQL密码
    driver-class-name: com.mysql.cj.jdbc.Driver

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect
        format_sql: true

注意: ​ 将 password改为你自己的 MySQL root 密码。

6.4 在 MySQL 中创建数据库

打开 MySQL 命令行或可视化工具,执行:

复制代码
CREATE DATABASE IF NOT EXISTS bookdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

6.5 修改 Book 实体类,添加 JPA 注解

java 复制代码
package com.example.backend1.model;
import jakarta.persistence.*;

@Entity   // 标记这个类是一个数据库实体
@Table(name = "books")  //指定对应的数据库表名为 books
// 这个 Book类就是一个"数据容器",用来存放一本书的信息(编号、书名、作者)。后面你会用 List 装好几个 Book 对象返回给前端。
public class Book {
    @Id   //标记 id字段是主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)   // 主键自增长
    private Long id;

    @Column(nullable = false)   // 字段不能为空
    private String title;

    @Column(nullable = false)
    private String author;

    @Column(nullable = false)
    private String status;

    // 无参构造方法(Spring 反序列化时需要)
    public Book() {
    }

    // 构造方法    全参构造方法  方便在初始化时一次性设置所有字段

    // 全参构造方法
    public Book(Long id, String title, String author, String status) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.status = status;
    }

    // Getter 和 Setter 方法
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

6.6 重启项目,观察自动建表

启动项目后,控制台会输出类似:

复制代码
Hibernate: create table books (id bigint not null auto_increment, author varchar(255) not null, status varchar(255) not null, title varchar(255) not null, primary key (id)) engine=InnoDB

此时 bookdb数据库中已自动创建 books表。

6.7 验证数据持久化

由于之前的内存数据已清空,GET 请求返回空数组 []。可以通过 POST 请求添加数据,数据将存入 MySQL,重启后不会丢失。

七、遇到的坑与解决

7.1 400 Bad Request

  • 原因 :JSON 格式错误或字段类型不匹配(如 long不能为 null)

  • 解决 :将 long改为 Long,确保 JSON 字段名与 Java 属性一致

7.2 Required request body is missing

  • 原因 :Postman 中未正确设置 Body 类型为 raw+ JSON

  • 解决:检查 Postman 请求配置

7.3 找不到主类

  • 原因:编译缓存问题

  • 解决 :执行 Build → Rebuild ProjectFile → Invalidate Caches

7.4 数据库连接失败

  • 原因:MySQL 未启动、密码错误、数据库未创建

  • 解决 :确保 MySQL 服务运行,检查 application.yml中的连接信息,提前创建 bookdb数据库


八、总结

第一周的学习让我完成了:

  1. ✅ 搭建 Spring Boot 开发环境

  2. ✅ 理解 Maven 和项目结构

  3. ✅ 掌握 @RestController、@GetMapping、@PostMapping、@PutMapping 等核心注解

  4. ✅ 编写并测试了完整的 REST API(CRUD)

  5. ✅ 学会使用 Postman 进行接口调试

  6. ✅ 配置 MySQL 数据库,使用 JPA 自动建表,实现数据持久化

虽然只是入门,但已经能够独立开发带有数据库的后端接口。下一周将深入学习更复杂的查询、异常处理、JWT 鉴权等内容。


附录:常用命令与工具

工具/命令 用途
java -version 查看 JDK 版本
mvn clean install 清理并重新编译
Postman API 测试工具
IDEA HTTP Client 内置的 API 测试工具(.http 文件)
MySQL Workbench / Navicat 数据库可视化管理

源码地址:helloworld​ backend1