插件开发没那么可怕:一个全职妈妈的IDEA插件实战手记

队列在排队
2025-12-21 03:49
阅读 760

上周五晚上十点半,娃终于睡了。我蹑手蹑脚摸到书房,打开MacBook Pro,准备处理一下白天被各种“妈妈、妈妈”打断的工作。结果刚打开IDEA,就看到产品又在群里@我:“能不能加个快捷生成SpringBoot Controller模板的功能?明天上线前要!”——好家伙,明天上线,今晚提需求,这熟悉的配方。

但说实话,这次我没像以前那样翻白眼。因为上个月我刚啃完IntelliJ平台插件开发文档,正好拿这个需求练练手。边带娃边写代码的日子不容易,但如果能写个插件把重复劳动自动化掉,那多出来的每一分钟都是赚的。

为什么我要学做IDE插件?

其实最早是被逼的。去年双11大促前,团队疯狂迭代,我负责的几个SpringBoot微服务项目里,Controller层的样板代码写到手软。GET、POST、参数校验、日志打印……每次都要复制粘贴改名字,稍不注意就漏了@Valid或者ResponseEntity包装。有次上线后发现某个接口没加权限校验,差点背锅。

当时就想:IDE天天用,为啥不能让它帮我干点活?于是抽空研究了一下IntelliJ的插件体系,发现其实没想象中那么高不可攀——尤其对于熟悉Java和Spring生态的开发者来说,门槛比写VSCode插件还低一点(别打我,Mac党偏见)。

从零开始:我的第一个SpringBoot辅助插件

环境准备

首先得装IntelliJ Platform Plugin SDK。别被名字吓到,其实就是个Gradle插件。在build.gradle里加上:

plugins {
    id 'java'
    id 'org.jetbrains.intellij' version '1.13.3'
}

intellij {
    version = '2023.2.1'
    plugins = ['com.intellij.java']
}

注意:别用Windows开发!虽然官方说支持,但我试过几次路径分隔符和文件监听器各种抽风。Mac+JetBrains全家桶才是舒适区。

核心逻辑:怎么让插件理解SpringBoot?

我想实现的功能很简单:右键点击一个Service类,自动生成对应的Controller,包含标准的RESTful接口、DTO转换、异常处理等。

关键在于如何识别SpringBoot项目结构。IntelliJ的PSI(Program Structure Interface)提供了强大的代码分析能力。通过PsiClass可以拿到类的所有注解、方法、字段。

比如判断一个类是不是Spring Service:

private boolean isSpringService(PsiClass psiClass) {
    return Arrays.stream(psiClass.getAnnotations())
        .anyMatch(annotation -> 
            "org.springframework.stereotype.Service".equals(annotation.getQualifiedName())
        );
}

然后遍历它的public方法,提取参数类型、返回值,再套进预设的模板里。

模板引擎选型:FreeMarker vs Velocity

一开始我用FreeMarker,结果发现IntelliJ自带Velocity支持,而且社区插件基本都用它。果断切过去。模板文件放在resources/templates/controller.vm

@RestController
@RequestMapping("/api/${className.toLowerCase()}")
public class ${className}Controller {

    @Autowired
    private ${className}Service service;

#if($method)
    @PostMapping
    public ResponseEntity<${returnType}> create(@Valid @RequestBody ${paramType} request) {
        // TODO: add business logic
        return ResponseEntity.ok(service.${methodName}(request));
    }
#end
}

变量替换靠VelocityEngine,几行代码搞定。

踩过的坑:那些让我想砸电脑的瞬间

坑1:上下文感知太弱

第一次测试时,插件在非Spring项目里也能右键生成Controller,结果导入了一堆不存在的包。后来才明白,得先判断当前项目是否包含spring-boot-starter-web依赖。

解决方案:通过ModuleRootManager拿到模块依赖,检查是否存在Spring相关jar:

private boolean hasSpringWeb(Module module) {
    var rootManager = ModuleRootManager.getInstance(module);
    return Arrays.stream(rootManager.getOrderEntries())
        .filter(entry -> entry instanceof LibraryOrderEntry)
        .map(entry -> ((LibraryOrderEntry) entry).getLibrary())
        .filter(Objects::nonNull)
        .flatMap(lib -> Arrays.stream(lib.getFiles(OrderRootType.CLASSES)))
        .anyMatch(file -> file.getName().contains("spring-web"));
}

坑2:UI卡死

有次在生成代码时直接操作PSI树,结果整个IDEA卡住十几秒。查文档才发现:所有PSI修改必须在Write Action中执行

赶紧改成:

WriteCommandAction.runWriteCommandAction(project, () -> {
    // 在这里安全地修改代码
    PsiFile controllerFile = ...;
    controllerFile.navigate(true);
});

坑3:测试太难

插件测试不像普通单元测试。IntelliJ提供了LightPlatformTestCase,但调试起来很麻烦。我的土办法是:写个最小化demo项目,用runIde任务启动沙盒IDE,然后手动测试。虽然原始,但胜在直观。

效果如何?真的省时间吗?

当然!现在我右键Service类,选“Generate SpringBoot Controller”,3秒内生成完整接口,连Swagger注解都配好了。上周帮新来的实习生配置环境,他看我演示完直接惊呼:“这比Postman还快!”

更重要的是,标准化了团队代码风格。以前每个人写的Controller五花八门,现在统一模板,CR(Code Review)时再也不用纠结格式问题。

顺手做了个对比:

场景 手动编写 插件生成
平均耗时 8-12分钟 <30秒
出错率 高(漏注解/校验) 接近0
团队一致性

给想入门的朋友几点建议

  1. 从小功能做起:别一上来就想做个智能AI助手。先试试“一键生成toString”这种小需求。
  2. 善用IntelliJ内置功能:很多基础能力(如代码补全、导航)框架已经封装好,别重复造轮子。
  3. 关注用户反馈:我把插件发到公司内部市场后,同事提了十几个优化点,比如支持Lombok、兼容Kotlin等。这些真实需求比文档有用多了。
  4. 别怕发布:JetBrains插件市场审核其实挺宽松,只要不搞恶意代码。我的插件现在每天有200+次下载,虽然不多,但每次看到用户评论“救我狗命”,就觉得值了。

最后:全职妈妈也能玩转底层技术

很多人觉得带娃后技术会退步,其实未必。碎片时间反而逼我更聚焦——既然每天只有2小时编码时间,那就必须高效。研究插件开发这种“杠杆率高”的技能,一次投入长期受益。

昨天娃趴在我键盘上乱按,不小心触发了插件快捷键,自动生成了个HelloWorldController。他指着屏幕喊:“妈妈,你做的机器人!” —— 嗯,这大概就是程序员妈妈的浪漫吧。

如果你也在被重复劳动折磨,不妨试试写个插件。说不定下次产品半夜提需求时,你能笑着回他:“已通过插件自动化,无需人工介入。”

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝