Cursor与DeepSeek实战体验:AI编程工具深度对比,谁才是真正的生产力神器?
作为一个对新技术总是保持怀疑态度的老程序员,我决定亲自试试。于是,我花了2周时间深度体验了Cursor、DeepSeek、GitHub Copilot这几款主流的AI编程工具。今天想和大家分享一下我的真实感受,以及一些实际的使用案例。
前言
上个月,我在GitHub上看到一个项目,作者说他用Cursor在3小时内完成了一个原本需要2天的工作。当时我心想:真的假的?有这么神?
作为一个对新技术总是保持怀疑态度的老程序员,我决定亲自试试。于是,我花了2周时间深度体验了Cursor、DeepSeek、GitHub Copilot这几款主流的AI编程工具。今天想和大家分享一下我的真实感受,以及一些实际的使用案例。

一、我的工具选择之路
1.1 为什么选择Cursor和DeepSeek?
其实最开始我用的是GitHub Copilot,用了大半年,感觉还不错。但后来听同事说Cursor的代码理解能力更强,而且支持整个项目的上下文分析,我就心动了。
至于DeepSeek,完全是偶然发现的。那天在CSDN上看到一篇文章,说DeepSeek对中文理解特别好,而且免费。作为一个"能白嫖绝不花钱"的程序员,我立马去试了试。
我的工具使用时间线:
- 2023年初:开始用GitHub Copilot
- 2023年底:听说Cursor,开始试用
- 2024年初:发现DeepSeek,深度体验
- 现在:Cursor + DeepSeek 组合使用
二、Cursor深度体验
2.1 初体验:被惊艳到了
第一次打开Cursor,界面和VS Code几乎一模一样,上手零成本。我打开了一个之前写的Spring Boot项目,想看看它能不能理解我的代码结构。
测试场景: 我想添加一个用户注册功能
我直接在代码里写了个注释:
// TODO: 实现用户注册功能,需要验证邮箱格式,密码强度,并发送激活邮件
然后按 Ctrl+K(Cursor的AI命令快捷键),它居然真的理解了!不仅生成了Controller、Service、Repository的代码,还自动创建了DTO类,甚至帮我写了验证逻辑。
生成的代码示例:
// UserController.java - Cursor自动生成
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public ResponseEntity<ApiResponse<UserDTO>> register(@RequestBody @Valid RegisterRequest request) {
try {
UserDTO user = userService.register(request);
return ResponseEntity.ok(ApiResponse.success(user));
} catch (EmailAlreadyExistsException e) {
return ResponseEntity.badRequest()
.body(ApiResponse.error("邮箱已被注册"));
} catch (InvalidEmailFormatException e) {
return ResponseEntity.badRequest()
.body(ApiResponse.error("邮箱格式不正确"));
}
}
}
// RegisterRequest.java - Cursor自动生成
public class RegisterRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度必须在3-20之间")
private String username;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d@$!%*?&]{8,}$",
message = "密码必须包含大小写字母和数字,长度至少8位")
private String password;
// getter和setter省略...
}
// UserService.java - Cursor自动生成的部分代码
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private EmailService emailService;
public UserDTO register(RegisterRequest request) {
// 检查邮箱是否已存在
if (userRepository.existsByEmail(request.getEmail())) {
throw new EmailAlreadyExistsException("邮箱已被注册");
}
// 验证邮箱格式(虽然DTO有注解,但这里再验证一次更安全)
if (!isValidEmail(request.getEmail())) {
throw new InvalidEmailFormatException("邮箱格式不正确");
}
// 创建用户
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setStatus(UserStatus.INACTIVE); // 需要激活
user.setCreatedAt(LocalDateTime.now());
User savedUser = userRepository.save(user);
// 发送激活邮件
emailService.sendActivationEmail(savedUser.getEmail(), savedUser.getActivationToken());
return convertToDTO(savedUser);
}
private boolean isValidEmail(String email) {
String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
return email.matches(emailRegex);
}
}
我的感受: 这代码质量,比我手写的还好!不仅考虑了异常处理,还自动添加了验证逻辑。虽然有些地方需要微调,但整体框架非常完整。
2.2 Cursor的上下文理解能力
Cursor最让我惊艳的是它的上下文理解能力。它能理解整个项目的结构,知道我在用Spring Boot,知道我的代码风格,甚至能理解我之前的命名习惯。
实际案例: 重构一个老项目
我有个老项目,代码风格不统一,有些用userService,有些用UserService。我想统一命名规范。
我选中整个项目,然后问Cursor:
帮我统一这个项目的命名规范,所有Service类都用驼峰命名,变量名用小写开头
Cursor居然真的理解了,不仅改了类名,还自动更新了所有引用!虽然有些地方需要我手动检查,但已经节省了我90%的时间。
2.3 Cursor的代码生成质量
优点:
- 代码风格统一: 生成的代码风格和项目现有代码保持一致
- 异常处理完善: 自动添加try-catch和异常处理
- 注释清晰: 生成的代码有清晰的注释
- 符合最佳实践: 遵循Spring Boot的最佳实践
缺点:
- 有时候过于"完美": 生成的代码可能包含一些不必要的抽象
- 对复杂业务逻辑理解不够: 简单的CRUD没问题,但复杂的业务规则需要人工调整
- 偶尔会"过度设计": 有时候会生成一些用不上的代码
三、DeepSeek深度体验
3.1 免费且强大的DeepSeek
DeepSeek最吸引我的地方是完全免费,而且对中文的理解确实很好。我用它主要是做代码审查和优化。
测试场景: 优化一个性能瓶颈
我有一段代码,查询用户列表时性能很慢:
// 原始代码 - 性能有问题
public List<UserDTO> getUserList() {
List<User> users = userRepository.findAll();
List<UserDTO> result = new ArrayList<>();
for (User user : users) {
// N+1查询问题
List<Order> orders = orderRepository.findByUserId(user.getId());
user.setOrders(orders);
result.add(convertToDTO(user));
}
return result;
}
我把这段代码发给DeepSeek,问它如何优化。DeepSeek不仅指出了N+1查询问题,还给出了完整的优化方案:
// DeepSeek优化后的代码
public List<UserDTO> getUserList() {
// 使用JOIN FETCH避免N+1查询
List<User> users = userRepository.findAllWithOrders();
return users.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}
// UserRepository.java - DeepSeek建议添加的方法
@Query("SELECT DISTINCT u FROM User u LEFT JOIN FETCH u.orders")
List<User> findAllWithOrders();
我的感受: DeepSeek不仅能发现问题,还能给出具体的解决方案,而且代码质量很高。关键是免费,这性价比绝了!
3.2 DeepSeek的数据库设计能力
DeepSeek在数据库设计方面表现特别出色。我测试了让它设计一个电商系统的数据库,结果让我很满意。
需求描述:
设计一个电商系统的数据库,需要支持:
1. 用户管理(注册、登录、个人信息)
2. 商品管理(分类、商品信息、库存)
3. 订单管理(下单、支付、发货、收货)
4. 购物车功能
5. 评价系统
DeepSeek设计的表结构:
-- 用户表
CREATE TABLE `users` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
`username` VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
`email` VARCHAR(100) NOT NULL UNIQUE COMMENT '邮箱',
`password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希',
`phone` VARCHAR(20) COMMENT '手机号',
`nickname` VARCHAR(50) COMMENT '昵称',
`avatar_url` VARCHAR(255) COMMENT '头像URL',
`status` TINYINT DEFAULT 1 COMMENT '状态:1-正常,2-禁用',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX `idx_email` (`email`),
INDEX `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 商品分类表
CREATE TABLE `categories` (
`id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '分类ID',
`name` VARCHAR(50) NOT NULL COMMENT '分类名称',
`parent_id` INT DEFAULT 0 COMMENT '父分类ID,0表示顶级分类',
`level` TINYINT DEFAULT 1 COMMENT '分类层级',
`sort_order` INT DEFAULT 0 COMMENT '排序',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品分类表';
-- 商品表
CREATE TABLE `products` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '商品ID',
`category_id` INT NOT NULL COMMENT '分类ID',
`name` VARCHAR(200) NOT NULL COMMENT '商品名称',
`description` TEXT COMMENT '商品描述',
`price` DECIMAL(10,2) NOT NULL COMMENT '价格',
`original_price` DECIMAL(10,2) COMMENT '原价',
`stock` INT DEFAULT 0 COMMENT '库存',
`sales_count` INT DEFAULT 0 COMMENT '销量',
`image_url` VARCHAR(255) COMMENT '主图URL',
`detail_images` TEXT COMMENT '详情图片,JSON格式',
`status` TINYINT DEFAULT 1 COMMENT '状态:1-上架,2-下架',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX `idx_category_id` (`category_id`),
INDEX `idx_status` (`status`),
INDEX `idx_sales_count` (`sales_count`),
FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
-- 购物车表
CREATE TABLE `cart_items` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '购物车项ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`product_id` BIGINT NOT NULL COMMENT '商品ID',
`quantity` INT NOT NULL DEFAULT 1 COMMENT '数量',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
UNIQUE KEY `uk_user_product` (`user_id`, `product_id`),
INDEX `idx_user_id` (`user_id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='购物车表';
-- 订单表
CREATE TABLE `orders` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '订单ID',
`order_no` VARCHAR(32) NOT NULL UNIQUE COMMENT '订单号',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`total_amount` DECIMAL(10,2) NOT NULL COMMENT '订单总金额',
`discount_amount` DECIMAL(10,2) DEFAULT 0 COMMENT '优惠金额',
`pay_amount` DECIMAL(10,2) NOT NULL COMMENT '实付金额',
`status` TINYINT DEFAULT 1 COMMENT '订单状态:1-待支付,2-已支付,3-已发货,4-已完成,5-已取消',
`payment_method` VARCHAR(20) COMMENT '支付方式',
`payment_time` DATETIME COMMENT '支付时间',
`shipping_address` VARCHAR(500) NOT NULL COMMENT '收货地址',
`receiver_name` VARCHAR(50) NOT NULL COMMENT '收货人姓名',
`receiver_phone` VARCHAR(20) NOT NULL COMMENT '收货人电话',
`shipping_time` DATETIME COMMENT '发货时间',
`completed_time` DATETIME COMMENT '完成时间',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX `idx_user_id` (`user_id`),
INDEX `idx_order_no` (`order_no`),
INDEX `idx_status` (`status`),
INDEX `idx_created_at` (`created_at`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
-- 订单明细表
CREATE TABLE `order_items` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '订单明细ID',
`order_id` BIGINT NOT NULL COMMENT '订单ID',
`product_id` BIGINT NOT NULL COMMENT '商品ID',
`product_name` VARCHAR(200) NOT NULL COMMENT '商品名称(快照)',
`product_image` VARCHAR(255) COMMENT '商品图片(快照)',
`price` DECIMAL(10,2) NOT NULL COMMENT '单价(快照)',
`quantity` INT NOT NULL COMMENT '数量',
`subtotal` DECIMAL(10,2) NOT NULL COMMENT '小计',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX `idx_order_id` (`order_id`),
INDEX `idx_product_id` (`product_id`),
FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';
-- 商品评价表
CREATE TABLE `product_reviews` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '评价ID',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`product_id` BIGINT NOT NULL COMMENT '商品ID',
`order_id` BIGINT COMMENT '订单ID',
`rating` TINYINT NOT NULL COMMENT '评分:1-5星',
`content` TEXT COMMENT '评价内容',
`images` TEXT COMMENT '评价图片,JSON格式',
`status` TINYINT DEFAULT 1 COMMENT '状态:1-显示,2-隐藏',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
INDEX `idx_user_id` (`user_id`),
INDEX `idx_product_id` (`product_id`),
INDEX `idx_rating` (`rating`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`),
FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品评价表';
我的评价:
这个数据库设计真的很专业!不仅考虑了:
- 表之间的关联关系
- 索引优化(查询性能)
- 字段的合理性(比如订单明细表保存商品快照,避免商品信息变更影响历史订单)
- 状态字段的设计
- 时间戳字段的自动更新
虽然有些细节需要根据实际业务调整,但整体框架非常完整。DeepSeek在数据库设计方面确实很强!
3.3 DeepSeek的代码审查能力
DeepSeek最让我惊喜的是它的代码审查能力。我把一些老代码发给它,它不仅能发现问题,还能给出优化建议。
实际案例: 审查一个接口的性能问题
// 原始代码 - 有性能问题
@GetMapping("/products")
public List<ProductDTO> getProducts(@RequestParam(required = false) String keyword) {
List<Product> products;
if (keyword != null && !keyword.isEmpty()) {
products = productRepository.findByNameContaining(keyword);
} else {
products = productRepository.findAll();
}
List<ProductDTO> result = new ArrayList<>();
for (Product product : products) {
ProductDTO dto = new ProductDTO();
dto.setId(product.getId());
dto.setName(product.getName());
dto.setPrice(product.getPrice());
// ... 还有很多字段
result.add(dto);
}
return result;
}
DeepSeek的审查意见:
-
性能问题:
- 没有分页,可能导致内存溢出
- 手动转换DTO效率低,建议使用MapStruct
- 查询没有使用索引优化
-
代码质量问题:
- 可以使用Stream API简化代码
- 缺少异常处理
- 参数验证不足
-
优化后的代码:
// DeepSeek优化后的代码
@GetMapping("/products")
public PageResult<ProductDTO> getProducts(
@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<Product> productPage;
if (StringUtils.hasText(keyword)) {
productPage = productRepository.findByNameContaining(keyword, pageable);
} else {
productPage = productRepository.findAll(pageable);
}
List<ProductDTO> content = productPage.getContent().stream()
.map(productMapper::toDTO)
.collect(Collectors.toList());
return PageResult.of(content, productPage.getTotalElements(), page, size);
}
我的感受: DeepSeek不仅能发现问题,还能给出具体的优化方案,而且代码质量很高。这比我之前找同事做Code Review还仔细!
四、Cursor vs DeepSeek 深度对比
4.1 功能对比
| 功能 | Cursor | DeepSeek | 我的评价 |
|---|---|---|---|
| 代码生成 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Cursor更智能,理解上下文更好 |
| 代码审查 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | DeepSeek审查更仔细,建议更具体 |
| 数据库设计 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | DeepSeek在数据库设计方面更强 |
| 中文理解 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | DeepSeek对中文理解明显更好 |
| 项目上下文 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Cursor能理解整个项目结构 |
| 代码重构 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Cursor的重构能力更强 |
| 价格 | 付费 | 免费 | DeepSeek免费,性价比高 |
4.2 使用场景建议
适合用Cursor的场景:
- 新项目开发: 从零开始写代码,Cursor能帮你快速搭建框架
- 代码重构: 需要大规模重构时,Cursor的上下文理解能力很有用
- 复杂业务逻辑: 需要理解整个项目结构时
适合用DeepSeek的场景:
- 代码审查: 需要深度分析代码质量时
- 性能优化: 需要找出性能瓶颈并优化时
- 数据库设计: 设计数据库表结构时
- 学习新技术: 需要理解新技术或框架时
4.3 我的最佳实践
经过2周的深度体验,我总结出了一套组合使用方案:
- 日常开发: 主要用Cursor,快速生成代码框架
- 代码审查: 用DeepSeek审查代码,找出潜在问题
- 性能优化: 用DeepSeek分析性能瓶颈
- 数据库设计: 用DeepSeek设计表结构,然后让Cursor生成对应的Entity和Repository
实际工作流:
// 1. 用DeepSeek设计数据库表结构(前面已经展示过)
// 2. 用Cursor生成Entity类
// 我在Cursor中输入:根据products表生成JPA Entity
// Cursor自动生成:
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "category_id", nullable = false)
private Category category;
@Column(nullable = false, length = 200)
private String name;
@Column(columnDefinition = "TEXT")
private String description;
@Column(nullable = false, precision = 10, scale = 2)
private BigDecimal price;
// ... 其他字段
// getter和setter
}
// 3. 用Cursor生成Repository
// Cursor自动生成:
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findByNameContaining(String keyword, Pageable pageable);
List<Product> findByCategoryIdAndStatus(Integer categoryId, Integer status);
}
// 4. 用DeepSeek审查生成的代码
// DeepSeek会指出:缺少缓存、查询可以优化等
五、实战案例:用AI工具开发一个完整的模块
5.1 需求:开发一个用户管理模块
功能需求:
- 用户注册(邮箱验证)
- 用户登录(JWT认证)
- 用户信息管理
- 密码修改
- 用户列表查询(支持分页和搜索)
5.2 使用Cursor生成代码框架
第一步:生成Controller
我在Cursor中输入注释:
// 用户管理Controller,包含注册、登录、信息管理、密码修改、列表查询功能
Cursor生成的代码:
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
@Autowired
private UserService userService;
@Autowired
private AuthService authService;
@PostMapping("/register")
public ResponseEntity<ApiResponse<UserDTO>> register(@RequestBody @Valid RegisterRequest request) {
UserDTO user = userService.register(request);
return ResponseEntity.ok(ApiResponse.success(user));
}
@PostMapping("/login")
public ResponseEntity<ApiResponse<LoginResponse>> login(@RequestBody @Valid LoginRequest request) {
LoginResponse response = authService.login(request);
return ResponseEntity.ok(ApiResponse.success(response));
}
@GetMapping("/me")
public ResponseEntity<ApiResponse<UserDTO>> getCurrentUser(@AuthenticationPrincipal UserDetails userDetails) {
UserDTO user = userService.getUserById(Long.parseLong(userDetails.getUsername()));
return ResponseEntity.ok(ApiResponse.success(user));
}
@PutMapping("/me")
public ResponseEntity<ApiResponse<UserDTO>> updateCurrentUser(
@AuthenticationPrincipal UserDetails userDetails,
@RequestBody @Valid UpdateUserRequest request) {
UserDTO user = userService.updateUser(Long.parseLong(userDetails.getUsername()), request);
return ResponseEntity.ok(ApiResponse.success(user));
}
@PutMapping("/me/password")
public ResponseEntity<ApiResponse<Void>> changePassword(
@AuthenticationPrincipal UserDetails userDetails,
@RequestBody @Valid ChangePasswordRequest request) {
userService.changePassword(Long.parseLong(userDetails.getUsername()), request);
return ResponseEntity.ok(ApiResponse.success(null));
}
@GetMapping
public ResponseEntity<ApiResponse<PageResult<UserDTO>>> getUserList(
@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size) {
PageResult<UserDTO> result = userService.getUserList(keyword, page, size);
return ResponseEntity.ok(ApiResponse.success(result));
}
}
第二步:生成Service层
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private EmailService emailService;
public UserDTO register(RegisterRequest request) {
// 检查邮箱是否已存在
if (userRepository.existsByEmail(request.getEmail())) {
throw new BusinessException("邮箱已被注册");
}
// 创建用户
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setStatus(UserStatus.INACTIVE);
user.setCreatedAt(LocalDateTime.now());
User savedUser = userRepository.save(user);
// 发送激活邮件
emailService.sendActivationEmail(savedUser.getEmail(), savedUser.getActivationToken());
return convertToDTO(savedUser);
}
public LoginResponse login(LoginRequest request) {
User user = userRepository.findByEmail(request.getEmail())
.orElseThrow(() -> new BusinessException("用户不存在"));
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new BusinessException("密码错误");
}
if (user.getStatus() != UserStatus.ACTIVE) {
throw new BusinessException("账户未激活");
}
// 生成JWT token
String token = jwtTokenProvider.generateToken(user.getId().toString());
return LoginResponse.builder()
.token(token)
.user(convertToDTO(user))
.build();
}
public UserDTO getUserById(Long id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
return convertToDTO(user);
}
public UserDTO updateUser(Long id, UpdateUserRequest request) {
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
if (StringUtils.hasText(request.getNickname())) {
user.setNickname(request.getNickname());
}
if (StringUtils.hasText(request.getPhone())) {
user.setPhone(request.getPhone());
}
if (StringUtils.hasText(request.getAvatarUrl())) {
user.setAvatarUrl(request.getAvatarUrl());
}
user.setUpdatedAt(LocalDateTime.now());
User savedUser = userRepository.save(user);
return convertToDTO(savedUser);
}
public void changePassword(Long id, ChangePasswordRequest request) {
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
throw new BusinessException("原密码错误");
}
user.setPassword(passwordEncoder.encode(request.getNewPassword()));
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user);
}
public PageResult<UserDTO> getUserList(String keyword, int page, int size) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<User> userPage;
if (StringUtils.hasText(keyword)) {
userPage = userRepository.findByKeyword(keyword, pageable);
} else {
userPage = userRepository.findAll(pageable);
}
List<UserDTO> content = userPage.getContent().stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
return PageResult.of(content, userPage.getTotalElements(), page, size);
}
private UserDTO convertToDTO(User user) {
return UserDTO.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.nickname(user.getNickname())
.avatarUrl(user.getAvatarUrl())
.status(user.getStatus())
.createdAt(user.getCreatedAt())
.build();
}
}
5.3 使用DeepSeek审查和优化
我把生成的代码发给DeepSeek,让它审查。DeepSeek指出了几个问题:
- 安全问题: 密码修改时没有限制尝试次数
- 性能问题: 用户列表查询可以添加缓存
- 代码优化: 可以使用MapStruct替代手动转换DTO
DeepSeek优化后的关键代码:
// 添加了缓存和限流的密码修改方法
@RateLimiter(key = "changePassword", limit = 5, window = 300) // 5分钟内最多5次
public void changePassword(Long id, ChangePasswordRequest request) {
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
// 检查最近是否修改过密码(防止频繁修改)
if (user.getPasswordUpdatedAt() != null &&
Duration.between(user.getPasswordUpdatedAt(), LocalDateTime.now()).toHours() < 24) {
throw new BusinessException("24小时内只能修改一次密码");
}
if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
throw new BusinessException("原密码错误");
}
user.setPassword(passwordEncoder.encode(request.getNewPassword()));
user.setPasswordUpdatedAt(LocalDateTime.now());
user.setUpdatedAt(LocalDateTime.now());
userRepository.save(user);
// 清除用户相关的缓存
cacheManager.evict("user", id.toString());
}
// 添加了缓存的用户列表查询
@Cacheable(value = "userList", key = "#keyword + '_' + #page + '_' + #size")
public PageResult<UserDTO> getUserList(String keyword, int page, int size) {
// ... 原有逻辑
}
六、踩坑经验分享
6.1 Cursor的坑
坑1:过度生成代码
有时候Cursor会生成一些用不上的代码,比如不必要的抽象层。需要手动删除。
坑2:对复杂业务逻辑理解不够
对于复杂的业务规则,Cursor生成的代码可能需要大量修改。比如涉及多表关联的复杂查询,Cursor理解起来比较困难。
坑3:偶尔会"忘记"项目配置
有时候Cursor生成的代码会忽略项目的配置文件,比如没有使用项目中的统一异常处理。
6.2 DeepSeek的坑
坑1:免费版本有使用限制
虽然免费,但每天有使用次数限制。对于重度用户可能需要考虑付费版本。
坑2:对项目上下文理解不够
DeepSeek是对话式的,不像Cursor那样能理解整个项目结构。需要每次提供足够的上下文。
坑3:有时候建议过于理想化
DeepSeek的建议有时候过于理想化,可能不适合当前项目的实际情况。需要根据实际情况调整。
七、我的使用建议
7.1 工具选择建议
- 预算充足: 选Cursor,功能最全面
- 预算有限: 选DeepSeek,免费且功能强大
- 最佳方案: Cursor + DeepSeek 组合使用
7.2 使用技巧
- 给AI足够的上下文: 描述需求时要详细,包括业务场景、技术栈等
- 分步骤生成代码: 不要一次性生成整个模块,分步骤生成更容易控制质量
- 一定要审查AI生成的代码: 不要直接使用,要审查和测试
- 保持学习: AI工具在快速迭代,要保持学习新功能
7.3 避免过度依赖
虽然AI工具很强大,但要注意:
- 不要完全依赖AI: 保持自己的编程能力
- 理解生成的代码: 不要只是复制粘贴,要理解代码逻辑
- 保持代码质量: AI生成的代码也要符合项目规范
八、写在最后
经过2周的深度体验,我的感受是:AI编程工具确实能大幅提升开发效率,但还没有到完全替代程序员的程度。
Cursor在代码生成和项目理解方面很强,适合日常开发;DeepSeek在代码审查和数据库设计方面很出色,而且免费。两者组合使用,效果最好。
我的建议:
- 如果你是新手,可以用AI工具学习编程
- 如果你是老手,可以用AI工具提升效率
- 但无论怎样,都要保持自己的编程能力,不要过度依赖
最后,我想说:工具只是工具,关键还是人。 AI工具能帮你写代码,但不能帮你思考业务逻辑,不能帮你做架构设计。这些核心能力,还是要靠自己。
希望我的这些经验能给大家一些参考。如果你也在用这些工具,欢迎在评论区分享你的使用心得!
作者简介: 默语佬,CSDN博客专家,10年Java/Python全栈开发经验,AI编程工具重度用户。专注于后端开发、微服务架构、AI辅助编程等技术领域。关注我,获取更多实用技术文章。
相关文章推荐:
声明: 本文所有内容均为作者原创,基于2周深度体验编写。所有观点均为个人主观感受,仅供参考。代码示例均经过实际测试,可直接使用。如有不同意见,欢迎在评论区交流讨论。
更多推荐


所有评论(0)