Blog: bugstack.cn
Precipitation, share, grow, let yourself and others can gain something! 😄
- Recently, I am interested in expanding various functions with the development ability of IDEA Plugin. Based on this, different cases are used to explore the IDEA Plugin plug-in development technology. I hope that such systematic learning and verification summary can bring help to more partners who need this technology.
- Source code address: github.com/fuzhengwei/…
One, foreword
Research and development, to avoid high!
What is your value in making this thing? Is there any research on competing products? Can you enable business? Why do you make your own wheel when there’s already one?
Are you going to be asked the same question, and maybe even have a headache. But it was fun doing it. It was technical. It landed. It was exciting. However, to say the value, it seems that a half will not be reflected, can not give business is not more uncertain.
Later can’t, but who can guarantee technology is one of the attack to try to have a chance to put these content into after a deep learning, like water, but sand and mud, “” seemed not to do, but put them to give the fire, was burn brick, brick yards into wall, the wall was built up a room.
Second, demand and purpose
This chapter combines freemarker capabilities with IDEA Plugin capabilities to develop a DDD scaffolding IDEA Plugin. You may be wondering why you want to build scaffolding into the Plugin. And isn’t there already a molding scaffolding to use?
First of all, the scaffolding we see at present is basically a web version, which is used to create a project at once. However, when we actually use it, we also hope to generate the corresponding ORM code in the process of creating the project, such as database, ES and Redis, so as to reduce the development workload. And in the process of using the engineering skeleton, but also hope to be able to add new functions as the development needs to go in, this time the web version of the scaffolding can not be very good support. In addition, some large factories will have their own technical system, completely using the market scaffolding is basically difficult to meet their own needs, so you need to have a scaffold in line with their own scene.
So, we put the scaffolding development into IDEA plug-in development in this chapter, on the one hand to learn the construction of scaffolding, on the other hand to learn how to change the project wizard, to create their own DDD structure scaffolding.
Case development
1. Engineering structure
Guide - idea - the plugin - scaffolding ├ ─ ─ the gradle └ ─ ─ the SRC ├ ─ ─ the main │ └ ─ ─ Java │ └ ─ ─ cn. Bugstack. Guide. Idea. The plugin │ ├ ─ ─ domain │ │ ├ ─ ─ model │ │ │ └ ─ ─ ProjectConfigVO. Java │ │ └ ─ ─ service │ │ ├ ─ ─ impl │ │ │ └ ─ ─ ProjectGeneratorImpl. Java │ │ ├ ─ ─ AbstractProjectGenerator. Java │ │ ├ ─ ─ FreemarkerConfiguration. Java │ │ └ ─ ─ IProjectGenerator. Java │ ├ ─ ─ factory │ │ └ ─ ─ ├── Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ Java │ ├─ MsgBundle. Java │ ├ ─ ─module│ │ ├ ─ ─ DDDModuleBuilder. Java │ │ └ ─ ─ DDDModuleConfigStep. Java │ └ ─ ─ the UI │ ├ ─ ─ ProjectConfigUI. Java │ └ ─ ─ ProjectConfigUI. Form ├ ─ ─ resources │ ├ ─ ─ meta-inf │ │ └ ─ ─ the plugin. The XML │ └ ─ ─ the template │ ├ ─ ─ pom. The FTL │ └ ─ ─ yml, FTL ├ ─ ─ Build. Gradle └ ─ ─ gradle. The propertiesCopy the code
Bugstack wormhole stack can be downloaded from the whole IDEA plug-in source code
This IDEA plug-in project is mainly divided into five areas:
- Domain: the domain layer, which provides services for creating DDD template projects, and the main use of this part is freemarker
- Factory: The factory layer provides the project creation template. The function of this layer is that when we create a new project in IDEA, we can add our own content, that is, create our defined DDD engineering structure.
- Infrastructure: Basic layer that provides functions such as data storage, image loading, and information mapping.
- Module: provides the DDD template project to create detailed operations and steps, that is, we create the project step by step, you can add your own step page as needed, allowing users to select and add their own content.For example, you need to connect libraries, select tables, add technology stacks for projects, etc
- UI: Interface layer, which provides swing-developed UI interfaces for user graphical selection and creation.
2. UI engineering configuration form
public class ProjectConfigUI {
private JPanel mainPanel;
private JTextField groupIdField;
private JTextField artifactIdField;
private JTextField versionField;
private JTextField packageField;
}
Copy the code
- Use Swing UI Designer to create a UI form that configures factory information and can be created in such a way that you can drag and drop it directly.
- In this UI form we mainly need;
roupId
,artifactId
,version
,package
3. Configure project procedure 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(a) {
return ServiceManager.getService(DataSetting.class);
}
@Nullable
@Override
public DataState getState(a) {
return state;
}
@Override
public void loadState(@NotNull DataState state) {
this.state = state;
}
public ProjectConfigVO getProjectConfig(a){
returnstate.getProjectConfigVO(); }}Copy the code
- The data storage service is provided in the basic layer, and the configuration information of the project is stored in the service, so that it is convenient to set up and obtain.
3.2 Extension Procedure
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(a) {
return projectConfigUI.getComponent();
}
@Override
public boolean validate(a) throws ConfigurationException {
// Get the configuration information and write to the 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(); }}Copy the code
- inheritance
ModuleWizardStep
Develop a step that you need, and this step will appear when we create a new project. - At the same time, the override validate method writes information from the project configuration UI form to the data configuration file.
3.3 Configuration Procedure
cn.bugstack.guide.idea.plugin.module.DDDModuleBuilder
public class DDDModuleBuilder extends ModuleBuilder {
private IProjectGenerator projectGenerator = new ProjectGeneratorImpl();
@Override
public Icon getNodeIcon(a) {
return ICONS.SPRING_BOOT;
}
/** * rewrite builderId to mount custom templates */
@Nullable
@Override
public String getBuilderId(a) {
return getClass().getName();
}
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
// Add project configuration steps. You can define the required steps by yourself. If there are multiple steps, you can add them one by one
DDDModuleConfigStep moduleConfigStep = new DDDModuleConfigStep(new ProjectConfigUI());
return newModuleWizardStep[]{moduleConfigStep}; }}Copy the code
- In the createWizardSteps method, add the one we already created
DDDModuleConfigStep
Add project configuration steps. You can define the required steps. If there are multiple steps, you can add them one by one. - Also note that your new wizard steps will only take effect if you override the getBuilderId() method.
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. Create the project master POM file
generateProjectPOM(project, entryPath, projectConfig);
// 2. Create a four-tier architecture
generateProjectDDD(project, entryPath, projectConfig);
// 3. Create Application
generateApplication(project, entryPath, projectConfig);
// create Yml
generateYml(project, entryPath, projectConfig);
// create CommongenerateCommon(project, entryPath, projectConfig); }}Copy the code
- Add a FreeMarker service for creating scaffolding frameworks at the Domain domain layer, which is a template engine: a generic tool for generating output text (HTML web pages, emails, profiles, source code, etc.) based on templates and data to change. FreeMarker online handbook: freemarker.foofun.cn
- According to the DDD engineering structure, the layers include: Application, Domain, infrastructure, and interfaces, so we abstract these creation processes into template methods and hand them over to subclasses to create.
5. Invoke the scaffolding service
cn.bugstack.guide.idea.plugin.module.DDDModuleBuilder
public class DDDModuleBuilder extends ModuleBuilder {
private IProjectGenerator projectGenerator = new ProjectGeneratorImpl();
@Override
public Icon getNodeIcon(a) {
return ICONS.SPRING_BOOT;
}
@Override
public void setupRootModel(@NotNull ModifiableRootModel rootModel) throws ConfigurationException {
/ / set the JDK
if (null! =this.myJdk) {
rootModel.setSdk(this.myJdk);
} else {
rootModel.inheritSdk();
}
// Generate the project path
String path = FileUtil.toSystemIndependentName(Objects.requireNonNull(getContentEntryPath()));
new File(path).mkdirs();
VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
rootModel.addContentEntry(virtualFile);
Project project = rootModel.getProject();
// Create the project structure
Runnable r = () -> new WriteCommandAction<VirtualFile>(project) {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable { projectGenerator.doGenerator(project, getContentEntryPath(), DataSetting.getInstance().getProjectConfig()); } }.execute(); }}Copy the code
- in
DDDModuleBuilder#setupRootModel
In, add CreateDDD engineering framework
The service,projectGenerator.doGenerator(project, getContentEntryPath(), DataSetting.getInstance().getProjectConfig());
- In addition, the thread call method provided by IDEA is used.
new WriteCommandAction
It can be created properly.
6. Configure the template project
6.1 Template Factory
cn.bugstack.guide.idea.plugin.factory.TemplateFactory
public class TemplateFactory extends ProjectTemplatesFactory {
@NotNull
@Override
public String[] getGroups() {
return new String[]{"DDD scaffolding"};
}
@Override
public Icon getGroupIcon(String group) {
return ICONS.DDD;
}
@NotNull
@Override
public ProjectTemplate[] createTemplates(@Nullable String group, WizardContext context) {
return new ProjectTemplate[]{new BuilderBasedTemplate(newDDDModuleBuilder())}; }}Copy the code
- The core of a template factory is to use us for creation
DDD steps
addcreateTemplates
In this way, the entire link to create a custom scaffold 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="[email protected]" url="https://bugstack.cn">Small Fu Ge</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>
Copy the code
- Next we need to configure the project templates we created and the data service to
plugin.xml
“, so that we can start our own plug-in when the plug-in starts.
4. Test and verification
- Click on the
Plugin
Start IDEA plug-in and create project as follows:
- Go ahead and try it out. Launch the plugin, click Create Project, click fool, and you can create a DDD project structure.
Five, the summary
- Learn how to use IDEA Plugin development techniques, change the project wizard, add your own project creation templates, and then create a DDD scaffold project skeleton. Then you can add your own stack to the scaffold according to your actual business scenario.
- If you are willing to try you can link to the database in the project creation, the corresponding table in the database to generate Java code, so some simple configuration, query, mapping, do not have to write their own hands.
- There are also details of the DDD scaffolding development process in the source code, including icon presentation, text information, and Freemarker usage details, which you can learn and debug in the source code.
Six, series recommendation
- Using Freemarker, create SpringBoot scaffolding
- Publish Jar packages to Maven’s central repository (in preparation for developing open source middleware)
- DDD domain-level decision tree service design
- Have you been working for two or three years and have no idea what the architecture diagram is?
- CodeGuide Github repository open source!