作者:小傅哥
沉淀、分享、成长,让自己和他人都能有所收获!
研发,要避免自嗨!
你做这个东西的价值是什么?有竞品调研吗?能赋能业务吗?那不已经有同类的了,你为什么还自己造轮子?
你是不是也会被问到这样的问题,甚至可能还有些头疼。但做的时候挺嗨,研究技术嘛,还落地了,多刺激。不过要说价值,好像一时半会还体现不出来,能不能赋能业务就不更不一定了。
可谁又能保证以后不能呢,技术的点是一个个攻克尝试的才有机会再深度学习后把这些内容连成一片,就像单说水、单说沙子、单说泥巴,好像并没有啥用,但把它们凑到一块再给把火,就烧成了砖,砖就码成了墙,墙就盖成房。
我们这一章节把 freemarker 能力与 IDEA Plugin 插件能力结合,开发一个DDD 脚手架 IDEA 插件
,可能你会想为什么要把脚手架开发到插件里呢?还有不是已经有了成型的脚手架可以用吗?
首先我们目前看到的脚手架基本都是网页版的,也就是一次性创建工程使用,不过在我们实际使用的时候,还希望在工程创建过程中把数据库、ES、Redis等生成对应的 ORM 代码,减少开发工作量。并且在使用的工程骨架的过程中,还希望可以随着开发需要再次补充新的功能进去,这个时候网页版的脚手架都不能很好的支持了。此外一些大厂都会自己的技术体系,完全是使用市面的脚手架基本很难满足自身的需求,所以就需要有一个符合自己场景的脚手架了。
那么,我们本章节就把脚手架的开发放到 IDEA 插件开发中,一方面学习脚手架的建设,另外一方面学习如何改变工程向导,创建出自己需要的DDD结构脚手架。
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块区域:
public class ProjectConfigUI {
private JPanel mainPanel;
private JTextField groupIdField;
private JTextField artifactIdField;
private JTextField versionField;
private JTextField packageField;
}
roupId
、artifactId
、version
、package
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();
}
}
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
开发一个自己需要的步骤,这个步骤就会出现到我们创建新的工程中。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};
}
}
DDDModuleConfigStep
添加工程配置步骤,可以自己定义需要的步骤,如果有多个可以依次添加。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);
}
}
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());
new WriteCommandAction
才能正常创建。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
方法中,这样算把整个创建自定义脚手架工程的链路就串联完成了。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的使用细节,这些你都可以在源码中学习并调试验证。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章