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 ofDDD 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
- uses Freemarker to create SpringBoot scaffolding
- Release the Jar package to the Maven central warehouse (preparing for the development of open source middleware)
- DDD domain layer decision rule tree service design
- working for two or three years, and I don't understand what the architecture diagrams are drawn?
- CodeGuide Github repository is open source!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。