前言:前几天尝试编写了一个简单的Kettle自定义Step插件,但是有一个很大的问题:之前的插件是通过用户输入字段的下标来确定哪些列需要进行字符替换,而非字段名,因此我看了下Kettle中提供的插件的源代码,找到了获取字段属性的方法,在此记录一下。
开发环境:
开发工具:IntelliJ IDEA 2020.1
开发环境:JDK1.8、Maven-3.6.3
Kettle版本:8.3.0.0-371
Kettle源代码:点击进入
插件示例代码:下载地址
官方文档:点击进入
注:本文将基于上一篇博客的基础上进行修改
博客地址:https://blog.csdn.net/xhy1999/article/details/108375836
GitHub地址:https://github.com/xhy1999/kettle-sdk-step-plugin-demo
(1).代码
首先,直接给出结论,具体的细节将会在文章后面提到,大家可以将下面的方法稍微修改一下,放到Dialog类中即可
//这里的colList即为获取到的列名
public void getColNames() {
try {
RowMetaInterface rowMetaInterface = transMeta.getPrevStepFields(stepname);
int num = rowMetaInterface.size();
List<String> colList = new ArrayList<>();
for (int i = 0; i < num; i++) {
ValueMetaInterface v = rowMetaInterface.getValueMeta(i);
colList.add(v.getName());
}
meta.setColNameList(colList);
} catch (KettleStepException e) {
e.printStackTrace();
}
}
以上即为关键代码,下面我将介绍下自己寻找方法的过程。
(2).API查找过程
首先我觉得官方文档应该有写,但是我并没有去查阅官方文档,而是通过查看已有的插件的源代码从而找到API。
1.ExcelOutput
在ExcelOutput插件中的字段选项卡下面有获取字段的按钮,此按钮的功能即为获得流中的字段、字段类型和字段长度等,因此我们只要知道ExcelOutput中此按钮的点击事件是如何实现的,即可使用类似的流程获得流中字段的各个属性。
2.查找源代码
在Step插件的包(steps)中找到有关于ExcelOutput的类
发现没有ExcelOutputDialog类,全局搜索一下,找到并进入
一看傻眼了,2000行代码怎么找呢。不过问题不大,我们知道按钮上面有"获取字段"这几个字,因此我们只要找到几个字对应的按钮即可,那么随便找一个从获取字段名的代码,将里面的字段全局搜索一下,找到最后是zh_CN结尾的文件进入
文件里面都是unicode编码,没关系,随便写一个程序,看看"获取字段"的unicode编码是什么,然后搜索一下即可
然后把字段名在ExcelOutputDialog查找一下,发现这个wGet就是我们要找的按钮
然后去找这个lsGet
最后发先get()即为获取字段的函数
(3).源代码分析
找到get()后,不难看出,下面两行代码即为获取并将字段属性绑定到table中的代码
RowMetaInterface r = transMeta.getPrevStepFields( stepname );
BaseStepDialog.getFieldsFromPrevious( r, wFields, 1, new int[] { 1 }, new int[] { 2 }, 4, 5, listener );
但是但从这两行无法看出数据是怎么抽取的,于是,进入BaseStepDialog.getFieldsFromPrevious方法查看一下
简单的套几层娃之后,我们就可以看到赋值的核心代码,从中也不难看出获得属性的关键代码
for (int i = 0; i < row.size(); i++) {
//获得列的属性
ValueMetaInterface v = row.getValueMeta(i);
boolean add = true;
if (choice == 0) { // hang on, see if it's not yet in the table view
if (keys.indexOf(v.getName()) >= 0) {
add = false;
}
}
if (add) {
TableItem tableItem = new TableItem(table, SWT.NONE);
for (int c = 0; c < nameColumn.length; c++) {
tableItem.setText(nameColumn[c], Const.NVL(v.getName(), ""));
}
if (dataTypeColumn != null) {
for (int c = 0; c < dataTypeColumn.length; c++) {
tableItem.setText(dataTypeColumn[c], v.getTypeDesc());
}
}
if (lengthColumn > 0) {
if (v.getLength() >= 0) {
tableItem.setText(lengthColumn, Integer.toString(v.getLength()));
}
}
if (precisionColumn > 0) {
if (v.getPrecision() >= 0) {
tableItem.setText(precisionColumn, Integer.toString(v.getPrecision()));
}
}
if (listener != null) {
if (!listener.tableItemInserted(tableItem, v)) {
tableItem.dispose(); // remove it again
}
}
}
}
反观方法名,这里用到的row就是我们传入的RowMetaInterface
(4).修改自定义插件代码
找到API后改起来就很简单了,主要的方法已经在文章开头给出了,代码我已经上传至GitHub,大家自取。
至此,列的各个属性我们都能获取到了。
本文只是记录自己查找API的过程,而并非深入研究Kettle底层的实现。