是五月呀!

IDEA插件开发(四)配置持久化

很多插件都需要提供用户配置参数的入口,这里以free-mybatis-plugin插件为例,我们想要用户配置方法匹配模版,例如dao层中insertadd等关键字开头的方法在mapper中生成insert语句。

创建GUI配置窗口

IDEA中可以直接创建一个GUI窗口:

弹出创建窗口:

名字自定,layout默认使用GridLayoutManager即可。
然后就可以拖拽编辑UI界面了。
第一次用会觉得超级难用!在排版的时候,如果想新加一行或者一列,拖拽组件到原来行的边缘,释放后会自动新增加一行。

给需要取值的组件填写filed name属性,这样在生成的类中会包含对应的成员变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MybatisSettingForm {
public JTextField insertPatternTextField;
public JTextField deletePatternTextField;
public JTextField updatePatternTextField;
public JTextField selectPatternTextField;
public JPanel mainPanel;
public JComboBox modelComboBox;
}

添加配置项

创建完GUI窗口后,需要在IDEA配置窗口中添加入口,那就需要实现SearchableConfigurable接口,并注册到plugin.xml中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
public class MybatisConfigurable implements SearchableConfigurable {
/**
* 保存全局配置,
*/
private MybatisSetting mybatisSetting;
/**
* GUI配置窗口
*/
private MybatisSettingForm mybatisSettingForm;
private String separator = ";";
private Splitter splitter = Splitter.on(separator).omitEmptyStrings().trimResults();
private Joiner joiner = Joiner.on(separator);
public MybatisConfigurable() {
mybatisSetting = MybatisSetting.getInstance();
}
/**
* 返回唯一id
* 这个id要与xml中的id(如果指定)一致
* @return
*/
@Override
public String getId() {
return "Mybatis";
}
/**
* 用户在setting对话框搜索时,启用的动作
* @param option
* @return
*/
@Override
public Runnable enableSearch(String option) {
return null;
}
/**
* 配置项名称
* @return
*/
@Nls
@Override
public String getDisplayName() {
return getId();
}
/**
* 帮助文档中的名称
* @return
*/
@Nullable
@Override
public String getHelpTopic() {
return getId();
}
/**
* 创建GUI组件
* @return
*/
@Nullable
@Override
public JComponent createComponent() {
if (null == mybatisSettingForm) {
this.mybatisSettingForm = new MybatisSettingForm();
}
return mybatisSettingForm.mainPanel;
}
/**
* 判断配置内容有没有修改
* @return
*/
@Override
public boolean isModified() {
return mybatisSetting.getStatementGenerateModel().getIdentifier() != mybatisSettingForm.modelComboBox.getSelectedIndex()
|| !joiner.join(INSERT_GENERATOR.getPatterns()).equals(mybatisSettingForm.insertPatternTextField.getText())
|| !joiner.join(DELETE_GENERATOR.getPatterns()).equals(mybatisSettingForm.deletePatternTextField.getText())
|| !joiner.join(UPDATE_GENERATOR.getPatterns()).equals(mybatisSettingForm.updatePatternTextField.getText())
|| !joiner.join(SELECT_GENERATOR.getPatterns()).equals(mybatisSettingForm.selectPatternTextField.getText());
}
/**
* 用户修改配置后点击确认
* @throws ConfigurationException
*/
@Override
public void apply() throws ConfigurationException {
mybatisSetting.setStatementGenerateModel(GenerateModel.getInstance(mybatisSettingForm.modelComboBox.getSelectedIndex()));
INSERT_GENERATOR.setPatterns(Sets.newHashSet(splitter.split(mybatisSettingForm.insertPatternTextField.getText())));
DELETE_GENERATOR.setPatterns(Sets.newHashSet(splitter.split(mybatisSettingForm.deletePatternTextField.getText())));
UPDATE_GENERATOR.setPatterns(Sets.newHashSet(splitter.split(mybatisSettingForm.updatePatternTextField.getText())));
SELECT_GENERATOR.setPatterns(Sets.newHashSet(splitter.split(mybatisSettingForm.selectPatternTextField.getText())));
}
/**
* 重置配置
*/
@Override
public void reset() {
mybatisSettingForm.modelComboBox.setSelectedIndex(mybatisSetting.getStatementGenerateModel().getIdentifier());
mybatisSettingForm.insertPatternTextField.setText(joiner.join(INSERT_GENERATOR.getPatterns()));
mybatisSettingForm.deletePatternTextField.setText(joiner.join(DELETE_GENERATOR.getPatterns()));
mybatisSettingForm.updatePatternTextField.setText(joiner.join(UPDATE_GENERATOR.getPatterns()));
mybatisSettingForm.selectPatternTextField.setText(joiner.join(SELECT_GENERATOR.getPatterns()));
}
/**
* 销毁GUI组件
*/
@Override
public void disposeUIResources() {
mybatisSettingForm.mainPanel = null;
}
}

之后在plugin.xml中注册:

1
2
3
4
5
6
7
<extensions defaultExtensionNs="com.intellij">
<!-- 插件配置窗口 -->
<applicationConfigurable instance="com.mybatis.setting.MybatisConfigurable"/>
<!-- applicationService 这个是插件配置文件的持久化 -->
<applicationService serviceInterface="com.xxx.mybatis.setting.MybatisSetting"
serviceImplementation="com.xxx.mybatis.setting.MybatisSetting"/>
</extensions>

这样就可以在IDEA setting窗口中见到我们的配置项了:

持久化配置

上面我们说了如何让用户修改插件配置,那当IDEA重启时,我们想让配置持久化到文件中,可以实现PersistentStateComponent接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@State(
name = "MybatisSettings",
storages = @Storage("mybatis.xml"))
public class MybatisSetting implements PersistentStateComponent<Element> {
private GenerateModel statementGenerateModel;
private Gson gson = new Gson();
private Type gsonTypeToken = new TypeToken<Set<String>>() {
}.getType();
public MybatisSetting() {
statementGenerateModel = GenerateModel.START_WITH_MODEL;
}
public static MybatisSetting getInstance() {
return ServiceManager.getService(MybatisSetting.class);
}
/**
* IDEA关闭时,将内存中配置持久化到xml中
* @return
*/
@Nullable
@Override
public Element getState() {
Element element = new Element("MybatisSettings");
element.setAttribute(INSERT_GENERATOR.getId(), gson.toJson(INSERT_GENERATOR.getPatterns()));
element.setAttribute(DELETE_GENERATOR.getId(), gson.toJson(DELETE_GENERATOR.getPatterns()));
element.setAttribute(UPDATE_GENERATOR.getId(), gson.toJson(UPDATE_GENERATOR.getPatterns()));
element.setAttribute(SELECT_GENERATOR.getId(), gson.toJson(SELECT_GENERATOR.getPatterns()));
element.setAttribute("statementGenerateModel", String.valueOf(statementGenerateModel.getIdentifier()));
return element;
}
/**
* IDEA打开时,从xml中读取配置
* @param state
*/
@Override
public void loadState(Element state) {
loadState(state, INSERT_GENERATOR);
loadState(state, DELETE_GENERATOR);
loadState(state, UPDATE_GENERATOR);
loadState(state, SELECT_GENERATOR);
statementGenerateModel = GenerateModel.getInstance(state.getAttributeValue("statementGenerateModel"));
}
private void loadState(Element state, StatementGenerator generator) {
String attribute = state.getAttributeValue(generator.getId());
if (null != attribute) {
generator.setPatterns((Set<String>) gson.fromJson(attribute, gsonTypeToken));
}
}
public GenerateModel getStatementGenerateModel() {
return statementGenerateModel;
}
public void setStatementGenerateModel(GenerateModel statementGenerateModel) {
this.statementGenerateModel = statementGenerateModel;
}
}

其中@State注解指明了xml中根元素的名字和xml文件名称。
配置文件储存位置:/Library/Caches/IntelliJIdea2018.2/plugins-sandbox/config/options/mybatis.xml
即在沙箱目录下的/config/options/mybatis.xml中。
当然,如果插件正式发布安装后,会保存到正式库目录中。