关于java:基于IDEA-Plugin插件开发撸一个DDD脚手架

6次阅读

共计 7987 个字符,预计需要花费 20 分钟才能阅读完成。

作者:小傅哥
博客:https://bugstack.cn

积淀、分享、成长,让本人和别人都能有所播种!😄

  • 最近很感兴趣联合 IDEA Plugin 开发能力,扩大各项性能。也基于此应用不同的案例,摸索 IDEA Plugin 插件开发技术。心愿这样的成体系学习和验证总结,能给更多须要此技术的搭档,带来帮忙。
  • 源码地址:https://github.com/fuzhengwei/CodeGuide#1-%E6%BA%90%E7%A0%81

一、前言

研发,要防止自嗨!

你做这个货色的价值是什么?有竞品调研吗?能赋能业务吗?那不曾经有同类的了,你为什么还本人造轮子?

你是不是也会被问到这样的问题,甚至可能还有些头疼。但做的时候挺嗨,钻研技术嘛,还落地了,多刺激。不过要说价值,如同一时半会还体现不进去,能不能赋能业务就不更不肯定了。

可谁又能保障当前不能呢,技术的点是一个个攻克尝试的才有机会再深度学习后把这些内容连成一片,就像单说水、单说沙子、单说泥巴,如同并没有啥用,但把它们凑到一块再给把火,就烧成了砖,砖就码成了墙,墙就盖成房。

二、需要目标

咱们这一章节把 freemarker 能力与 IDEA Plugin 插件能力联合,开发一个DDD 脚手架 IDEA 插件,可能你会想为什么要把脚手架开发到插件里呢?还有不是曾经有了成型的脚手架能够用吗?

首先咱们目前看到的脚手架根本都是网页版的,也就是一次性创立工程应用,不过在咱们理论应用的时候,还心愿在工程创立过程中把数据库、ES、Redis 等生成对应的 ORM 代码,缩小开发工作量。并且在应用的工程骨架的过程中,还心愿能够随着开发须要再次补充新的性能进去,这个时候网页版的脚手架都不能很好的反对了。此外一些大厂都会本人的技术体系,齐全是应用市面的脚手架根本很难满足本身的需要,所以就须要有一个合乎本人场景的脚手架了。

那么,咱们本章节就把脚手架的开发放到 IDEA 插件开发中,一方面学习脚手架的建设,另外一方面学习如何扭转工程向导,创立出本人须要的 DDD 构造脚手架。

三、案例开发

1. 工程构造

guide-idea-plugin-scaffolding
├── .gradle
└── src
    ├── main
    │   └── java
    │       └── cn.bugstack.guide.idea.plugin 
    │           ├── domain
    │           │     ├── model   
    │           │     │    └── ProjectConfigVO.java       
    │           │     └── service   
    │           │          ├── impl     
    │           │          │    └── ProjectGeneratorImpl.java  
    │           │          ├── AbstractProjectGenerator.java     
    │           │          ├── FreemarkerConfiguration.java      
    │           │          └── IProjectGenerator.java      
    │           ├── factory
    │           │      └── TemplateFactory.java  
    │           ├── infrastructure
    │           │     ├── DataSetting.java       
    │           │     ├── DataState.java  
    │           │     ├── ICONS.java      
    │           │     └── MsgBundle.java     
    │           ├── module  
    │           │     ├── DDDModuleBuilder.java    
    │           │     └── DDDModuleConfigStep.java         
    │           └── ui
    │                 ├── ProjectConfigUI.java  
    │                 └── ProjectConfigUI.form
    ├── resources
    │   ├── META-INF
    │   │   └── plugin.xml 
    │   └── template
    │       ├── pom.ftl
    │       └── yml.ftl 
    ├── build.gradle  
    └── gradle.properties

源码获取:# 公众号:bugstack 虫洞栈 回复:idea 即可下载全副 IDEA 插件开发源码

在此 IDEA 插件工程中,次要分为 5 块区域:

  • domain:畛域层,提供创立 DDD 模板工程的服务,其实这部分次要应用的就是 freemarker
  • factory:工厂层,提供工程创立模板,这一层的作用就是咱们在 IDEA 中创立新工程的时候,能够增加上咱们本人的内容,也就是创立出咱们定义好的 DDD 工程构造。
  • infrastructure:根底层,提供数据寄存、图片加载、信息映射这些性能。
  • module:模块层,提供 DDD 模板工程的创立具体操作和步骤,也就是说咱们创立工程的时候是一步步抉择的,你能够按需增加本人的步骤页面,容许用户抉择和增加本人须要的内容。比方你须要连库、抉择表、增加工程所须要的技术栈等
  • ui:界面层,提供 Swing 开发的 UI 界面,用于用户图形化抉择和创立。

2. UI 工程配置窗体

public class ProjectConfigUI {

    private JPanel mainPanel;
    private JTextField groupIdField;
    private JTextField artifactIdField;
    private JTextField versionField;
    private JTextField packageField;

}
  • 应用 Swing UI Designer 创立一个配置工厂信息的 UI 窗体,通过这样的形式创立能够间接拖拽。
  • 在这个 UI 窗体中咱们次要须要;roupIdartifactIdversionpackage

3. 配置工程步骤创立

3.1 数据寄存

cn.bugstack.guide.idea.plugin.infrastructure.DataSetting

@State(name = "DataSetting",storages = @Storage("plugin.xml"))
public class DataSetting implements PersistentStateComponent<DataState> {private DataState state = new DataState();

    public static DataSetting getInstance() {return ServiceManager.getService(DataSetting.class);
    }

    @Nullable
    @Override
    public DataState getState() {return state;}

    @Override
    public void loadState(@NotNull DataState state) {this.state = state;}

     public ProjectConfigVO getProjectConfig(){return state.getProjectConfigVO();
     }

}
  • 在根底层提供数据寄存的服务,把创立工程的配置信息寄存到服务中,这样比拟不便设置和获取。

3.2 扩大步骤

cn.bugstack.guide.idea.plugin.module.DDDModuleConfigStep

public class DDDModuleConfigStep extends ModuleWizardStep {

    private ProjectConfigUI projectConfigUI;

    public DDDModuleConfigStep(ProjectConfigUI projectConfigUI) {this.projectConfigUI = projectConfigUI;}

    @Override
    public JComponent getComponent() {return projectConfigUI.getComponent();
    }

    @Override
    public boolean validate() throws ConfigurationException {
        // 获取配置信息,写入到 DataSetting
        ProjectConfigVO projectConfig = DataSetting.getInstance().getProjectConfig();
        projectConfig.set_groupId(projectConfigUI.getGroupIdField().getText());
        projectConfig.set_artifactId(projectConfigUI.getArtifactIdField().getText());
        projectConfig.set_version(projectConfigUI.getVersionField().getText());
        projectConfig.set_package(projectConfigUI.getPackageField().getText());

        return super.validate();}

}
  • 继承 ModuleWizardStep 开发一个本人须要的步骤,这个步骤就会呈现到咱们创立新的工程中。
  • 同时在重写的 validate 办法中,把从工程配置 UI 窗体中获取到信息,写入到数据配置文件中。

3.3 配置步骤

cn.bugstack.guide.idea.plugin.module.DDDModuleBuilder

public class DDDModuleBuilder extends ModuleBuilder {private IProjectGenerator projectGenerator = new ProjectGeneratorImpl();

    @Override
    public Icon getNodeIcon() {return ICONS.SPRING_BOOT;}
    
    /**
     * 重写 builderId 挂载自定义模板
     */
    @Nullable
    @Override
    public String getBuilderId() {return getClass().getName();}
    
    @Override
    public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {

        // 增加工程配置步骤,能够本人定义须要的步骤,如果有多个能够顺次增加
        DDDModuleConfigStep moduleConfigStep = new DDDModuleConfigStep(new ProjectConfigUI());

        return new ModuleWizardStep[]{moduleConfigStep};
    }
}
  • 在 createWizardSteps 办法中,把咱们曾经创立好的 DDDModuleConfigStep 增加工程配置步骤,能够本人定义须要的步骤,如果有多个能够顺次增加。
  • 同时须要留神,只有重写了 getBuilderId() 办法后,你新减少的向导步骤能力失效。

4. 开发脚手架服务

cn.bugstack.guide.idea.plugin.domain.service.AbstractProjectGenerator

public abstract class AbstractProjectGenerator extends FreemarkerConfiguration implements IProjectGenerator {

    @Override
    public void doGenerator(Project project, String entryPath, ProjectConfigVO projectConfig) {

        // 1. 创立工程主 POM 文件
        generateProjectPOM(project, entryPath, projectConfig);

        // 2. 创立四层架构
        generateProjectDDD(project, entryPath, projectConfig);

        // 3. 创立 Application
        generateApplication(project, entryPath, projectConfig);

        // 4. 创立 Yml
        generateYml(project, entryPath, projectConfig);

        // 5. 创立 Common
        generateCommon(project, entryPath, projectConfig);
    }

}
  • 在 domain 畛域层增加用于创立脚手架框架的 FreeMarker 服务,它是一款 模板引擎:即一种基于模板和要扭转的数据,并用来生成输入文本 (HTML 网页,电子邮件,配置文件,源代码等) 的通用工具。FreeMarker 在线手册:http://freemarker.foofun.cn
  • 依照 DDD 工程构造,分层包含:application、domain、infrastructure、interfaces,那么咱们把这些创立过程形象到模板办法中,具体交给子类来创立。

5. 调用脚手架服务

cn.bugstack.guide.idea.plugin.module.DDDModuleBuilder

public class DDDModuleBuilder extends ModuleBuilder {private IProjectGenerator projectGenerator = new ProjectGeneratorImpl();

    @Override
    public Icon getNodeIcon() {return ICONS.SPRING_BOOT;}

    @Override
    public void setupRootModel(@NotNull ModifiableRootModel rootModel) throws ConfigurationException {

        // 设置 JDK
        if (null != this.myJdk) {rootModel.setSdk(this.myJdk);
        } else {rootModel.inheritSdk();
        }

        // 生成工程门路
        String path = FileUtil.toSystemIndependentName(Objects.requireNonNull(getContentEntryPath()));
        new File(path).mkdirs();
        VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
        rootModel.addContentEntry(virtualFile);

        Project project = rootModel.getProject();

        // 创立工程构造
        Runnable r = () -> new WriteCommandAction<VirtualFile>(project) {
            @Override
            protected void run(@NotNull Result<VirtualFile> result) throws Throwable {projectGenerator.doGenerator(project, getContentEntryPath(), DataSetting.getInstance().getProjectConfig());
            }
        }.execute();}

}
  • DDDModuleBuilder#setupRootModel 中,增加创立 DDD 工程框架 的服务,projectGenerator.doGenerator(project, getContentEntryPath(), DataSetting.getInstance().getProjectConfig());
  • 另外这里须要用到 IDEA 提供的线程调用办法,new WriteCommandAction 能力失常创立。

6. 配置模板工程

6.1 模板工厂

cn.bugstack.guide.idea.plugin.factory.TemplateFactory

public class TemplateFactory extends ProjectTemplatesFactory {

    @NotNull
    @Override
    public String[] getGroups() {return new String[]{"DDD 脚手架"};
    }

    @Override
    public Icon getGroupIcon(String group) {return ICONS.DDD;}

    @NotNull
    @Override
    public ProjectTemplate[] createTemplates(@Nullable String group, WizardContext context) {return new ProjectTemplate[]{new BuilderBasedTemplate(new DDDModuleBuilder())};
    }

}
  • 模板工厂的外围在于把咱们用于创立 DDD 的步骤 增加 createTemplates 办法中,这样算把整个创立自定义脚手架工程的链路就串联实现了。

6.2 文件配置

plugin.xml

<idea-plugin>
    <id>cn.bugstack.guide.idea.plugin.guide-idea-plugin-scaffolding</id>
    <name>Scaffolding</name>
    <vendor email="184172133@qq.com" url="https://bugstack.cn"> 小傅哥 </vendor>

    <!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
         on how to target different products -->
    <depends>com.intellij.modules.platform</depends>

    <extensions defaultExtensionNs="com.intellij">
        <projectTemplatesFactory implementation="cn.bugstack.guide.idea.plugin.factory.TemplateFactory"/>
        <applicationService serviceImplementation="cn.bugstack.guide.idea.plugin.infrastructure.DataSetting"/>
    </extensions>

</idea-plugin>
  • 接下来还须要把咱们创立的工程模板以及数据服务配置到 plugin.xml 中,这样在插件启动的时候就能够把咱们本人插件启动起来了。

四、测试验证

  • 点击 Plugin 启动 IDEA 插件,之后创立工程如下:

  • 快拿去试试吧,启动插件,点击创立工程,傻瓜式点击,就能够创立出一个 DDD 工程构造了。

五、总结

  • 学习应用 IDEA Plugin 开发技术,扭转创立工程向导,增加本人须要的工程创立模板,这样就能够创立出一个 DDD 脚手架工程骨架了,接下来你还能够联合本人理论的业务场景增加本人须要的一些技术栈到脚手架中。
  • 如果你违心尝试能够在工程创立中链接到数据库,把数据库中对应的表生成 Java 代码,这样一些简略的配置、查问、映射,就不必本人入手写了。
  • 在开发 DDD 脚手架的源码中还有一些细节过程,包含图标的展现、文案的信息、Freemarker 的应用细节,这些你都能够在源码中学习并调试验证。

六、系列举荐

  • 应用 Freemarker,创立 SpringBoot 脚手架
  • 公布 Jar 包到 Maven 地方仓库(为开发开源中间件做筹备)
  • DDD 畛域层决策规定树服务设计
  • 工作两三年了,整不明确架构图都画啥?
  • CodeGuide Github 仓库开源啦!
正文完
 0