一、项目需求
搭建一个用户管理系统的后端 API:
┌──────────────────────────────────────────────────┐
│ 用户管理 RESTful API │
├────────┬──────────┬─────────────────────────────┤
│ 接口 │ 方法 │ 说明 │
├────────┼──────────┼─────────────────────────────┤
│/users │ GET │ 获取用户列表(分页) │
│/users │ POST │ 创建用户 │
│/users/{id}│ GET │ 获取单个用户 │
│/users/{id}│ PUT │ 更新用户 │
│/users/{id}│ DELETE│ 删除用户 │
└────────┴──────────┴─────────────────────────────┘
技术栈:
- Spring Boot 3.2 + Java 17
- MyBatis-Plus(简化数据库操作)
- MySQL 8.0
- Lombok
二、Cursor 新建项目
2.1 创建 Spring Boot 项目
在 Cursor 中打开终端,输入:
bash
# 方式一:用 Spring Initializr(推荐在 Cursor Terminal 中操作)
# 访问 https://start.spring.io/ 下载项目,然后在 Cursor 中打开
# 方式二:或者直接让 Cursor 生成
# 打开 Cursor 的 Composer (Ctrl+I / Cmd+I),输入:
Cursor Prompt:
帮我创建一个 Spring Boot 3.2 项目,要求:
1. Java 17
2. 依赖:spring-boot-starter-web, mybatis-plus-spring-boot3-starter, mysql-connector-j, lombok
3. groupId: com.example, artifactId: user-management
4. 在 application.yml 中配置 MySQL 数据源(用户名root,密码123456,数据库user_db)
5. 创建数据库建表SQL:users表(id, username, email, phone, create_time, update_time, is_deleted逻辑删除)
Cursor 会自动帮你生成项目结构和配置文件。
2.2 项目结构
生成后项目结构应该是:
user-management/
├── src/main/java/com/example/usermanagement/
│ ├── UserManagementApplication.java
│ ├── entity/
│ │ └── User.java
│ ├── mapper/
│ │ └── UserMapper.java
│ ├── service/
│ │ ├── UserService.java
│ │ └── impl/
│ │ └── UserServiceImpl.java
│ ├── controller/
│ │ └── UserController.java
│ ├── dto/
│ │ ├── UserCreateDTO.java
│ │ ├── UserUpdateDTO.java
│ │ └── UserVO.java
│ ├── common/
│ │ ├── Result.java
│ │ └── PageResult.java
│ └── config/
│ └── MybatisPlusConfig.java
├── src/main/resources/
│ ├── application.yml
│ └── db/
│ └── schema.sql
└── pom.xml
三、Cursor 对话实录:搭框架
3.1 让 Cursor 生成实体类和 Mapper
Prompt(在 Cursor Chat 中输入):
基于上面的 users 表结构,帮我生成以下文件:
1. User.java (entity) - 使用 MyBatis-Plus 注解 @TableName, @TableId, @TableField
2. UserMapper.java - 继承 BaseMapper<User>
3. MybatisPlusConfig.java - 配置分页插件和逻辑删除
注意:
- 使用 @TableLogic 实现逻辑删除
- id 使用雪花算法 @TableId(type = IdType.ASSIGN_ID)
- create_time 和 update_time 使用 @TableField(fill = FieldFill.INSERT/UPDATE)
- 代码风格要简洁,用 Lombok
3.2 Cursor 生成的实体类
java
package com.example.usermanagement.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("users")
public class User {
/** 主键ID(雪花算法) */
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/** 用户名 */
private String username;
/** 邮箱 */
private String email;
/** 手机号 */
private String phone;
/** 创建时间(自动填充) */
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/** 更新时间(自动填充) */
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/** 逻辑删除(0=正常,1=已删除) */
@TableLogic
private Integer isDeleted;
}
四、Cursor 对话实录:写业务代码
4.1 Service 层
Prompt:
帮我生成 UserService 和 UserServiceImpl:
要求:
1. 分页查询用户列表(支持按用户名模糊搜索)
2. 根据 ID 获取用户详情
3. 创建用户(校验用户名不能重复,邮箱格式校验)
4. 更新用户(只更新非空字段)
5. 删除用户(逻辑删除)
返回值统一用 Result<T> 包装,分页用 PageResult<T>
DTO 和 VO 要和 Entity 分开
java
// Service 接口
public interface UserService {
/** 分页查询 */
PageResult<UserVO> listUsers(int pageNum, int pageSize, String username);
/** 获取详情 */
UserVO getUserById(Long id);
/** 创建用户 */
Long createUser(UserCreateDTO dto);
/** 更新用户 */
void updateUser(Long id, UserUpdateDTO dto);
/** 删除用户 */
void deleteUser(Long id);
}
java
// Service 实现
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserMapper userMapper;
@Override
public PageResult<UserVO> listUsers(int pageNum, int pageSize, String username) {
Page<User> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(username != null && !username.isBlank(), User::getUsername, username);
wrapper.orderByDesc(User::getCreateTime);
userMapper.selectPage(page, wrapper);
List<UserVO> voList = page.getRecords().stream()
.map(this::toVO)
.collect(Collectors.toList());
return new PageResult<>(voList, page.getTotal());
}
@Override
public UserVO getUserById(Long id) {
User user = userMapper.selectById(id);
if (user == null) {
throw new RuntimeException("用户不存在");
}
return toVO(user);
}
@Override
@Transactional
public Long createUser(UserCreateDTO dto) {
// 校验用户名唯一
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getUsername, dto.getUsername());
if (userMapper.selectCount(wrapper) > 0) {
throw new RuntimeException("用户名已存在");
}
User user = new User();
user.setUsername(dto.getUsername());
user.setEmail(dto.getEmail());
user.setPhone(dto.getPhone());
userMapper.insert(user);
return user.getId();
}
@Override
@Transactional
public void updateUser(Long id, UserUpdateDTO dto) {
User user = userMapper.selectById(id);
if (user == null) {
throw new RuntimeException("用户不存在");
}
// 只更新非空字段
if (dto.getUsername() != null) user.setUsername(dto.getUsername());
if (dto.getEmail() != null) user.setEmail(dto.getEmail());
if (dto.getPhone() != null) user.setPhone(dto.getPhone());
userMapper.updateById(user);
}
@Override
public void deleteUser(Long id) {
userMapper.deleteById(id); // 逻辑删除
}
private UserVO toVO(User user) {
return UserVO.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.phone(user.getPhone())
.createTime(user.getCreateTime())
.build();
}
}
4.2 Controller 层
Prompt:
帮我生成 UserController,遵循 RESTful 风格:
- GET /api/users?page=1&size=10&username=xxx
- POST /api/users
- GET /api/users/{id}
- PUT /api/users/{id}
- DELETE /api/users/{id}
用 @Valid 做参数校验,统一异常处理
java
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
@Tag(name = "用户管理")
public class UserController {
private final UserService userService;
@GetMapping
@Operation(summary = "分页查询用户列表")
public Result<PageResult<UserVO>> listUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String username) {
return Result.success(userService.listUsers(page, size, username));
}
@GetMapping("/{id}")
@Operation(summary = "获取用户详情")
public Result<UserVO> getUser(@PathVariable Long id) {
return Result.success(userService.getUserById(id));
}
@PostMapping
@Operation(summary = "创建用户")
public Result<Long> createUser(@Valid @RequestBody UserCreateDTO dto) {
return Result.success(userService.createUser(dto));
}
@PutMapping("/{id}")
@Operation(summary = "更新用户")
public Result<Void> updateUser(@PathVariable Long id,
@Valid @RequestBody UserUpdateDTO dto) {
userService.updateUser(id, dto);
return Result.success();
}
@DeleteMapping("/{id}")
@Operation(summary = "删除用户")
public Result<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return Result.success();
}
}
五、Cursor 对话实录:写测试
Prompt:
帮我写 UserController 的集成测试类,使用 @SpringBootTest + MockMvc:
1. 测试创建用户(正常 + 用户名重复)
2. 测试分页查询
3. 测试获取用户详情(存在 + 不存在)
4. 测试更新用户
5. 测试删除用户
java
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Test
void createUser_success() throws Exception {
UserCreateDTO dto = new UserCreateDTO();
dto.setUsername("testuser");
dto.setEmail("test@example.com");
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(dto)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.data").isNumber());
}
}
六、接口测试
用 Apifox / Postman / cURL 测试:
bash
# 1. 创建用户
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"username":"张三","email":"zhangsan@example.com","phone":"13800138000"}'
# 2. 查询用户列表
curl http://localhost:8080/api/users?page=1\&size=10
# 3. 获取用户详情
curl http://localhost:8080/api/users/1
# 4. 更新用户
curl -X PUT http://localhost:8080/api/users/1 \
-H "Content-Type: application/json" \
-d '{"email":"newemail@example.com"}'
# 5. 删除用户
curl -X DELETE http://localhost:8080/api/users/1
七、Cursor 使用技巧总结
7.1 Prompt 编写技巧
┌─────────────────────────────────────────────────────────┐
│ ✅ 好的 Prompt │ ❌ 差的 Prompt │
├───────────────────────────────┬──────────────────────────┤
│ "用 MyBatis-Plus 写,雪花算法ID" │ "写一个用户管理" │
│ "返回 Result<T> 包装" │ "给我代码" │
│ "校验用户名唯一,邮箱格式" │ "加上校验" │
│ "只更新非空字段" │ "写 update 方法" │
│ "分页查询,按创建时间倒序" │ "查询所有用户" │
└───────────────────────────────┴──────────────────────────┘
7.2 Cursor Debug 技巧
当代码有 bug 时,不要直接让 Cursor "帮我修"。正确做法:
Step 1: 先自己看报错信息,理解错误原因
Step 2: 在 Cursor Chat 中粘贴报错日志
Step 3: 告诉 Cursor 你已经做了什么排查
Step 4: 让 Cursor 给出修复建议,而不是直接给完整代码
示例 Prompt:
"用户创建时报错 DuplicateKeyException,我已经检查了数据库确实有唯一索引。
但我的代码里有校验用户名唯一性,为什么还会报这个错?
我的校验逻辑是:[粘贴代码]。帮我看看问题在哪。"
7.3 效率对比
┌─────────────────────────────────────────────────────┐
│ 传统开发 vs Cursor 开发(本项目管理API) │
├──────────────┬──────────────┬───────────────────────┤
│ 步骤 │ 传统方式 │ Cursor 辅助 │
├──────────────┼──────────────┼───────────────────────┤
│ 创建项目 │ 10分钟 │ 2分钟(自动生成) │
│ 写实体类 │ 15分钟 │ 1分钟(Prompt生成) │
│ 写 Mapper │ 5分钟 │ 30秒 │
│ 写 Service │ 40分钟 │ 5分钟(Prompt+微调) │
│ 写 Controller │ 20分钟 │ 3分钟 │
│ 写 DTO/VO │ 15分钟 │ 2分钟 │
│ 写异常处理 │ 15分钟 │ 3分钟 │
│ 写测试 │ 30分钟 │ 5分钟 │
│ 调试Bug │ 30分钟 │ 10分钟 │
├──────────────┼──────────────┼───────────────────────┤
│ 总计 │ ~3小时 │ ~30分钟 │
└──────────────┴──────────────┴───────────────────────┘
八、踩坑记录
踩坑1:MyBatis-Plus 分页不生效
忘记配置分页插件,分页查询返回的是全部数据。
java
// ❌ 忘记加这个配置
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
踩坑2:逻辑删除和查询冲突
配置了 @TableLogic 后,selectById 会自动加 is_deleted=0 条件。如果需要查包含已删除的数据,需要手写 SQL。
踩坑3:Cursor 生成的 import 可能缺失
Cursor 有时不会自动添加所有 import,特别是自定义的类。编译报错后让 Cursor "帮我修复 import" 即可。
🎉 总结 :Cursor 最大的价值不是"帮你写代码",而是把你的想法快速变成可运行的代码,让你把精力放在架构设计和业务逻辑上。用对 Prompt,效率可以提升 5-10 倍。
如果觉得有帮助,点赞 + 收藏支持一下!有问题欢迎评论区讨论 💬