前言
这篇文章教你从零开始,一步步复现 learning-demo 项目。每一步都有代码,照着做就能跑起来。
第一步:创建 Spring Boot 项目
1.1 使用 Spring Initializr 创建
打开 https://start.spring.io ,填写:
| 项目 | 值 |
|---|---|
| Project | Maven |
| Language | Java |
| Spring Boot | 3.2.5 |
| Group | com.demo |
| Artifact | learning-demo-backend |
| Name | learning-demo-backend |
| Package name | com.demo |
| Packaging | Jar |
| Java | 17 |
点击「ADD DEPENDENCIES」,添加:
- Spring Web
- Spring Data JDBC
- MySQL Driver
- Lombok
点击「GENERATE」,下载 zip 文件,解压到你的工作目录。
1.2 项目结构
解压后是这样的:
learning-demo-backend/
├── src/
│ ├── main/
│ │ ├── java/com/demo/
│ │ │ └── DemoApplication.java ← 启动类
│ │ └── resources/
│ │ └── application.properties ← 配置文件(先删掉,用 yml)
│ └── test/
├── pom.xml ← Maven 配置
第二步:配置 pom.xml 依赖
打开 pom.xml,把 <dependencies> 部分改成这样:
<dependencies>
<!-- Web:提供 REST API -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JDBC:数据库连接池 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis-Plus:比 MyBatis 更好用 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.6</version>
</dependency>
<!-- Redis:缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Kafka:消息队列 -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<!-- Lombok:少写 getter/setter -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
第三步:配置 application.yml
删掉 application.properties,新建 application.yml:
server:
port: 8080
spring:
application:
name: learning-demo
# 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/learning_demo?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: root123 # 改成你的密码
# Redis 配置
data:
redis:
host: localhost
port: 6379
# Kafka 配置
kafka:
bootstrap-servers: localhost:9092
consumer:
group-id: demo-group
auto-offset-reset: earliest
producer:
acks: "1"
# MyBatis-Plus 配置
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
map-underscore-to-camel-case: true
第四步:创建数据库
4.1 创建数据库
打开 MySQL,执行:
CREATE DATABASE learning_demo;
4.2 创建用户表
USE learning_demo;
CREATE TABLE t_user (
id BIGINT 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 '状态:1正常,0禁用',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
);
-- 插入测试数据
INSERT INTO t_user (username, password, email) VALUES
('admin', '123456', 'admin@example.com'),
('zhangsan', '123456', 'zhangsan@example.com');
第五步:创建实体类 Entity
新建 src/main/java/com/demo/entity/User.java:
package com.demo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data // Lombok 自动生成 getter/setter
@TableName("t_user") // 对应数据库表名
public class User {
private Long id;
private String username;
private String password;
private String email;
private Integer status;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
第六步:创建 Mapper 接口
新建 src/main/java/com/demo/mapper/UserMapper.java:
package com.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 继承 BaseMapper 后,自动拥有:
// - selectById(id) 查单个
// - selectList() 查列表
// - insert(user) 插入
// - updateById(user) 更新
// - deleteById(id) 删除
// 自定义查询
@Select("SELECT * FROM t_user WHERE username = #{username}")
List<User> selectByUsername(String username);
}
第七步:创建 Service 层
新建 src/main/java/com/demo/service/UserService.java:
package com.demo.service;
import com.demo.entity.User;
import java.util.List;
public interface UserService {
User getById(Long id);
List<User> getAll();
User register(String username, String password, String email);
User update(Long id, String email);
boolean delete(Long id);
}
新建 src/main/java/com/demo/service/impl/UserServiceImpl.java:
package com.demo.service.impl;
import com.demo.entity.User;
import com.demo.mapper.UserMapper;
import com.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 UserMapper userMapper;
@Override
public User getById(Long id) {
return userMapper.selectById(id);
}
@Override
public List<User> getAll() {
return userMapper.selectList(null);
}
@Override
public User register(String username, String password, String email) {
// 检查用户名是否已存在
List<User> existing = userMapper.selectByUsername(username);
if (!existing.isEmpty()) {
throw new RuntimeException("用户名已存在");
}
User user = new User();
user.setUsername(username);
user.setPassword(password); // 生产环境要加密!
user.setEmail(email);
user.setStatus(1);
userMapper.insert(user);
return user;
}
@Override
public User update(Long id, String email) {
User user = userMapper.selectById(id);
if (user == null) {
throw new RuntimeException("用户不存在");
}
user.setEmail(email);
userMapper.updateById(user);
return user;
}
@Override
public boolean delete(Long id) {
return userMapper.deleteById(id) > 0;
}
}
第八步:创建 Controller 层
新建 src/main/java/com/demo/controller/UserController.java:
package com.demo.controller;
import com.demo.entity.User;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
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> getAll() {
return userService.getAll();
}
// 查单个用户
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.getById(id);
}
// 注册
@PostMapping("/register")
public User register(@RequestBody User user) {
return userService.register(
user.getUsername(),
user.getPassword(),
user.getEmail()
);
}
// 更新
@PutMapping("/{id}")
public User update(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user.getEmail());
}
// 删除
@DeleteMapping("/{id}")
public String delete(@PathVariable Long id) {
userService.delete(id);
return "删除成功";
}
}
第九步:统一返回格式
新建 src/main/java/com/demo/common/Result.java:
package com.demo.common;
import lombok.Data;
@Data
public class Result<T> {
private Integer code; // 200 成功,其他失败
private String message;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage("成功");
result.setData(data);
return result;
}
public static <T> Result<T> error(String message) {
Result<T> result = new Result<>();
result.setCode(500);
result.setMessage(message);
return result;
}
}
修改 Controller,用 Result 包装返回值:
@GetMapping
public Result<List<User>> getAll() {
return Result.success(userService.getAll());
}
第十步:添加 Redis 缓存
新建 src/main/java/com/demo/redis/UserCacheService.java:
package com.demo.redis;
import com.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class UserCacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 缓存用户,有效期 30 分钟
public void cacheUser(Long id, User user) {
String key = "user:" + id;
redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
}
// 从缓存取用户
public User getUser(Long id) {
String key = "user:" + id;
return (User) redisTemplate.opsForValue().get(key);
}
// 删除缓存
public void deleteUser(Long id) {
String key = "user:" + id;
redisTemplate.delete(key);
}
}
在 Service 里用缓存:
@Override
public User getById(Long id) {
// 先查缓存
User cached = userCacheService.getUser(id);
if (cached != null) {
return cached;
}
// 缓存没有,查数据库
User user = userMapper.selectById(id);
if (user != null) {
userCacheService.cacheUser(id, user); // 存到缓存
}
return user;
}
第十一步:添加 Kafka 消息
新建 src/main/java/com/demo/kafka/UserKafkaProducer.java:
package com.demo.kafka;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserKafkaProducer {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
private static final String TOPIC = "user-events";
// 发送消息
public void sendUserRegistered(String username) {
String message = "新用户注册:" + username;
kafkaTemplate.send(TOPIC, message);
}
}
新建 src/main/java/com/demo/kafka/UserKafkaConsumer.java:
package com.demo.kafka;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;
@Service
public class UserKafkaConsumer {
// 监听消息
@KafkaListener(topics = "user-events", groupId = "demo-group")
public void consume(String message) {
System.out.println("收到消息:" + message);
// 可以在这里做其他事情,比如发欢迎邮件
}
}
在注册时发送消息:
@Autowired
private UserKafkaProducer kafkaProducer;
@Override
public User register(String username, String password, String email) {
// ... 注册逻辑 ...
// 发送 Kafka 消息
kafkaProducer.sendUserRegistered(username);
return user;
}
第十二步:启动测试
12.1 启动依赖服务
确保这些服务在运行:
- MySQL:localhost:3306
- Redis:localhost:6379
- Kafka:localhost:9092
12.2 运行项目
mvn spring-boot:run
12.3 测试 API
用浏览器或 curl 测试:
# 查所有用户
curl http://localhost:8080/api/users
# 注册新用户
curl -X POST http://localhost:8080/api/users/register \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"123456","email":"test@example.com"}'
# 查单个用户
curl http://localhost:8080/api/users/1
# 删除用户
curl -X DELETE http://localhost:8080/api/users/1
总结
从零到完整项目,一共 12 步:
| 步骤 | 做了什么 |
|---|---|
| 1 | 创建 Spring Boot 项目 |
| 2 | 配置 pom.xml 依赖 |
| 3 | 配置 application.yml |
| 4 | 创建数据库和表 |
| 5 | 创建 Entity 实体类 |
| 6 | 创建 Mapper 接口 |
| 7 | 创建 Service 层 |
| 8 | 创建 Controller 层 |
| 9 | 统一返回格式 Result |
| 10 | 添加 Redis 缓存 |
| 11 | 添加 Kafka 消息 |
| 12 | 启动测试 |
这就是 learning-demo 后端的核心部分。前端 Vue 3 部分可以参考项目解读那篇文章。