1
头图

Author: Xiao Fu Ge
Blog: https://bugstack.cn

Precipitate, share, and grow, so that you and others can gain something! 😄

  • Recently, I am very interested in combining IDEA Plugin development capabilities to expand various functions. Also based on this use different cases to explore the IDEA Plugin plug-in development technology. I hope that such a systematic study and verification summary can bring help to more partners who need this technology.
  • Source address: https://github.com/fuzhengwei/CodeGuide#1-%E6%BA%90%E7%A0%81

I. Introduction

research and development, to avoid self-confidence!

What is the value of your making this thing? Is there any research on competing products? Can it empower business? Then there are no more similar ones, why do you make your own wheels?

Do you also get asked this question, maybe even some headaches. But when I did it, I was very excited. I studied the technology, and I got to the ground. How exciting. But when it comes to value, it doesn't seem to be reflected in a while, and whether it can empower the business is not even more certain.

But who can guarantee that it won’t be possible in the future. The technical point is that only those who try to overcome them will have the opportunity to connect these contents into one piece after deep learning. Just like water, sand, and mud, there seems to be nothing. Use them, but if you put them together and put them on the fire, they will be burned into bricks, the bricks will be built into walls, and the walls will be built into houses.

2. Purpose of demand

In this chapter, we combine the capabilities of freemarker with the capabilities of IDEA Plugin to develop a DDD scaffolding IDEA plug-in. You may wonder why you want to develop the scaffolding into the plug-in? Is there already a formed scaffold that can be used?

First of all, the scaffolding we currently see is basically a web version, which is to create a project at a time, but when we actually use it, we also hope that the database, ES, Redis, etc. will be generated during the project creation process to generate the corresponding ORM code. Reduce development workload. And in the process of using the engineering skeleton, I hope that new functions can be added again as the development needs. At this time, the scaffolding of the web version cannot be well supported. In addition, some large factories have their own technical systems, and it is basically difficult to meet their own needs using scaffolding on the market, so they need to have a scaffolding that fits their own scenarios.

So, in this chapter, we will put the development of scaffolding into IDEA plug-in development. On the one hand, we will learn the construction of scaffolding, and on the other hand, we will learn how to change the engineering wizard to create the DDD structure scaffolding we need.

Three, case development

1. Engineering structure

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

source code acquisition : #public number: bugstack wormhole stack reply: idea can download all IDEA plug-in development source code

In this IDEA plug-in project, it is mainly divided into 5 areas:

  • domain: Domain layer, providing services for creating DDD template projects, in fact, this part mainly uses freemarker
  • factory: The factory layer provides project creation templates. The function of this layer is that when we create a new project in IDEA, we can add our own content, which is to create a DDD project structure that we have defined.
  • Infrastructure: The basic layer provides functions such as data storage, image loading, and information mapping.
  • module: Module layer, providing specific operations and steps for creating DDD template projects, that is to say, we select step by step when we create a project. You can add your own step page as needed, allowing users to select and add what they need. example, you need to connect the library, select the list, add the technology stack required for the project, etc.
  • ui: The interface layer, which provides a UI interface developed by Swing for user graphical selection and creation.

2. UI project configuration form

public class ProjectConfigUI {

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

}
  • Use Swing UI Designer to create a UI form for configuring factory information, which can be directly dragged and dropped.
  • In this UI form we mainly need; roupId , artifactId , version , package

3. Configuration project creation

3.1 Data storage

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();
     }

}
  • Provide data storage services at the basic layer, and store the configuration information of the created project in the service, which is more convenient to set up and obtain.

3.2 Expansion steps

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();
    }

}
  • Inherit ModuleWizardStep develop a step you need, and this step will appear when we create a new project.
  • At the same time, in the rewritten validate method, the information obtained from the project configuration UI form is written into the data configuration file.

3.3 Configuration steps

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};
    }
}
  • In the createWizardSteps method, we have already created DDDModuleConfigStep add the project configuration steps, you can define the required steps yourself, if there are more than one, you can add them in sequence.
  • At the same time, it should be noted that your newly added wizard steps can only take effect after the getBuilderId() method is overridden.

4. Develop scaffolding services

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);
    }

}
  • Add the FreeMarker service for creating scaffolding framework at the domain layer. It is a template engine: it is based on the template and the data to be changed, and is used to generate output text (HTML pages, emails, configuration files, source code, etc.) ) Universal tool. FreeMarker online manual: http://freemarker.foofun.cn
  • According to the DDD project structure, the layers include: application, domain, infrastructure, interfaces, then we abstract these creation processes into template methods, and hand them over to subclasses to create them.

5. Call scaffolding service

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();

    }

}
  • In DDDModuleBuilder#setupRootModel , add the service of DDD engineering framework projectGenerator.doGenerator(project, getContentEntryPath(), DataSetting.getInstance().getProjectConfig());
  • In addition, you need to use the thread call method provided by IDEA, so that new WriteCommandAction can be created normally.

6. Configure the template project

6.1 Formwork factory

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())};
    }

}
  • The core of the template factory is to add DDD to the createTemplates method, so that the entire link for creating a custom scaffolding project is completed in series.

6.2 File configuration

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>
  • Next, we need to configure the project template and data service we created to plugin.xml , so that we can start our own plug-in when the plug-in is started.

Four, test verification

  • Click Plugin start the IDEA plug-in, and then create the project as follows:

  • Try it quickly, start the plug-in, click Create Project, and click foolishly to create a DDD project structure.

Five, summary

  • Learn to use IDEA Plugin development technology, change the creation project wizard, add the project creation template you need, so that you can create a DDD scaffolding project skeleton, and then you can add some technology stacks you need based on your actual business scenarios Into the scaffolding.
  • If you are willing to try, you can link to the database during project creation, and generate Java code from the corresponding tables in the database, so that you don't need to write by yourself for some simple configuration, query, and mapping.
  • There are some detailed processes in the development of the source code of DDD scaffolding, including the display of icons, the information of the copy, and the details of using Freemarker. You can learn and debug and verify these in the source code.

Sixth, series recommendation


小傅哥
4.7k 声望28.4k 粉丝

CodeGuide | 程序员编码指南 - 原创文章、案例源码、资料书籍、简历模版等下载。