Author: Xiao Fu Ge
Blog: https://bugstack.cn
Precipitate, share and grow, so that you and others can gain something! 😄
- Recently, I am interested in expanding various functions in combination with the development capability of IDEA Plugin. Based on this, different cases are used to explore the IDEA Plugin plug-in development technology. I hope this systematic learning and verification summary can help more partners who need this technology.
- Source address: https://github.com/fuzhengwei/CodeGuide#1-%E6%BA%90%E7%A0%81
1, Foreword
R & D, to avoid self hi!
What is the value of doing this? Is there any competitive product research? Can you enable business? There are already similar ones. Why do you make your own wheels?
Will you also be asked such questions, and may even have a headache. But when doing it, I was very hi. I studied technology and landed. It's so exciting. However, when it comes to value, it seems that it can't be reflected for a while, and it's not certain whether it can empower the business.
But who can guarantee that they will not be able to do so in the future? Only by trying to overcome the technical points one by one can we have the opportunity to connect these contents after in-depth learning, just like talking about water, sand and mud alone. It seems to be of no use, but when they are gathered together and put into a fire, they will be burned into bricks, bricks will be built into walls, and walls will be built into houses.
2, Demand purpose
In this chapter, we combine freemaker capability with IDEA Plugin capability to develop an IDEA Plugin for DDD scaffold. You may wonder why you want to develop scaffold into the plugin? Also, isn't there a formed scaffold that can be used?
First of all, the scaffolds we see at present are basically web versions, that is, they are used to create projects at one time. However, when we actually use them, we also hope to generate corresponding ORM codes from databases, ES, Redis, etc. in the process of project creation, so as to reduce the development workload. And in the process of using the engineering skeleton, I hope to add new functions again as the development needs. At this time, the scaffold of the web version can not be well supported. In addition, some large factories have their own technical system, which is completely using the scaffold on the market, which is basically difficult to meet their own needs, so they need a scaffold that meets their own scenes.
Then, in this chapter, we put the development of scaffold into the development of IDEA plug-in. On the one hand, we learn the construction of scaffold, on the other hand, we learn how to change the engineering wizard and create the DDD structure scaffold we need.
3, 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: the official account: bugstack wormhole stack reply: idea can download all the IDEA plug-in development source code.
In this IDEA plug-in project, it is mainly divided into five areas:
- Domain: the domain layer, which provides services for creating DDD template projects. In fact, freemaker is mainly used in this part
- factory: factory layer, which provides project creation templates. The role of this layer is to add our own content when we create a new project in the IDEA, that is, to create the DDD project structure we have defined.
- infrastructure: the basic layer, which provides the functions of data storage, image loading and information mapping.
- Module: the module layer provides specific operations and steps for creating DDD template projects, that is, when we create projects, we select them step by step. You can add your own step page as needed to allow users to select and add their own content. For example, you need to connect the library, select the table, add the technology stack required by the project, etc
- UI: interface layer, which provides the 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.
- In this UI form, we mainly need; roupId,artifactId,version,package
3. Configuration engineering step 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(); } }
- The data storage service is provided in the basic layer, and the configuration information of the creation project is stored in the service, which is more convenient to set 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 { // Get the configuration information and write it to 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 to develop a required step, which will appear in the new project we create.
- 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; } /** * Override builderId to mount custom template */ @Nullable @Override public String getBuilderId() { 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 in turn DDDModuleConfigStep moduleConfigStep = new DDDModuleConfigStep(new ProjectConfigUI()); return new ModuleWizardStep[]{moduleConfigStep}; } }
- In the createWizardSteps method, add the DDDModuleConfigStep we have created to the project configuration step. You can define the required steps yourself. If there are multiple steps, you can add them in turn.
- At the same time, it should be noted that the newly added wizard steps can only take effect after overriding 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 project main POM file generateProjectPOM(project, entryPath, projectConfig); // 2. Create a four tier architecture generateProjectDDD(project, entryPath, projectConfig); // 3. Create Application generateApplication(project, entryPath, projectConfig); // 4. Create Yml generateYml(project, entryPath, projectConfig); // 5. Create Common generateCommon(project, entryPath, projectConfig); } }
- FreeMarker service for creating scaffold framework is added in the domain domain layer. It is a template engine: a general tool based on template and data to be changed, and used to generate output text (HTML web page, e-mail, configuration file, source code, etc.). FreeMarker online manual: http://freemarker.foofun.cn
- According to the DDD engineering structure, the hierarchy includes: application, domain, infrastructure and interfaces. Then we abstract these creation processes into the template method and give them to subclasses to create.
5. Call scaffold 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 { // Set JDK if (null != this.myJdk) { rootModel.setSdk(this.myJdk); } else { rootModel.inheritSdk(); } // Generate 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 engineering 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(); } }
- In DDDModuleBuilder#setupRootModel, add the service for creating DDD project framework, projectGenerator.doGenerator(project, getContentEntryPath(), DataSetting.getInstance().getProjectConfig());
- In addition, the thread calling method provided by IDEA is required here to create a new WriteCommandAction normally.
6. Configure formwork works
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 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(new DDDModuleBuilder())}; } }
- The core of the template factory is to add the steps we used to create DDD to the createTemplates method, so that the whole link to create a custom scaffold project can be connected 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 "> little brother Fu < / 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 into plugin.xml, so that we can start our own plug-in when the plug-in starts.
4, Test verification
- Click Plugin to start the IDEA plug-in, and then create the project as follows:
- Take it and try it. Start the plug-in, click create project, and click fool to create a DDD project structure.
5, Summary
- Learn to use the IDEA Plugin development technology, change the project creation wizard and add the project creation template you need, so that you can create a DDD scaffold project skeleton. Next, you can add some technology stacks you need to the scaffold in combination with your actual business scenario.
- If you are willing to try, you can link to the database in the project creation and generate Java code from the corresponding tables in the database. In this way, you don't have to write some simple configuration, query and mapping yourself.
- In developing the source code of DDD scaffold, there are some detailed processes, including the display of icons, the information of copywriting, and the use details of Freemarker, which you can learn, debug and verify in the source code.
6, Series recommendation
- Using Freemarker, create a SpringBoot scaffold
- Release Jar package to Maven central warehouse (to prepare for the development of open source middleware)
- DDD domain level decision rule tree service design
- I've been working for two or three years. I don't understand what the architecture drawing is?
- CodeGuide Github warehouse is open source!