Spring Boot + Vue 3 全栈学习笔记

星期四, 4月 9, 2026 | 6分钟阅读 | 更新于 星期四, 4月 9, 2026

@

这是一份详细的学习笔记,记录了一个最小的 Spring Boot 后端 + Vue 3 前端项目。项目集成了 MySQL、MyBatis、Redis、Kafka,通过一个完整的"用户注册"业务流程演示各组件的协作。

目录

  1. 项目整体架构
  2. 后端技术栈详解
  3. 前端技术栈详解
  4. 业务流程分析
  5. 数据库设计
  6. API 接口设计
  7. 快速启动指南

1. 项目整体架构

1.1 技术架构图

┌─────────────────────────────────────────────────────────────────────────┐
│                              前端 (Vue 3)                                │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐                 │
│  │  UserManage │───▶│  Pinia     │───▶│   Axios     │                 │
│  │    View     │    │   Store    │    │   API       │                 │
│  └─────────────┘    └─────────────┘    └─────────────┘                 │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │ HTTP/json
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                            后端 (Spring Boot)                            │
│                                                                         │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐                 │
│  │ Controller  │───▶│  Service    │───▶│   Mapper    │                 │
│  │  用户接口    │    │  业务逻辑   │    │  数据访问   │                 │
│  └─────────────┘    └─────────────┘    └─────────────┘                 │
│         │                   │                                              │
│         │                   ▼                                              │
│         │           ┌─────────────┐    ┌─────────────┐                   │
│         │           │   Redis     │    │   Kafka     │                   │
│         │           │   缓存      │    │   消息队列  │                   │
│         │           └─────────────┘    └─────────────┘                   │
│         │                                  │                              │
│         └──────────▶│   MySQL   │◀─────────┘                              │
│                    │   数据库   │                                          │
│                    └───────────┘                                          │
└─────────────────────────────────────────────────────────────────────────┘

1.2 目录结构

learning-demo/
├── backend/                          # Spring Boot 后端
│   ├── pom.xml                       # Maven 依赖配置
│   └── src/main/
│       ├── java/com/demo/
│       │   ├── DemoApplication.java  # 启动类
│       │   ├── config/               # 配置类
│       │   ├── controller/           # 控制器层
│       │   ├── service/              # 服务层
│       │   ├── mapper/               # 数据访问层
│       │   ├── entity/               # 实体类
│       │   ├── dto/                  # 数据传输对象
│       │   ├── kafka/                # Kafka 消息处理
│       │   ├── redis/                # Redis 缓存
│       │   └── common/               # 通用类
│       └── resources/
│           ├── application.yml        # 应用配置
│           ├── mapper/               # MyBatis XML
│           └── schema.sql            # 数据库脚本
│
└── frontend/                         # Vue 3 前端
    ├── package.json                   # npm 依赖
    ├── vite.config.js                 # Vite 配置
    └── src/
        ├── main.js                    # Vue 入口
        ├── App.vue                    # 根组件
        ├── api/                      # API 封装
        ├── views/                    # 页面组件
        ├── components/               # 通用组件
        └── stores/                   # 状态管理

2. 后端技术栈详解

2.1 pom.xml - Maven 项目配置

pom.xml 是 Maven 项目的核心配置文件,定义了项目的基本信息、依赖包、构建插件等。Maven 可以管理项目依赖、定义项目的构建配置、管理项目版本和模块。

核心依赖:

依赖作用
spring-boot-starter-webSpring MVC、内嵌 Tomcat 服务器
mysql-connector-jMySQL 数据库驱动
mybatis-plus-spring-boot3-starterMyBatis 增强工具
spring-boot-starter-data-redisRedis 缓存支持
spring-kafkaKafka 消息队列支持
lombok自动生成 getter/setter 等代码

2.2 application.yml - 应用配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/learning_demo?useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root123
    type: com.zaxxer.hikari.HikariDataSource

  data:
    redis:
      host: localhost
      port: 6379

  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      group-id: demo-consumer-group
      enable-auto-commit: false  # 手动提交 offset

2.3 DemoApplication.java - 启动类

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@SpringBootApplication 是组合注解,等价于:

  • @SpringBootConfiguration - 标记配置类
  • @EnableAutoConfiguration - 启用自动配置
  • @ComponentScan - 扫描组件

2.4 User.java - 用户实体类

@Data
@TableName("t_user")
public class User implements Serializable {
    @TableId(type = IdType.AUTO)
    private Long id;

    private String username;
    private String password;
    private String email;
    private Integer status;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

Lombok 注解:

  • @Data - 生成 getter/setter/equals/hashCode/toString
  • @TableName - 指定对应的数据库表名
  • @TableId - 标记主键,type = AUTO 表示自增

2.5 UserMapper.java - MyBatis Mapper 接口

@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
    // BaseMapper 已提供:insert、deleteById、updateById、selectById 等方法

    @Select("SELECT * FROM t_user WHERE username = #{username}")
    List<User> selectByUsername(String username);

    @Delete("DELETE FROM t_user WHERE id = #{id}")
    int deleteById(Long id);
}

BaseMapper 继承后自动获得 CRUD 方法。@Select、@Delete 等注解用于自定义 SQL。

2.6 UserCacheService.java - Redis 缓存服务

@Service
public class UserCacheService {
    private final RedisTemplate<String, Object> redisTemplate;

    public User getUser(Long userId) {
        String key = "learning-demo:user:cache:" + userId;
        return (User) redisTemplate.opsForValue().get(key);
    }

    public void setUser(User user) {
        String key = "learning-demo:user:cache:" + user.getId();
        redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
    }

    public void deleteUser(Long userId) {
        redisTemplate.delete("learning-demo:user:cache:" + userId);
    }
}

缓存策略(Cache Aside):

  1. 查询时先查缓存
  2. 缓存未命中则查数据库
  3. 写入/更新/删除时同步更新缓存

2.7 Kafka 生产者和消费者

UserKafkaProducer.java:

@Service
public class UserKafkaProducer {
    private final KafkaTemplate<String, String> kafkaTemplate;

    public void sendUserRegistrationMessage(User user) {
        String message = "{\"userId\":" + user.getId() + ",\"username\":\"" + user.getUsername() + "\"}";
        kafkaTemplate.send("user-registration-topic", user.getId().toString(), message);
    }
}

UserKafkaConsumer.java:

@Component
public class UserKafkaConsumer {
    @KafkaListener(topics = "user-registration-topic", groupId = "demo-group")
    public void consume(String message, Acknowledgment ack) {
        // 处理消息:发送欢迎邮件、初始化数据等
        ack.acknowledge();  // 手动提交 offset
    }
}

2.8 UserServiceImpl.java - 用户服务实现

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;
    private final UserCacheService userCacheService;
    private final UserKafkaProducer userKafkaProducer;

    @Override
    @Transactional
    public UserDTO register(RegisterRequest request) {
        // 1. 验证用户名/邮箱是否已存在
        // 2. 创建用户对象并保存到数据库
        // 3. 发送 Kafka 消息(异步)
        // 4. 返回用户信息
        userKafkaProducer.sendUserRegistrationMessage(user);
        return UserDTO.fromUser(user);
    }

    @Override
    public UserDTO getUserById(Long id) {
        // 1. 先查缓存
        User cached = userCacheService.getUser(id);
        if (cached != null) return UserDTO.fromUser(cached);

        // 2. 缓存未命中,查数据库
        User user = userMapper.selectById(id);
        userCacheService.setUser(user);
        return UserDTO.fromUser(user);
    }
}

2.9 UserController.java - REST API 控制器

@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;

    @PostMapping("/register")
    public Result<UserDTO> register(@RequestBody RegisterRequest request) {
        try {
            return Result.success(userService.register(request));
        } catch (RuntimeException e) {
            return Result.error(400, e.getMessage());
        }
    }

    @GetMapping("/{id}")
    public Result<UserDTO> getUserById(@PathVariable Long id) {
        UserDTO user = userService.getUserById(id);
        if (user == null) return Result.error(404, "用户不存在");
        return Result.success(user);
    }
}

3. 前端技术栈详解

3.1 main.js - Vue 应用入口

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.use(ElementPlus)
app.mount('#app')

3.2 user.js - API 封装

const request = axios.create({
  baseURL: '/api',
  timeout: 10000
})

request.interceptors.response.use(response => {
  const { code, message, data } = response.data
  if (code === 200) return data
  ElMessage.error(message)
  return Promise.reject(new Error(message))
})

export function register(data) {
  return request.post('/users/register', data)
}

export function getUsers(page, pageSize) {
  return request.get('/users', { params: { page, pageSize } })
}

3.3 Pinia 状态管理

export const useUserStore = defineStore('user', () => {
  const userList = ref([])
  const loading = ref(false)

  async function fetchUsers(page = 1, pageSize = 10) {
    loading.value = true
    try {
      const data = await getUsers(page, pageSize)
      userList.value = data
    } finally {
      loading.value = false
    }
  }

  return { userList, loading, fetchUsers }
})

4. 业务流程分析

4.1 用户注册流程

用户注册流程:

1. 前端提交表单 POST /api/users/register
         │
         ▼
2. Controller 接收请求
         │
         ▼
3. Service 验证用户名/邮箱
         │
         ▼
4. 保存到 MySQL 数据库
         │
         ▼
5. 发送 Kafka 消息到 user-registration-topic(异步,不阻塞响应)
         │
         ▼
6. 返回成功响应给前端
         │
         ▼
7. Kafka Consumer 接收消息,执行后续业务:
   - 发送欢迎邮件(模拟)
   - 初始化用户数据(模拟)

4.2 用户查询流程(带缓存)

查询请求
    │
    ▼
查 Redis 缓存 ──── 命中 ──── 直接返回
    │
  未命中
    │
    ▼
查 MySQL 数据库
    │
    ▼
写入 Redis 缓存(TTL 30分钟)
    │
    ▼
返回数据

5. 数据库设计

CREATE TABLE t_user (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '用户ID',
    username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
    password VARCHAR(100) NOT NULL COMMENT '密码',
    email VARCHAR(100) COMMENT '邮箱',
    status TINYINT DEFAULT 1 COMMENT '状态:0-禁用,1-正常',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

6. API 接口设计

方法路径说明请求体
POST/api/users/register用户注册{username, password, email}
GET/api/users获取用户列表?page=1&pageSize=10
GET/api/users/{id}获取单个用户-
PUT/api/users/{id}更新用户{username, email, ...}
DELETE/api/users/{id}删除用户-
GET/api/users/cache/stats缓存统计-

7. 快速启动指南

环境要求

  • JDK 17+
  • Maven 3.6+
  • Node.js 16+
  • MySQL 8.0
  • Redis 6+
  • Kafka 3+

启动步骤

# 1. 创建数据库
mysql -u root -p -e "CREATE DATABASE learning_demo;"

# 2. 启动后端
export JAVA_HOME="/opt/homebrew/opt/openjdk@17"
cd backend
mvn spring-boot:run

# 3. 启动前端
cd frontend
npm install
npm run dev

验证

  • 后端 API:http://localhost:8080/api/users
  • 前端界面:http://localhost:5173

学习建议

后端学习顺序

  1. DemoApplication.java - 启动类和配置入口
  2. User.java - 实体类定义
  3. UserMapper.java - 数据库操作
  4. UserServiceImpl.java - 核心业务逻辑
  5. UserController.java - API 接口
  6. UserCacheService.java - 缓存策略
  7. UserKafkaProducer/Consumer.java - 消息队列

前端学习顺序

  1. main.js - 应用入口
  2. stores/user.js - 状态管理
  3. api/user.js - API 封装
  4. views/UserManage.vue - 页面组件
  5. components/UserForm.vue - 表单组件

项目完整代码已保存在 /Users/hanzi/Desktop/learning-demo/

© 2026 My Blog

🌱 Powered by Hugo with theme Dream.