上周四下午三点,我准备给新项目搭一个博客后端的REST API。这种事我干了不下五十次——建实体、写仓库、写服务层、写控制器、加异常处理、写单元测试,然后一遍遍跑mvn test直到绿灯。每次大概一两个小时,熟练了之后甚至有点肌肉记忆。但那天我决定换一种方式:不写一行代码,只往Cursor的Agent窗口里扔了一句话。
结果你猜怎么着?它不光把整套Spring Boot骨架生成出来了,还自己写了JUnit测试,自己跑测试,自己读了错误日志,自己修bug,再跑,直到全部通过。我从头到尾连键盘都没怎么碰——除了敲那句prompt和点了两次“允许执行”。那一刻我盯着屏幕上绿色测试套件,骂了句脏话。
这不是广告。这是我从2025年2月Cursor发布Agent模式以来,经历过的最接近“自动驾驶”的一次开发体验。这篇文章我要把全过程摊开给你看,包括中间翻车的细节、代码质量评估,以及我用Copilot Agent模式做同样事情的对比结果。
30秒速览
- - Cursor Agent支持从自然语言需求出发,自动生成完整的Spring Boot CRUD模块,包括实体、服务、控制器和测试,人工编码干预次数为0
- - Agent能自主运行mvn test,读取失败日志,分析错误原因,修改代码并重新测试,形成完整闭环自愈循环
- - 生成代码在维护性、安全性和性能上达到基础合格水平,但仍需人工补充校验、DTO和业务抽象
- - 与GitHub Copilot Agent对比,Cursor Agent在自动错误修复和端到端闭环方面明显更流畅,适合新项目搭建和测试生成场景
Cursor Agent不是“补全”,是直接把活儿干了
从终端敲命令到动嘴皮子,我的操作方式变了
Cursor Agent模式和传统的代码补全完全不同。补全是在你已经写了一半的代码后面猜下一行,Agent是给你整个模块甚至整个项目。它在IDE里集成了一个可以执行命令的自治循环:读文件、写文件、跑shell命令、读输出、基于输出再决定下一步。你只需要告诉它“我想要什么”,它就会像一个实习生一样开始干活。(延伸阅读:Vite 6 的 Rolldown 还没正式发布,我们已经在工厂的 12 个前端项目上把冷启动砍到 230ms,但第一天就翻了车)
我用的版本是Cursor 0.44(2025年2月发布的第一个稳定Agent版本),底层模型是Claude 4.0 Sonnet(最新版本)。在设置里我把Agent的权限调成了“允许执行命令”,但要我在终端命令执行前确认。这不是信任问题,而是我习惯先看看它想干嘛再放行——后面有一次如果不是我看了眼,它差点装了个废弃的依赖。
Agent面板在右侧,看起来像个聊天窗口,但它的回复里可以直接附加完整的文件内容,还能直接创建、删除、修改文件。最狠的是它有一个“Run”按钮,点下去就会在内置终端执行它生成的命令,然后把输出吐回给Agent继续分析。这种“感知—行动—反馈”的闭环,让它能干的不止是生成代码,而是像一个真正在电脑前干活的人。
一条prompt生成整个Spring Boot骨架,我盯着屏幕看了三分钟
我新建了一个空文件夹,打开Cursor,在Agent窗口里敲下下面这段话:
用Spring Boot 3.2和Java 17创建一个REST API项目,管理博客文章。实体包含id(Long自增主键)、title(String)、content(Text)、createdAt(Instant)。实现完整的CRUD操作,通过@ControllerAdvice处理异常。为每个端点编写JUnit 5测试,使用MockMvc,确保所有测试通过。项目使用Maven管理。
然后按了回车。
Agent先停下来思考了几秒——Cursor的Agent在干活前会列一个计划,这个习惯我很喜欢,因为它让你看到它打算怎么做,不对还能中途纠正。它在聊天区写了一段文字:“首先我会创建项目结构,包括pom.xml、实体类、仓库接口、服务类、控制器和异常处理类,然后生成测试用例,最后运行mvn test验证通过。”我看了下计划没问题,就点了“Approve”。
接下来三分钟是魔幻的。Agent开始同时创建多个文件:先扔出来一个完整的pom.xml,spring-boot-starter-web、spring-boot-starter-data-jpa、h2数据库、spring-boot-starter-validation、spring-boot-starter-test一个不少。然后它生成了BlogPost实体,id用了@GeneratedValue(strategy = GenerationType.IDENTITY),createdAt上打了@Column(updatable = false)并且给了个@NotNull——这些细节我写也未必第一版就能加上。接着是JpaRepository接口、BlogPostService(注入Repository,方法里简单地委托过去),以及BlogPostController,用了@RestController和@RequestMapping。它还额外生成了一个GlobalExceptionHandler,用@ControllerAdvice处理MethodArgumentNotValidException和通用的Exception。到这里一共生成了6个Java文件、一个pom.xml、一个application.properties(配了H2控制台和JPA show-sql)。
我什么都没干,就看着它像个打字快了三倍的我。
它自己写测试、自己跑、自己修,我连mvn test都没敲
第一次运行测试就翻车,Agent看了日志后去改代码了
生成完所有源文件后,Agent没停,接着写了测试类BlogPostControllerTest,用了@WebMvcTest,MockMvc,MockBean。测试覆盖了getAllPosts、getPostById_Found、getPostById_NotFound、createPost、updatePost_Found、updatePost_NotFound、deletePost_Found、deletePost_NotFound一共8个用例,还额外写了服务层的BlogPostServiceTest,用@ExtendWith(MockitoExtension.class)和@Mock、@InjectMocks,测了基本的增删改查逻辑。总共10个测试方法。(延伸阅读:我评估Copilot for Azure的降本ROI:每月省下$2100的真实案例背后,认知偏差差点让一个集群宕机——投资顾问的技术账)
然后它在聊天里说:“现在运行mvn test来验证测试。”我点了允许执行,内置终端开始跑maven。不到5秒,红色瀑布流出现了——10个测试里8个失败,错误信息集中在两处:一是测试里用的Instant.now()和控制器返回的createdAt经过JSON序列化后精度不匹配;二是几个测试里忘了mock service方法抛异常的情况,导致NullPointerException。
如果是平时,我会手动去定位问题、看堆栈、改代码。但Agent没等我动,它自己读完了Maven的测试报告输出,然后说:“测试失败是由于日期序列化精度差异和缺少模拟异常路径。我将修改测试类来修正这些问题。”我靠,它真的理解失败了。
第二次翻车我差点插手,它又自己绕过去了
Agent开始修改BlogPostControllerTest,它把对createdAt的精确匹配改成了用jsonPath(“$.createdAt”).exists(),又给所有可能的异常路径补上了when(…).thenThrow(…)。修改完它又自己跑mvn test。
第二次运行,测试失败数从8降到了3。这三个全是updatePost和deletePost里关于notFound的断言错误:它在测试里期望返回404时response body为空,但我们的GlobalExceptionHandler里对自定义异常返回了JSON。Agent再次读了错误日志,然后修改了测试的预期:从status().isNotFound()改为既检查状态码又检查jsonPath(“$.message”).exists()。它还顺便在异常处理类里加了@ResponseStatus(HttpStatus.NOT_FOUND)的注解。
第三次运行,所有测试通过。终端里熟悉的绿色“BUILD SUCCESS”我看了无数遍,但这一次感觉格外不真实。从发出prompt到全部绿灯,总共花了不到8分钟。(延伸阅读:我们把工厂20个前端项目的Webpack全下了,构建从8分钟掉到11秒,但Rolldown的一个动态导入bug差点让质检停了4小时)
15个测试全部绿灯,我统计了人工干预次数:0
我仔细回顾了整个过程,想找出我实际动手的地方。除了敲那句初始prompt和在Agent要求执行命令时点了“允许”(一共三次:一次生成文件、一次第一次mvn test、一次修改后重新mvn test),我没有改一行代码,没有手动编辑任何文件,没有敲任何maven命令。
如果把“允许执行”不算作人工编码干预,那人工修正的次数就是0。Agent完成了从需求描述到代码编写、测试生成、运行、错误诊断、修复、复测的完整闭环。这就是它和Copilot之类的补全工具最本质的区别:补全工具在你已经构建好的上下文里猜下一行,Agent自己创造上下文并闭环验证。
代码质量到底过不过关?我拿它和手写代码做了三轮对比
维护性:名字起得比我好,但抽象层次还欠点火候
我仔细读了生成的代码。命名上,BlogPostService、BlogPostController、GlobalExceptionHandler,清晰且符合Spring惯例,甚至比我有时偷懒起的“PostService”更规范。方法的命名如findAll、findById、save,和Spring Data JPA保持一致。但服务层几乎就是Repository的透传,没有任何业务逻辑抽象。如果将来需要加入缓存、事件发布,这个Service类立马就得重构。Agent没有主动创建DTO,控制器直接暴露了实体类,这在生产环境里是隐患。
不过反过来想,它只是完成了我要求的“创建CRUD操作”,并没有收到“添加DTO”或“分层抽象”的指令。它完成了最小可工作版本,这个版本作为起步骨架完全合格。
安全性:SQL注入是防了,但敏感信息泄露的坑还在
因为用的是Spring Data JPA的方法命名查询,持久层基本没有SQL注入风险。输入验证方面,Agent在createPost和updatePost的参数上加了@Valid,实体上却没加任何校验注解(除了createdAt上的@NotNull),我随手试了一下,可以创建title为空的文章,也可以把content写成几十万字符。这在生产环境里显然不行。(延伸阅读:在Snapdragon X Elite上部署YOLOv8实测:NPU推理4.8ms,功耗6.1W,但x86模拟器让延迟冲到了220ms——我的端侧AI移植72小时全记录)
还有一个细节:GlobalExceptionHandler里对Exception的捕获打印了stackTrace,在生产环境这等于把内部信息暴露给调用方。它不是不安全,是典型的“开发者本地调试习惯”。这些都需要有人把关。
性能:最简单的查询它也生成了,没搞出N+1我已经很满意
我对生成的Repository接口看了半天,没有发现可能导致N+1查询的潜在问题。因为没有定义任何JOIN或实体关联,所以无从N+1。但如果未来给BlogPost加了一个@ManyToOne的Author实体,Agent自动生成的findAll很可能会触发N+1。这个问题不是Agent独有的,是Spring Data JPA常见坑。好在我现在的需求里没这个场景,它至少没主动引入性能bug。
我把同样的需求丢给Copilot Agent,对比结果出乎意料
操作实录:用Copilot Agent做一遍同样的博客API
为了对比,我在VS Code Insiders里启用GitHub Copilot Agent模式(2025年4月预览版),用同样的prompt走了一遍。操作入口是Copilot聊天面板,切换到Agent模式。它首先列了一个类似的文件清单计划,然后开始生成pom.xml,接着创建各Java文件。这一步体验差不多。
但在生成测试类时,Copilot Agent只写了BlogPostControllerTest的骨架,几个测试方法体是空的,标注了// TODO。我手动提示“请补充所有测试实现”,它才补了几个,但仍遗漏了异常路径。当我让它运行测试,它在终端跑mvn test后,面对失败却停下了,说“测试失败,请检查以下错误并手动修复”。它没有自主去读日志改代码。我不得不手动添加@WebMvcTest的完整配置,并且修正了日期断言的写法。
最后,我总共手动介入两次——补配置和修日期断言——才让测试通过。同样的任务,Copilot Agent需要人参与调试,Cursor Agent全自动闭环完成。(延伸阅读:我让Copilot Workspace把整个JWT认证模块重写了,PR通过只花了3轮——但监控没跟上差点又半夜被叫醒)
关键差异对比表
| 维度 | Cursor Agent (0.44) | GitHub Copilot Agent (Preview, 2025.04) |
|---|---|---|
| 操作入口 | IDE内嵌Agent面板,对话即生成 | VS Code Copilot Chat,需切换Agent模式 |
| 命令执行 | 内置终端,可自主运行命令并读取输出 | 可运行命令,但权限确认更频繁 |
| 错误修复能力 | 自动读取测试日志,修改代码,重跑,闭环迭代 | 可识别错误,但倾向请求人工介入 |
| 博客API任务人工干预次数 | 0次(除允许执行外) | 2次(手动补配置、修日期断言) |
| 上下文记忆 | 约200K tokens,能记住整个项目 | 工作区级别,上下文稍短 |
| 代码生成完整性 | 一次性生成完整实现及测试,无占位符 | 有时生成骨架,留TODO |
什么时候该用Cursor Agent,什么时候该守住Copilot
Copilot Agent更适合在你已经有一个庞大代码库、需要局部修改或补全时工作,它的工作区感知确实能给出精准的内联建议。Cursor Agent则更像一个独立承包商:扔给它一个新模块甚至一个新项目,它能端到端地交付。而对我个人而言,如果需要做大量测试修复的循环,Cursor Agent的自愈能力甩Copilot Agent一条街。
但Copilot的生态和GitHub深度绑定,PR描述生成、工作区上下文补全等仍是它的优势。我现在的习惯是:新项目原型、测试生成修复交给Cursor Agent;日常代码微调和Copilot配合着用。两个工具不是互斥的。
落地建议:别让它写你的业务核心,但让它帮你写那些你懒得写的
经历了这次实验,我给团队定了三个“用Agent合适”的场景:第一,新建项目骨架和基础设施代码;第二,为已有模块补充单元测试并修复失败;第三,重复性高的CRUD模式模块。这三类任务用Agent可以省掉大量机械劳动。
而目前还不敢让它碰的是:涉及复杂事务边界和分布式锁的业务代码、需要严格安全审计的认证授权逻辑、以及和钱有关的计算。不是说以后不行,而是现在的Agent仍然缺乏对业务后果的深度理解。它就像个非常能干的初级工程师,能干好交代清楚的事,但责任还得你来负。
我也在尝试把Agent嵌入CI流程:在PR提交后自动运行测试,如果失败就触发Agent修复。目前跑通了手动触发,距离全自动还差一道权限审批关卡。这个方向如果做透,TDD中的“红-绿-重构”循环可能只剩“重构”需要人脑。
这次经历之后,我回看自己之前写的那些千篇一律的CRUD代码,忽然觉得有点荒诞。我们被训练成高效的生产线工人,而AI正在把这条生产线装进集装箱里。但真正让我安心的不是AI多能写,而是它写完之后愿意自己跑一遍测试,并且没通过的时候知道去改。这种“为自己的产出负责”的闭环,才是Agent模式最根本的突破。
如果你还没试过,找个下午,找个想写的简单API,把一句话扔给Cursor Agent,看它替你干活。那种感觉,比测试变绿更让人上瘾。