Spring Boot 入门教程——从零搭建 RESTful API

Spring Boot 入门教程——从零搭建 RESTful API

作者: CaoZH
日期: 2023-04-15
本文为原创教程


Spring Boot 是 Java 生态中最流行的微服务框架。Spring Boot 2.7.x 是 2023 年初的稳定版本,本文基于此版本,带你从零搭建一个完整的 RESTful API 项目。

一、环境准备

必需工具

工具 版本 说明
JDK 8 或 11 Spring Boot 2.7 支持 JDK 8+
Maven 3.6+ 项目构建
IDE IDEA / VS Code 开发环境
Postman 任意版本 API 测试(可选)

创建项目

方式一:Spring Initializr(推荐)

访问 start.spring.io,选择:

  • Project: Maven
  • Language: Java
  • Spring Boot: 2.7.x
  • Dependencies: Spring Web, Spring Data JPA, MySQL Driver, Lombok

点击 Generate 下载项目压缩包,解压后用 IDEA 打开。

方式二:手动创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
</parent>

<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

二、项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
demo/
├── src/main/java/com/example/demo/
│ ├── DemoApplication.java # 启动类
│ ├── controller/ # 控制器层
│ │ └── UserController.java
│ ├── service/ # 业务层
│ │ ├── UserService.java
│ │ └── impl/
│ │ └── UserServiceImpl.java
│ ├── repository/ # 数据访问层
│ │ └── UserRepository.java
│ ├── entity/ # 实体类
│ │ └── User.java
│ └── dto/ # 数据传输对象
│ ├── UserCreateRequest.java
│ └── UserUpdateRequest.java

├── src/main/resources/
│ ├── application.yml # 配置文件
│ └── schema.sql # 建表脚本

└── pom.xml

三、配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# application.yml
server:
port: 8080

spring:
datasource:
url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: update # 自动建表
show-sql: true # 打印 SQL
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect

四、编写代码

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// entity/User.java
package com.example.demo.entity;

import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;

@Data
@Entity
@Table(name = "sys_user")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false, length = 50)
private String username;

@Column(nullable = false, length = 100)
private String password;

@Column(length = 100)
private String email;

@Column(length = 20)
private String phone;

private Integer status = 0; // 0:正常 1:停用

private LocalDateTime createTime;

private LocalDateTime updateTime;

@PrePersist
protected void onCreate() {
createTime = LocalDateTime.now();
updateTime = LocalDateTime.now();
}

@PreUpdate
protected void onUpdate() {
updateTime = LocalDateTime.now();
}
}

Repository

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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.List;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

User findByUsername(String username);

List<User> findByStatus(Integer status);

boolean existsByUsername(String username);
}

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
// service/UserService.java
package com.example.demo.service;

import com.example.demo.entity.User;
import java.util.List;

public interface UserService {
List<User> findAll();
User findById(Long id);
User create(User user);
User update(Long id, User user);
void delete(Long id);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// service/impl/UserServiceImpl.java
package com.example.demo.service.impl;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserRepository userRepository;

@Override
public List<User> findAll() {
return userRepository.findAll();
}

@Override
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在: " + id));
}

@Override
public User create(User user) {
if (userRepository.existsByUsername(user.getUsername())) {
throw new RuntimeException("用户名已存在");
}
return userRepository.save(user);
}

@Override
public User update(Long id, User user) {
User existing = findById(id);
existing.setEmail(user.getEmail());
existing.setPhone(user.getPhone());
existing.setStatus(user.getStatus());
return userRepository.save(existing);
}

@Override
public void delete(Long id) {
User user = findById(id);
userRepository.delete(user);
}
}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 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.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

@Autowired
private UserService userService;

@GetMapping
public List<User> list() {
return userService.findAll();
}

@GetMapping("/{id}")
public ResponseEntity<User> getById(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}

@PostMapping
public ResponseEntity<User> create(@RequestBody User user) {
User created = userService.create(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}

@PutMapping("/{id}")
public ResponseEntity<User> update(
@PathVariable Long id,
@RequestBody User user) {
return ResponseEntity.ok(userService.update(id, user));
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}

启动类

1
2
3
4
5
6
7
8
9
10
11
12
// 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);
}
}

五、运行与测试

1
2
3
4
5
6
7
8
9
10
11
# 启动项目
mvn spring-boot:run

# 测试接口
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"123456","email":"admin@test.com"}'

curl http://localhost:8080/api/users

curl http://localhost:8080/api/users/1

六、总结

通过本教程,你搭建了一个完整的 RESTful API 项目:

  • ✅ Spring Boot 项目初始化
  • ✅ 三层架构(Controller → Service → Repository)
  • ✅ JPA 自动建表与 CRUD
  • ✅ RESTful API 设计
  • ✅ 异常处理

下一步: 添加 Swagger 文档、集成 Redis 缓存、添加安全认证(Spring Security)。


首发于 CaoZH 的笔记