소스 검색

!41 V_1.1.2
Merge pull request !41 from AE86/V_1.0.0

AE86 3 년 전
부모
커밋
543ff9444f
100개의 변경된 파일2183개의 추가작업 그리고 901개의 파일을 삭제
  1. 36 73
      README.md
  2. 1 1
      dbsyncer-biz/pom.xml
  3. 8 8
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/AbstractChecker.java
  4. 4 4
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/ConnectorConfigChecker.java
  5. 6 6
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/config/ConfigChecker.java
  6. 9 13
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/AbstractDataBaseConfigChecker.java
  7. 6 5
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/ConnectorChecker.java
  8. 4 4
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlMysqlConfigChecker.java
  9. 4 4
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlOracleConfigChecker.java
  10. 4 4
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlSqlServerConfigChecker.java
  11. 42 0
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/ElasticsearchConfigChecker.java
  12. 4 4
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/OracleConfigChecker.java
  13. 3 3
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/mapping/MappingChecker.java
  14. 8 8
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/mapping/TimingConfigChecker.java
  15. 2 3
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/tablegroup/TableGroupChecker.java
  16. 2 2
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/ConnectorServiceImpl.java
  17. 2 2
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MappingServiceImpl.java
  18. 11 8
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MonitorServiceImpl.java
  19. 5 5
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/PluginServiceImpl.java
  20. 1 1
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/DiskMetricDetailFormatter.java
  21. 1 4
      dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/MemoryMetricDetailFormatter.java
  22. 1 1
      dbsyncer-cache/pom.xml
  23. 1 1
      dbsyncer-cluster/pom.xml
  24. 4 4
      dbsyncer-common/pom.xml
  25. 0 2
      dbsyncer-common/src/main/java/org/dbsyncer/common/util/CollectionUtils.java
  26. 0 3
      dbsyncer-common/src/main/java/org/dbsyncer/common/util/DateFormatUtil.java
  27. 6 0
      dbsyncer-common/src/main/java/org/dbsyncer/common/util/JsonUtil.java
  28. 22 0
      dbsyncer-common/src/main/java/org/dbsyncer/common/util/NumberUtil.java
  29. 11 0
      dbsyncer-common/src/main/java/org/dbsyncer/common/util/RandomUtil.java
  30. 56 2
      dbsyncer-common/src/main/java/org/dbsyncer/common/util/StringUtil.java
  31. 13 1
      dbsyncer-connector/pom.xml
  32. 31 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/AbstractConnector.java
  33. 31 25
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/Connector.java
  34. 13 18
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/ConnectorFactory.java
  35. 5 27
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/ConnectorMapper.java
  36. 101 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/ESConfig.java
  37. 1 14
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/ReaderConfig.java
  38. 1 4
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/WriterBatchConfig.java
  39. 0 15
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/WriterConfig.java
  40. 1 4
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/WriterSingleConfig.java
  41. 5 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/constant/ConnectorConstant.java
  42. 98 130
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/AbstractDatabaseConnector.java
  43. 1 2
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/Database.java
  44. 38 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/DatabaseConnectorMapper.java
  45. 6 8
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/HandleCallback.java
  46. 3 3
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/sqlbuilder/SqlBuilderQuery.java
  47. 9 3
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/ConnectorEnum.java
  48. 100 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/ESFieldTypeEnum.java
  49. 9 9
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/FilterEnum.java
  50. 8 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/OperationEnum.java
  51. 8 4
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/SqlBuilderEnum.java
  52. 347 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/es/ESConnector.java
  53. 25 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/es/ESConnectorMapper.java
  54. 7 4
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLMysqlConnector.java
  55. 3 3
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLOracleConnector.java
  56. 7 6
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLSqlServerConnector.java
  57. 5 5
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/sqlserver/SqlServerConnector.java
  58. 6 6
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/sqlserver/SqlServerConnectorMapper.java
  59. 3 7
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/util/DatabaseUtil.java
  60. 67 0
      dbsyncer-connector/src/main/java/org/dbsyncer/connector/util/ESUtil.java
  61. 1 1
      dbsyncer-listener/pom.xml
  62. 1 1
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/Listener.java
  63. 2 2
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/ListenerFactory.java
  64. 27 12
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/enums/ListenerEnum.java
  65. 3 3
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/enums/ListenerTypeEnum.java
  66. 25 62
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/enums/QuartzFilterEnum.java
  67. 16 16
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/mysql/MysqlExtractor.java
  68. 139 0
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/AbstractQuartzExtractor.java
  69. 78 0
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/DatabaseQuartzExtractor.java
  70. 74 0
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/ESQuartzExtractor.java
  71. 69 0
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/Point.java
  72. 0 249
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/QuartzExtractor.java
  73. 2 4
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/QuartzFilter.java
  74. 35 0
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/filter/DateFilter.java
  75. 36 0
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/filter/TimestampFilter.java
  76. 18 18
      dbsyncer-listener/src/main/java/org/dbsyncer/listener/sqlserver/SqlServerExtractor.java
  77. 263 0
      dbsyncer-listener/src/main/test/ESClientTest.java
  78. 4 4
      dbsyncer-listener/src/main/test/LinkedBlockingQueueTest.java
  79. 1 1
      dbsyncer-manager/pom.xml
  80. 4 4
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/config/FieldPicker.java
  81. 5 5
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/puller/impl/IncrementPuller.java
  82. 2 2
      dbsyncer-manager/src/main/java/org/dbsyncer/manager/template/impl/OperationTemplate.java
  83. 1 1
      dbsyncer-monitor/pom.xml
  84. 5 5
      dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/MonitorFactory.java
  85. 2 2
      dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/enums/MetricEnum.java
  86. 1 1
      dbsyncer-parser/pom.xml
  87. 8 6
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/ParserFactory.java
  88. 21 0
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/DateHandler.java
  89. 2 2
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/DefaultHandler.java
  90. 25 0
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/LongToTimestampHandler.java
  91. 2 2
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/RemStrFirstHandler.java
  92. 2 2
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/RemStrLastHandler.java
  93. 3 3
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/ReplaceHandler.java
  94. 5 5
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/SubStrFirstHandler.java
  95. 5 5
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/SubStrLastHandler.java
  96. 5 3
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/TimestampHandler.java
  97. 27 0
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/TimestampToDateHandler.java
  98. 25 0
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/TimestampToLongHandler.java
  99. 20 4
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/enums/ConvertEnum.java
  100. 3 3
      dbsyncer-parser/src/main/java/org/dbsyncer/parser/enums/ModelEnum.java

+ 36 - 73
README.md

@@ -1,6 +1,6 @@
 <div>
     <h3>介绍</h3>
-    <p>DBSyncer是一款开源的数据同步中间件,提供Mysql、Oracle、SqlServer、SQL结果集等同步场景。支持上传插件自定义同步转换业务,提供监控全量和增量数据统计图、应用性能预警等。</p>
+    <p>DBSyncer是一款开源的数据同步中间件,提供Mysql、Oracle、SqlServer、Elasticsearch(ES)、SQL等同步场景。支持上传插件自定义同步转换业务,提供监控全量和增量数据统计图、应用性能预警等。</p>
     <p>特点</p>
     <ol>
         <li>组合驱动,自定义库同步到库组合,关系型数据库与非关系型之间组合,任意搭配表同步映射关系</li>
@@ -14,30 +14,24 @@
     <table>
         <tbody>
             <tr>
-                <td colspan="2" rowspan="3">Every point is a DataBase</td>
+                <td colspan="2" rowspan="2">Every point is a DataBase</td>
                 <td colspan="6" align="center">目标源</td>
             </tr>
             <tr>
-                <td colspan="3" align="center">全量</td>
-                <td colspan="3" align="center">增量</td>
-            </tr>
-            <tr>
-                <td>Mysql</td>
-                <td>Oracle</td>
-                <td>SqlServer</td>
                 <td>Mysql</td>
                 <td>Oracle</td>
                 <td>SqlServer</td>
+                <td>ES</td>
+                <td>SQL(Mysql/Oracle/SqlServer)</td>
             </tr>
             <tr>
-                <td rowspan="6">数据源</td>
+                <td rowspan="5">数据源</td>
                 <td>Mysql</td>
                 <td>√</td>
                 <td>√</td>
                 <td>√</td>
                 <td>√</td>
                 <td>√</td>
-                <td>√</td>
             </tr>
             <tr>
                 <td>Oracle</td>
@@ -46,7 +40,6 @@
                 <td>√</td>
                 <td>√</td>
                 <td>√</td>
-                <td>√</td>
             </tr>
             <tr>
                 <td>SqlServer</td>
@@ -55,11 +48,9 @@
                 <td>√</td>
                 <td>√</td>
                 <td>√</td>
-                <td>√</td>
             </tr>
             <tr>
-                <td>DQLMysql</td>
-                <td>√</td>
+                <td>ES</td>
                 <td>√</td>
                 <td>√</td>
                 <td>√</td>
@@ -67,25 +58,15 @@
                 <td>√</td>
             </tr>
             <tr>
-                <td>DQLOracle</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
+                <td>SQL(Mysql/Oracle/SqlServer)</td>
+                <td></td>
+                <td></td>
+                <td></td>
+                <td></td>
+                <td></td>
             </tr>
             <tr>
-                <td>DQLSqlServer</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-                <td>√</td>
-            </tr>
-            <tr>
-                <td rowspan="3">版本支持</td>
+                <td rowspan="4">版本支持</td>
                 <td>Mysql</td>
                 <td colspan="7">5.7.19以上</td>
             </tr>
@@ -97,9 +78,13 @@
                 <td>SqlServer</td>
                 <td colspan="7">2008以上</td>
             </tr>
+            <tr>
+                <td>ES</td>
+                <td colspan="7">6.X以上</td>
+            </tr>
             <tr>
                 <td>最近计划</td>
-                <td colspan="7">kafka、es、postgrep</td>
+                <td colspan="7">kafka、postgrep</td>
             </tr>
         </tbody>
     </table>
@@ -113,11 +98,11 @@
     <ol>
         <li>安装JRE1.8版本以上(省略详细)</li>
         <li>下载安装包DBSyncer-X.X.X-RELEASE.zip</li>
-        <li>解压,进入目录bin,启动脚本startup.bat(Windows)/startup.sh(Linux)</li>
+        <li>解压,启动脚本bin/startup.bat(Windows)/ bin/startup.sh(Linux)</li>
         <li>打开浏览器,输入访问地址:http://127.0.0.1:18686</li>
         <li>默认账号和密码:admin/admin</li>
     </ol>
-    <h3>增量同步配置</h3>
+    <h3>增量同步配置(源库)</h3>
     <table>
         <tbody>
             <tr>
@@ -138,7 +123,7 @@
                     <p>max_binlog_cache_size = 256M</p>
                     <p>max_binlog_size = 512M</p>
                     <p>expire_logs_days = 7</p>
-                    <p># 多个库使用英文逗号“,”拼接</p>
+                    <p># 监听同步的库, 多个库使用英文逗号“,”拼接</p>
                     <p>replicate-do-db=test</p>
                 </td>
                 <td>Dump Binlog二进制日志。Master同步Slave, 创建IO线程读取数据,写入relaylog,基于消息订阅捕获增量数据。</td>
@@ -166,32 +151,26 @@
             </tr>
         </tbody>
     </table>
-    <p>Mysql增量示例</p>
-    <p align="center">
-        <img src="https://images.gitee.com/uploads/images/2021/0518/004448_26286acc_376718.png" />
-    </p>
-    <p>Oracle增量示例</p>
-    <p align="center">
-        <img src="https://images.gitee.com/uploads/images/2021/0518/004239_d79cf045_376718.png" />
-    </p>
-    <p>定时示例</p>
-    <p align="center">
-        <img src="https://images.gitee.com/uploads/images/2020/1023/160953_d34d6d11_376718.png" />
-    </p>
 </div>
 
 <div>
     <h3>预览</h3>
     <p align="center">
-        <img src="https://images.gitee.com/uploads/images/2020/0519/000443_b52b4a8c_376718.png" />
+        <img src="https://images.gitee.com/uploads/images/2021/0903/003755_01016fc1_376718.png" />
     </p>
-    <p>驱动关系配置</p>
+    <p>驱动表关系配置</p>
     <p align="center">
-        <img src="https://images.gitee.com/uploads/images/2021/0728/000933_477eb06d_376718.png" />
+        <img src="https://images.gitee.com/uploads/images/2021/0903/004031_a571f6b5_376718.png" />
     </p>
-    <p>驱动表关系配置</p>
+    <p>驱动表字段关系配置</p>
     <p align="center">
-        <img src="https://images.gitee.com/uploads/images/2021/0727/235329_54f0fbc6_376718.png" />
+        <img src="https://images.gitee.com/uploads/images/2021/0903/004106_26399534_376718.png" />
+    </p>
+    <p>定时配置</p>
+    <p align="center">
+        <p>假设源表数据格式</p>
+        <img src="https://images.gitee.com/uploads/images/2021/0903/004406_68ef9bb4_376718.png" />
+        <img src="https://images.gitee.com/uploads/images/2021/0903/004807_07cdf2b7_376718.png" />
     </p>
     <p>监控</p>
     <p align="center">
@@ -201,15 +180,10 @@
     <p align="center">
         <img src="https://images.gitee.com/uploads/images/2021/0806/232643_9b1f3f64_376718.png" />
     </p>
-    <h3>流程图</h3>
-    <p align="center">
-        <img src="http://assets.processon.com/chart_image/5d53b405e4b09965fac2ae27.png" />
-    </p>
 </div>
 
 <div>
 <h3>使用说明</h3>
-    <p>驱动管理<p/>
     <ol>
         <li>创建一个连接器。选择数据源类型,比如:Mysql,填写配置,保存</li>
         <li>添加驱动。配置数据源和目标源(数据源:数据的发送端,目标源:数据接收端),保存</li>
@@ -220,28 +194,17 @@
         <li>点击驱动右上角齿轮按钮,启动或删除</li>
         <li>驱动面板下方显示同步的详细,如果有异常日志,点击日志可跳转至监控菜单查看详细</li>
     </ol>
-    <p>监控<p/>
-    <ol>
-        <li>查看驱动同步数据</li>
-        <li>查看系统性能指标</li>
-        <li>查看系统操作日志</li>
-    </ol>
-    <p>其他<p/>
-    <ol>
-        <li>参数>修改系统参数</li>
-        <li>参数>修改管理员密码</li>
-        <li>注销</li>
-    </ol>
     <h3>开发框架版本</h3>
     <ol>
         <li>JDK - 1.8.0_40 (推荐版本及以上)</li>
         <li>Maven - 3.3.9</li>
-        <li><a target="_blank" href="https://docs.spring.io/spring-boot/docs/2.1.8.RELEASE/reference/html/">Spring Boot - 2.1.8.RELEASE</a></li>
+        <li><a target="_blank" href="https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/html">Spring Boot - 2.2.0.RELEASE</a></li>
         <li><a target="_blank" href="http://getbootstrap.com">Bootstrap - 3.3.4</a></li>
     </ol>
 </div>
 
 <div>
-    <h3>欢迎加群</h3>
-    QQ群: 875519623 或点击右侧按钮 <a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=fce8d51b264130bac5890674e7db99f82f7f8af3f790d49fcf21eaafc8775f2a"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="数据同步dbsyncer" title="数据同步dbsyncer" />
+    <h3>了解更多</h3>
+    博客地址:<a target="_blank" href="https://my.oschina.net/dbsyncer">https://my.oschina.net/dbsyncer</a><br />
+    QQ群: 875519623或点击右侧按钮<a target="_blank" href="//shang.qq.com/wpa/qunwpa?idkey=fce8d51b264130bac5890674e7db99f82f7f8af3f790d49fcf21eaafc8775f2a"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="数据同步dbsyncer" title="数据同步dbsyncer" />
 </div>

+ 1 - 1
dbsyncer-biz/pom.xml

@@ -5,7 +5,7 @@
 	<parent>
 		<artifactId>dbsyncer</artifactId>
 		<groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>dbsyncer-biz</artifactId>

+ 8 - 8
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/AbstractChecker.java

@@ -1,9 +1,9 @@
 package org.dbsyncer.biz.checker;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.biz.BizException;
 import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.common.util.JsonUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.config.Filter;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.parser.model.AbstractConfigModel;
@@ -47,10 +47,10 @@ public abstract class AbstractChecker implements Checker {
         Assert.hasText(model.getName(), "ConfigModel name can not be empty.");
         // 名称
         String name = params.get(ConfigConstant.CONFIG_MODEL_NAME);
-        if (StringUtils.isNotBlank(name)) {
+        if (StringUtil.isNotBlank(name)) {
             model.setName(name);
         }
-        model.setId(StringUtils.isEmpty(model.getId()) ? String.valueOf(snowflakeIdWorker.nextId()) : model.getId());
+        model.setId(StringUtil.isBlank(model.getId()) ? String.valueOf(snowflakeIdWorker.nextId()) : model.getId());
         long now = Instant.now().toEpochMilli();
         model.setCreateTime(null == model.getCreateTime() ? now : model.getCreateTime());
         model.setUpdateTime(now);
@@ -65,18 +65,18 @@ public abstract class AbstractChecker implements Checker {
     protected void modifySuperConfigModel(AbstractConfigModel model, Map<String, String> params) {
         // 全局参数
         String mappingParams = params.get("params");
-        model.setParams(StringUtils.isNotBlank(mappingParams) ? JsonUtil.jsonToObj(mappingParams, Map.class) : new LinkedHashMap());
+        model.setParams(StringUtil.isNotBlank(mappingParams) ? JsonUtil.jsonToObj(mappingParams, Map.class) : new LinkedHashMap());
 
         // 过滤条件
         String filterJson = params.get("filter");
-        if (StringUtils.isNotBlank(filterJson)) {
+        if (StringUtil.isNotBlank(filterJson)) {
             List<Filter> list = jsonToList(filterJson, Filter.class);
             model.setFilter(list);
         }
 
         // 转换配置
         String convertJson = params.get("convert");
-        if (StringUtils.isNotBlank(convertJson)) {
+        if (StringUtil.isNotBlank(convertJson)) {
             List<Convert> convert = jsonToList(convertJson, Convert.class);
             model.setConvert(convert);
         }
@@ -84,11 +84,11 @@ public abstract class AbstractChecker implements Checker {
         // 插件配置
         String pluginClassName = params.get("pluginClassName");
         Plugin plugin = null;
-        if (StringUtils.isNotBlank(pluginClassName)) {
+        if (StringUtil.isNotBlank(pluginClassName)) {
             List<Plugin> plugins = manager.getPluginAll();
             if (!CollectionUtils.isEmpty(plugins)) {
                 for (Plugin p : plugins) {
-                    if (StringUtils.equals(p.getClassName(), pluginClassName)) {
+                    if (StringUtil.equals(p.getClassName(), pluginClassName)) {
                         plugin = p;
                         break;
                     }

+ 4 - 4
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/ConnectorConfigChecker.java

@@ -1,17 +1,17 @@
 package org.dbsyncer.biz.checker;
 
-import org.dbsyncer.parser.model.Connector;
 import org.dbsyncer.parser.model.Mapping;
 import org.dbsyncer.parser.model.TableGroup;
 
 import java.util.Map;
 
 /**
+ * @param <C> ConnectorConfig
  * @author AE86
  * @version 1.0.0
  * @date 2020/1/7 23:17
  */
-public interface ConnectorConfigChecker {
+public interface ConnectorConfigChecker<C> {
 
     /**
      * 处理增量同步策略
@@ -24,10 +24,10 @@ public interface ConnectorConfigChecker {
     /**
      * 修改配置
      *
-     * @param connector
+     * @param connectorConfig
      * @param params
      * @return
      */
-    void modify(Connector connector, Map<String, String> params);
+    void modify(C connectorConfig, Map<String, String> params);
 
 }

+ 6 - 6
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/config/ConfigChecker.java

@@ -1,10 +1,10 @@
 package org.dbsyncer.biz.checker.impl.config;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
 import org.dbsyncer.biz.BizException;
 import org.dbsyncer.biz.checker.AbstractChecker;
+import org.dbsyncer.common.util.NumberUtil;
 import org.dbsyncer.common.util.SHA1Util;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.parser.logger.LogService;
 import org.dbsyncer.parser.logger.LogType;
@@ -66,9 +66,9 @@ public class ConfigChecker extends AbstractChecker {
         // 修改密码
         String newPwd = params.get("newPwd");
         String oldPwd = params.get("oldPwd");
-        if (StringUtils.isNotBlank(newPwd) && StringUtils.isNotBlank(oldPwd)) {
+        if (StringUtil.isNotBlank(newPwd) && StringUtil.isNotBlank(oldPwd)) {
             oldPwd = SHA1Util.b64_sha1(oldPwd);
-            if (!StringUtils.equals(config.getPassword(), oldPwd)) {
+            if (!StringUtil.equals(config.getPassword(), oldPwd)) {
                 logService.log(LogType.SystemLog.ERROR, "修改密码失败");
                 throw new BizException("修改密码失败");
             }
@@ -79,8 +79,8 @@ public class ConfigChecker extends AbstractChecker {
 
         // 刷新监控间隔(秒)
         String refreshInterval = params.get("refreshInterval");
-        if(StringUtils.isNotBlank(refreshInterval)){
-            int time = NumberUtils.toInt(refreshInterval, 10);
+        if (StringUtil.isNotBlank(refreshInterval)) {
+            int time = NumberUtil.toInt(refreshInterval, 10);
             config.setRefreshInterval(time);
         }
 

+ 9 - 13
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/AbstractDataBaseConfigChecker.java

@@ -2,8 +2,6 @@ package org.dbsyncer.biz.checker.impl.connector;
 
 import org.dbsyncer.biz.checker.ConnectorConfigChecker;
 import org.dbsyncer.connector.config.DatabaseConfig;
-import org.dbsyncer.parser.model.Connector;
-import org.springframework.stereotype.Component;
 import org.springframework.util.Assert;
 
 import java.util.Map;
@@ -13,10 +11,10 @@ import java.util.Map;
  * @version 1.0.0
  * @date 2020/1/8 15:17
  */
-public abstract class AbstractDataBaseConfigChecker implements ConnectorConfigChecker {
+public abstract class AbstractDataBaseConfigChecker implements ConnectorConfigChecker<DatabaseConfig> {
 
     @Override
-    public void modify(Connector connector, Map<String, String> params) {
+    public void modify(DatabaseConfig connectorConfig, Map<String, String> params) {
         String username = params.get("username");
         String password = params.get("password");
         String url = params.get("url");
@@ -26,21 +24,19 @@ public abstract class AbstractDataBaseConfigChecker implements ConnectorConfigCh
         Assert.hasText(url, "Url is empty.");
         Assert.hasText(driverClassName, "DriverClassName is empty.");
 
-        DatabaseConfig config = (DatabaseConfig) connector.getConfig();
-        config.setUsername(username);
-        config.setPassword(password);
-        config.setUrl(url);
-        config.setDriverClassName(driverClassName);
+        connectorConfig.setUsername(username);
+        connectorConfig.setPassword(password);
+        connectorConfig.setUrl(url);
+        connectorConfig.setDriverClassName(driverClassName);
     }
 
-    protected void modifyDql(Connector connector, Map<String, String> params) {
+    protected void modifyDql(DatabaseConfig connectorConfig, Map<String, String> params) {
         String sql = params.get("sql");
         String table = params.get("table");
         Assert.hasText(sql, "Sql is empty.");
         Assert.hasText(table, "Table is empty.");
-        DatabaseConfig config = (DatabaseConfig) connector.getConfig();
-        config.setSql(sql);
-        config.setTable(table);
+        connectorConfig.setSql(sql);
+        connectorConfig.setTable(table);
     }
 
 }

+ 6 - 5
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/ConnectorChecker.java

@@ -52,13 +52,14 @@ public class ConnectorChecker extends AbstractChecker {
         Connector connector = new Connector();
         connector.setName(name);
         connector.setType(ConfigConstant.CONNECTOR);
-        setConfig(connector, connectorType);
+        ConnectorConfig config = getConfig(connectorType);
+        connector.setConfig(config);
 
         // 配置连接器配置
         String type = StringUtil.toLowerCaseFirstOne(connectorType).concat("ConfigChecker");
         ConnectorConfigChecker checker = map.get(type);
         Assert.notNull(checker, "Checker can not be null.");
-        checker.modify(connector, params);
+        checker.modify(config, params);
 
         // 获取表
         setTable(connector);
@@ -85,7 +86,7 @@ public class ConnectorChecker extends AbstractChecker {
         String type = StringUtil.toLowerCaseFirstOne(config.getConnectorType()).concat("ConfigChecker");
         ConnectorConfigChecker checker = map.get(type);
         Assert.notNull(checker, "Checker can not be null.");
-        checker.modify(connector, params);
+        checker.modify(config, params);
 
         // 获取表
         setTable(connector);
@@ -93,13 +94,13 @@ public class ConnectorChecker extends AbstractChecker {
         return connector;
     }
 
-    private void setConfig(Connector connector, String connectorType) {
+    private ConnectorConfig getConfig(String connectorType) {
         Class<ConnectorConfig> configClass = (Class<ConnectorConfig>) ConnectorEnum.getConfigClass(connectorType);
         Assert.notNull(configClass, String.format("不支持该连接器类型:%s", connectorType));
         try {
             ConnectorConfig config = configClass.newInstance();
             config.setConnectorType(connectorType);
-            connector.setConfig(config);
+            return config;
         } catch (Exception e) {
             logger.error(e.getMessage());
             throw new BizException("获取连接器配置异常.");

+ 4 - 4
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlMysqlConfigChecker.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.biz.checker.impl.connector;
 
-import org.dbsyncer.parser.model.Connector;
+import org.dbsyncer.connector.config.DatabaseConfig;
 import org.springframework.stereotype.Component;
 
 import java.util.Map;
@@ -14,8 +14,8 @@ import java.util.Map;
 public class DqlMysqlConfigChecker extends AbstractDataBaseConfigChecker {
 
     @Override
-    public void modify(Connector connector, Map<String, String> params) {
-        super.modify(connector, params);
-        super.modifyDql(connector, params);
+    public void modify(DatabaseConfig connectorConfig, Map<String, String> params) {
+        super.modify(connectorConfig, params);
+        super.modifyDql(connectorConfig, params);
     }
 }

+ 4 - 4
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlOracleConfigChecker.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.biz.checker.impl.connector;
 
-import org.dbsyncer.parser.model.Connector;
+import org.dbsyncer.connector.config.DatabaseConfig;
 import org.springframework.stereotype.Component;
 
 import java.util.Map;
@@ -14,8 +14,8 @@ import java.util.Map;
 public class DqlOracleConfigChecker extends AbstractDataBaseConfigChecker {
 
     @Override
-    public void modify(Connector connector, Map<String, String> params) {
-        super.modify(connector, params);
-        super.modifyDql(connector, params);
+    public void modify(DatabaseConfig connectorConfig, Map<String, String> params) {
+        super.modify(connectorConfig, params);
+        super.modifyDql(connectorConfig, params);
     }
 }

+ 4 - 4
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/DqlSqlServerConfigChecker.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.biz.checker.impl.connector;
 
-import org.dbsyncer.parser.model.Connector;
+import org.dbsyncer.connector.config.DatabaseConfig;
 import org.springframework.stereotype.Component;
 
 import java.util.Map;
@@ -14,8 +14,8 @@ import java.util.Map;
 public class DqlSqlServerConfigChecker extends AbstractDataBaseConfigChecker {
 
     @Override
-    public void modify(Connector connector, Map<String, String> params) {
-        super.modify(connector, params);
-        super.modifyDql(connector, params);
+    public void modify(DatabaseConfig connectorConfig, Map<String, String> params) {
+        super.modify(connectorConfig, params);
+        super.modifyDql(connectorConfig, params);
     }
 }

+ 42 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/ElasticsearchConfigChecker.java

@@ -0,0 +1,42 @@
+package org.dbsyncer.biz.checker.impl.connector;
+
+import org.dbsyncer.biz.checker.ConnectorConfigChecker;
+import org.dbsyncer.connector.config.ESConfig;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import java.util.Map;
+
+/**
+ * @author AE86
+ * @version 1.0.0
+ * @date 2021/8/25 23:30
+ */
+@Component
+public class ElasticsearchConfigChecker implements ConnectorConfigChecker<ESConfig> {
+
+    @Override
+    public void modify(ESConfig connectorConfig, Map<String, String> params) {
+        String username = params.get("username");
+        String password = params.get("password");
+        String index = params.get("index");
+        String type = params.get("type");
+        String url = params.get("url");
+        String schema = params.get("schema");
+        String primaryKey = params.get("primaryKey");
+        Assert.hasText(username, "Username is empty.");
+        Assert.hasText(password, "Password is empty.");
+        Assert.hasText(index, "Index is empty.");
+        Assert.hasText(type, "Type is empty.");
+        Assert.hasText(url, "Url is empty.");
+        Assert.hasText(schema, "Schema is empty.");
+
+        connectorConfig.setUsername(username);
+        connectorConfig.setPassword(password);
+        connectorConfig.setIndex(index);
+        connectorConfig.setType(type);
+        connectorConfig.setUrl(url);
+        connectorConfig.setSchema(schema);
+        connectorConfig.setPrimaryKey(primaryKey);
+    }
+}

+ 4 - 4
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/connector/OracleConfigChecker.java

@@ -1,8 +1,8 @@
 package org.dbsyncer.biz.checker.impl.connector;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.biz.enums.OracleIncrementEnum;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.config.Field;
 import org.dbsyncer.connector.config.MetaInfo;
 import org.dbsyncer.connector.config.Table;
@@ -48,7 +48,7 @@ public class OracleConfigChecker extends AbstractDataBaseConfigChecker {
         List<Field> targetColumn = tableGroup.getTargetTable().getColumn();
         Field targetField = null;
         for (Field f : targetColumn) {
-            if (StringUtils.equals(f.getName(), targetRowIdName)) {
+            if (StringUtil.equals(f.getName(), targetRowIdName)) {
                 targetField = f;
                 targetField.setPk(true);
                 continue;
@@ -69,7 +69,7 @@ public class OracleConfigChecker extends AbstractDataBaseConfigChecker {
             }
 
             // 排除主键关系
-            if (null != m.getTarget() && StringUtils.equals(m.getTarget().getName(), targetRowIdName)) {
+            if (null != m.getTarget() && StringUtil.equals(m.getTarget().getName(), targetRowIdName)) {
                 continue;
             }
 
@@ -151,7 +151,7 @@ public class OracleConfigChecker extends AbstractDataBaseConfigChecker {
                 continue;
             }
 
-            if (null != m.getTarget() && StringUtils.equals(m.getTarget().getName(), pk)) {
+            if (null != m.getTarget() && StringUtil.equals(m.getTarget().getName(), pk)) {
                 m.getTarget().setPk(true);
             }
             list.add(m);

+ 3 - 3
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/mapping/MappingChecker.java

@@ -1,10 +1,10 @@
 package org.dbsyncer.biz.checker.impl.mapping;
 
-import org.apache.commons.lang.math.NumberUtils;
 import org.dbsyncer.biz.checker.AbstractChecker;
 import org.dbsyncer.biz.checker.MappingConfigChecker;
 import org.dbsyncer.biz.checker.impl.tablegroup.TableGroupChecker;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.NumberUtil;
 import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.listener.config.ListenerConfig;
 import org.dbsyncer.listener.enums.ListenerTypeEnum;
@@ -90,8 +90,8 @@ public class MappingChecker extends AbstractChecker {
         mapping.setModel(null != ModelEnum.getModelEnum(model) ? model : ModelEnum.FULL.getCode());
 
         // 全量配置
-        mapping.setReadNum(NumberUtils.toInt(params.get("readNum"), mapping.getReadNum()));
-        mapping.setBatchNum(NumberUtils.toInt(params.get("batchNum"), mapping.getBatchNum()));
+        mapping.setReadNum(NumberUtil.toInt(params.get("readNum"), mapping.getReadNum()));
+        mapping.setBatchNum(NumberUtil.toInt(params.get("batchNum"), mapping.getBatchNum()));
 
         // 增量配置(日志/定时)
         String incrementStrategy = params.get("incrementStrategy");

+ 8 - 8
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/mapping/TimingConfigChecker.java

@@ -1,8 +1,8 @@
 package org.dbsyncer.biz.checker.impl.mapping;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
 import org.dbsyncer.biz.checker.MappingConfigChecker;
+import org.dbsyncer.common.util.NumberUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.listener.config.ListenerConfig;
 import org.dbsyncer.listener.enums.ListenerTypeEnum;
 import org.dbsyncer.parser.model.Mapping;
@@ -32,19 +32,19 @@ public class TimingConfigChecker implements MappingConfigChecker {
         ListenerConfig config = mapping.getListener();
         Assert.notNull(config, "ListenerConfig can not be null.");
 
-        if (StringUtils.isNotBlank(period)) {
-            config.setPeriod(NumberUtils.toLong(period, 30));
+        if (StringUtil.isNotBlank(period)) {
+            config.setPeriod(NumberUtil.toLong(period, 30));
         }
-        if (StringUtils.isNotBlank(eventFieldName)) {
+        if (StringUtil.isNotBlank(eventFieldName)) {
             config.setEventFieldName(eventFieldName);
         }
-        if (StringUtils.isNotBlank(insert)) {
+        if (StringUtil.isNotBlank(insert)) {
             config.setInsert(insert);
         }
-        if (StringUtils.isNotBlank(update)) {
+        if (StringUtil.isNotBlank(update)) {
             config.setUpdate(update);
         }
-        if (StringUtils.isNotBlank(delete)) {
+        if (StringUtil.isNotBlank(delete)) {
             config.setDelete(delete);
         }
 

+ 2 - 3
dbsyncer-biz/src/main/java/org/dbsyncer/biz/checker/impl/tablegroup/TableGroupChecker.java

@@ -1,6 +1,5 @@
 package org.dbsyncer.biz.checker.impl.tablegroup;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.biz.BizException;
 import org.dbsyncer.biz.checker.AbstractChecker;
 import org.dbsyncer.biz.checker.ConnectorConfigChecker;
@@ -142,8 +141,8 @@ public class TableGroupChecker extends AbstractChecker {
         if (!CollectionUtils.isEmpty(list)) {
             for (TableGroup g : list) {
                 // 数据源表和目标表都存在
-                if (StringUtils.equals(sourceTable, g.getSourceTable().getName())
-                        && StringUtils.equals(targetTable, g.getTargetTable().getName())) {
+                if (StringUtil.equals(sourceTable, g.getSourceTable().getName())
+                        && StringUtil.equals(targetTable, g.getTargetTable().getName())) {
                     final String error = String.format("映射关系已存在.%s > %s", sourceTable, targetTable);
                     logger.error(error);
                     throw new BizException(error);

+ 2 - 2
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/ConnectorServiceImpl.java

@@ -1,8 +1,8 @@
 package org.dbsyncer.biz.impl;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.biz.ConnectorService;
 import org.dbsyncer.biz.checker.Checker;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.parser.logger.LogType;
 import org.dbsyncer.parser.model.ConfigModel;
@@ -57,7 +57,7 @@ public class ConnectorServiceImpl extends BaseServiceImpl implements ConnectorSe
 
     @Override
     public Connector getConnector(String id) {
-        return StringUtils.isNotBlank(id) ? manager.getConnector(id) : null;
+        return StringUtil.isNotBlank(id) ? manager.getConnector(id) : null;
     }
 
     @Override

+ 2 - 2
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MappingServiceImpl.java

@@ -1,6 +1,5 @@
 package org.dbsyncer.biz.impl;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.biz.BizException;
 import org.dbsyncer.biz.MappingService;
 import org.dbsyncer.biz.TableGroupService;
@@ -9,6 +8,7 @@ import org.dbsyncer.biz.vo.ConnectorVo;
 import org.dbsyncer.biz.vo.MappingVo;
 import org.dbsyncer.biz.vo.MetaVo;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.monitor.Monitor;
 import org.dbsyncer.parser.enums.ModelEnum;
 import org.dbsyncer.parser.logger.LogType;
@@ -52,7 +52,7 @@ public class MappingServiceImpl extends BaseServiceImpl implements MappingServic
 
         // 匹配相似表 on
         String autoMatchTable = params.get("autoMatchTable");
-        if(StringUtils.isNotBlank(autoMatchTable)){
+        if(StringUtil.isNotBlank(autoMatchTable)){
             matchSimilarTable(model);
         }
 

+ 11 - 8
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/MonitorServiceImpl.java

@@ -1,7 +1,5 @@
 package org.dbsyncer.biz.impl;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
 import org.dbsyncer.biz.MonitorService;
 import org.dbsyncer.biz.metric.MetricDetailFormatter;
 import org.dbsyncer.biz.metric.impl.*;
@@ -9,6 +7,8 @@ import org.dbsyncer.biz.vo.*;
 import org.dbsyncer.common.model.Paging;
 import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.common.util.JsonUtil;
+import org.dbsyncer.common.util.NumberUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.monitor.Monitor;
 import org.dbsyncer.monitor.enums.DiskMetricEnum;
 import org.dbsyncer.monitor.enums.MetricEnum;
@@ -26,7 +26,10 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 
 import javax.annotation.PostConstruct;
-import java.util.*;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -80,8 +83,8 @@ public class MonitorServiceImpl implements MonitorService {
     @Override
     public Paging queryData(Map<String, String> params) {
         String id = params.get(ConfigConstant.CONFIG_MODEL_ID);
-        int pageNum = NumberUtils.toInt(params.get("pageNum"), 1);
-        int pageSize = NumberUtils.toInt(params.get("pageSize"), 10);
+        int pageNum = NumberUtil.toInt(params.get("pageNum"), 1);
+        int pageSize = NumberUtil.toInt(params.get("pageSize"), 10);
         String error = params.get(ConfigConstant.DATA_ERROR);
         String success = params.get(ConfigConstant.DATA_SUCCESS);
 
@@ -102,8 +105,8 @@ public class MonitorServiceImpl implements MonitorService {
 
     @Override
     public Paging queryLog(Map<String, String> params) {
-        int pageNum = NumberUtils.toInt(params.get("pageNum"), 1);
-        int pageSize = NumberUtils.toInt(params.get("pageSize"), 10);
+        int pageNum = NumberUtil.toInt(params.get("pageNum"), 1);
+        int pageSize = NumberUtil.toInt(params.get("pageSize"), 10);
         String json = params.get(ConfigConstant.CONFIG_MODEL_JSON);
         Paging paging = monitor.queryLog(pageNum, pageSize, json);
         List<Map> data = (List<Map>) paging.getData();
@@ -153,7 +156,7 @@ public class MonitorServiceImpl implements MonitorService {
     }
 
     private String getDefaultMetaId(String id) {
-        if (StringUtils.isBlank(id)) {
+        if (StringUtil.isBlank(id)) {
             List<MetaVo> list = getMetaAll();
             if (!CollectionUtils.isEmpty(list)) {
                 return list.get(0).getId();

+ 5 - 5
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/PluginServiceImpl.java

@@ -1,10 +1,10 @@
 package org.dbsyncer.biz.impl;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.biz.BizException;
 import org.dbsyncer.biz.PluginService;
 import org.dbsyncer.biz.vo.PluginVo;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.parser.logger.LogService;
 import org.dbsyncer.parser.logger.LogType;
@@ -45,7 +45,7 @@ public class PluginServiceImpl implements PluginService {
             if (!CollectionUtils.isEmpty(mappingAll)) {
                 mappingAll.forEach(mapping -> {
                     Plugin plugin = mapping.getPlugin();
-                    if(null != plugin){
+                    if (null != plugin) {
                         pluginClassNameMap.putIfAbsent(plugin.getClassName(), new ArrayList<>());
                         pluginClassNameMap.get(plugin.getClassName()).add(mapping.getName());
                     }
@@ -55,7 +55,7 @@ public class PluginServiceImpl implements PluginService {
             vos.addAll(pluginAll.stream().map(plugin -> {
                 PluginVo vo = new PluginVo();
                 BeanUtils.copyProperties(plugin, vo);
-                vo.setMappingName(StringUtils.join(pluginClassNameMap.get(plugin.getClassName()), "|"));
+                vo.setMappingName(StringUtil.join(pluginClassNameMap.get(plugin.getClassName()), "|"));
                 return vo;
             }).collect(Collectors.toList()));
         }
@@ -80,10 +80,10 @@ public class PluginServiceImpl implements PluginService {
 
     @Override
     public void checkFileSuffix(String filename) {
-        if (StringUtils.isNotBlank(filename)) {
+        if (StringUtil.isNotBlank(filename)) {
             String suffix = filename.substring(filename.lastIndexOf(".") + 1, filename.length());
             if (null == FileSuffixEnum.getFileSuffix(suffix)) {
-                suffix = StringUtils.join(FileSuffixEnum.values(), ",").toLowerCase();
+                suffix = StringUtil.join(FileSuffixEnum.values(), ",").toLowerCase();
                 String msg = String.format("不正确的文件扩展名 \"%s\",只支持 \"%s\" 的文件扩展名。", filename, suffix);
                 logService.log(LogType.PluginLog.CHECK_ERROR, msg);
                 throw new BizException(msg);

+ 1 - 1
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/DiskMetricDetailFormatter.java

@@ -6,7 +6,7 @@ import org.dbsyncer.monitor.model.Sample;
 
 import java.math.BigDecimal;
 
-public class DiskMetricDetailFormatter extends AbstractMetricDetailFormatter {
+public final class DiskMetricDetailFormatter extends AbstractMetricDetailFormatter {
 
     @Override
     public void apply(MetricResponseVo vo) {

+ 1 - 4
dbsyncer-biz/src/main/java/org/dbsyncer/biz/metric/impl/MemoryMetricDetailFormatter.java

@@ -2,12 +2,9 @@ package org.dbsyncer.biz.metric.impl;
 
 import org.dbsyncer.biz.metric.AbstractMetricDetailFormatter;
 import org.dbsyncer.biz.vo.MetricResponseVo;
-import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.monitor.model.Sample;
 
-import java.text.DecimalFormat;
-
-public class MemoryMetricDetailFormatter extends AbstractMetricDetailFormatter {
+public final class MemoryMetricDetailFormatter extends AbstractMetricDetailFormatter {
 
     @Override
     public void apply(MetricResponseVo vo) {

+ 1 - 1
dbsyncer-cache/pom.xml

@@ -4,7 +4,7 @@
 	<parent>
 		<artifactId>dbsyncer</artifactId>
 		<groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
 	</parent>
 	<modelVersion>4.0.0</modelVersion>
 	<artifactId>dbsyncer-cache</artifactId>

+ 1 - 1
dbsyncer-cluster/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-cluster</artifactId>

+ 4 - 4
dbsyncer-common/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-common</artifactId>
@@ -45,10 +45,10 @@
             <artifactId>caffeine</artifactId>
         </dependency>
 
-        <!-- apache 字符工具类 -->
+        <!-- apache 工具类 -->
         <dependency>
-            <groupId>commons-lang</groupId>
-            <artifactId>commons-lang</artifactId>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
         </dependency>
         <dependency>
             <groupId>commons-io</groupId>

+ 0 - 2
dbsyncer-common/src/main/java/org/dbsyncer/common/util/CollectionUtils.java

@@ -4,8 +4,6 @@ import java.util.Collection;
 import java.util.Map;
 
 public abstract class CollectionUtils {
-    public CollectionUtils() {
-    }
 
     public static boolean isEmpty(Collection<?> collection) {
         return collection == null || collection.isEmpty();

+ 0 - 3
dbsyncer-common/src/main/java/org/dbsyncer/common/util/DateFormatUtil.java

@@ -13,9 +13,6 @@ public abstract class DateFormatUtil {
     private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
     private static ZoneId zoneId = ZoneId.systemDefault();
 
-    public DateFormatUtil() {
-    }
-
     public static String getCurrentTime() {
         return LocalDateTime.now().format(timeFormatter);
     }

+ 6 - 0
dbsyncer-common/src/main/java/org/dbsyncer/common/util/JsonUtil.java

@@ -3,6 +3,8 @@ package org.dbsyncer.common.util;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.serializer.SerializerFeature;
 
+import java.util.List;
+
 public abstract class JsonUtil {
 
     public static String objToJson(Object obj) {
@@ -13,4 +15,8 @@ public abstract class JsonUtil {
         return JSON.parseObject(json, valueType);
     }
 
+    public static <T> List<T> jsonToArray(String json, Class<T> valueType) {
+        return JSON.parseArray(json, valueType);
+    }
+
 }

+ 22 - 0
dbsyncer-common/src/main/java/org/dbsyncer/common/util/NumberUtil.java

@@ -0,0 +1,22 @@
+package org.dbsyncer.common.util;
+
+import org.apache.commons.lang3.math.NumberUtils;
+
+public abstract class NumberUtil {
+
+    public static int toInt(String str) {
+        return NumberUtils.toInt(str);
+    }
+
+    public static int toInt(String str, int defaultValue) {
+        return NumberUtils.toInt(str, defaultValue);
+    }
+
+    public static long toLong(String str, long defaultValue) {
+        return NumberUtils.toLong(str, defaultValue);
+    }
+
+    public static boolean isCreatable(String str) {
+        return NumberUtils.isCreatable(str);
+    }
+}

+ 11 - 0
dbsyncer-common/src/main/java/org/dbsyncer/common/util/RandomUtil.java

@@ -0,0 +1,11 @@
+package org.dbsyncer.common.util;
+
+import org.apache.commons.lang3.RandomUtils;
+
+public abstract class RandomUtil {
+
+    public static int nextInt(int startInclusive, int endExclusive) {
+        return RandomUtils.nextInt(startInclusive, endExclusive);
+    }
+
+}

+ 56 - 2
dbsyncer-common/src/main/java/org/dbsyncer/common/util/StringUtil.java

@@ -1,9 +1,63 @@
 package org.dbsyncer.common.util;
 
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
 
 public abstract class StringUtil {
-    public StringUtil() {
+
+    public static boolean equals(CharSequence cs1, CharSequence cs2) {
+        return StringUtils.equals(cs1, cs2);
+    }
+
+    public static boolean isBlank(CharSequence cs) {
+        return StringUtils.isBlank(cs);
+    }
+
+    public static boolean isNotBlank(CharSequence cs) {
+        return StringUtils.isNotBlank(cs);
+    }
+
+    public static String[] split(String str, String separatorChars) {
+        return StringUtils.split(str, separatorChars);
+    }
+
+    public static boolean contains(CharSequence seq, CharSequence searchSeq) {
+        return StringUtils.contains(seq, searchSeq);
+    }
+
+    public static String replace(String text, String searchString, String replacement) {
+        return StringUtils.replace(text, searchString, replacement);
+    }
+
+    public static String replaceOnce(String text, String searchString, String replacement) {
+        return StringUtils.replaceOnce(text, searchString, replacement);
+    }
+
+    public static String join(Iterable<?> iterable, String separator) {
+        return StringUtils.join(iterable, separator);
+    }
+
+    public static String join(Object[] array, String separator) {
+        return StringUtils.join(array, separator);
+    }
+
+    public static String substring(String str, int start) {
+        return StringUtils.substring(str, start);
+    }
+
+    public static String substring(String str, int start, int end) {
+        return StringUtils.substring(str, start, end);
+    }
+
+    public static int indexOf(CharSequence seq, CharSequence searchChar) {
+        return StringUtils.indexOf(seq, searchChar);
+    }
+
+    public static int lastIndexOf(CharSequence seq, CharSequence searchChar) {
+        return StringUtils.lastIndexOf(seq, searchChar);
+    }
+
+    public static boolean startsWith(CharSequence str, CharSequence prefix) {
+        return StringUtils.startsWith(str, prefix);
     }
 
     /**

+ 13 - 1
dbsyncer-connector/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-connector</artifactId>
@@ -42,6 +42,18 @@
             <artifactId>mssql-jdbc</artifactId>
         </dependency>
 
+        <!-- smartcn中文分词器 -->
+        <dependency>
+            <groupId>org.apache.lucene</groupId>
+            <artifactId>lucene-analyzers-smartcn</artifactId>
+        </dependency>
+
+        <!-- elasticsearch -->
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-high-level-client</artifactId>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 31 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/AbstractConnector.java

@@ -0,0 +1,31 @@
+package org.dbsyncer.connector;
+
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.config.Field;
+import org.dbsyncer.connector.constant.ConnectorConstant;
+
+import java.util.List;
+
+public abstract class AbstractConnector {
+
+    protected Field getPrimaryKeyField(List<Field> fields) {
+        for (Field f : fields) {
+            if (f.isPk()) {
+                return f;
+            }
+        }
+        throw new ConnectorException("主键为空");
+    }
+
+    protected boolean isUpdate(String event) {
+        return StringUtil.equals(ConnectorConstant.OPERTION_UPDATE, event);
+    }
+
+    protected boolean isInsert(String event) {
+        return StringUtil.equals(ConnectorConstant.OPERTION_INSERT, event);
+    }
+
+    protected boolean isDelete(String event) {
+        return StringUtil.equals(ConnectorConstant.OPERTION_DELETE, event);
+    }
+}

+ 31 - 25
dbsyncer-connector/src/main/java/org/dbsyncer/connector/Connector.java

@@ -3,17 +3,20 @@ package org.dbsyncer.connector;
 import org.dbsyncer.common.model.Result;
 import org.dbsyncer.connector.config.*;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
 /**
  * 连接器基础功能
  *
+ * @param <M> ConnectorMapper
+ * @param <C> ConnectorConfig
  * @author AE86
  * @version 1.0.0
  * @date 2019/9/18 23:30
  */
-public interface Connector {
+public interface Connector<M, C> {
 
     /**
      * 建立连接
@@ -21,14 +24,14 @@ public interface Connector {
      * @param config
      * @return
      */
-    ConnectorMapper connect(ConnectorConfig config);
+    ConnectorMapper connect(C config);
 
     /**
      * 断开连接
      *
      * @param connectorMapper
      */
-    void disconnect(ConnectorMapper connectorMapper);
+    void disconnect(M connectorMapper);
 
     /**
      * 检查连接器是否连接正常
@@ -36,7 +39,7 @@ public interface Connector {
      * @param connectorMapper
      * @return
      */
-    boolean isAlive(ConnectorMapper connectorMapper);
+    boolean isAlive(M connectorMapper);
 
     /**
      * 获取连接缓存key
@@ -44,7 +47,7 @@ public interface Connector {
      * @param config
      * @return
      */
-    String getConnectorMapperCacheKey(ConnectorConfig config);
+    String getConnectorMapperCacheKey(C config);
 
     /**
      * 获取所有表名
@@ -52,7 +55,7 @@ public interface Connector {
      * @param connectorMapper
      * @return
      */
-    List<String> getTable(ConnectorMapper connectorMapper);
+    List<String> getTable(M connectorMapper);
 
     /**
      * 获取表元信息
@@ -61,55 +64,58 @@ public interface Connector {
      * @param tableName
      * @return
      */
-    MetaInfo getMetaInfo(ConnectorMapper connectorMapper, String tableName);
+    MetaInfo getMetaInfo(M connectorMapper, String tableName);
 
     /**
-     * 获取数据源同步参
+     * 获取
      *
-     * @param commandConfig
+     * @param connectorMapper
+     * @param command
      * @return
      */
-    Map<String, String> getSourceCommand(CommandConfig commandConfig);
+    long getCount(M connectorMapper, Map<String, String> command);
 
     /**
-     * 获取目标源同步参数
+     * 分页获取数据源数据
      *
-     * @param commandConfig
+     * @param config
      * @return
      */
-    Map<String, String> getTargetCommand(CommandConfig commandConfig);
+    Result reader(M connectorMapper, ReaderConfig config);
 
     /**
-     * 获取总数
+     * 批量写入目标源数据
      *
      * @param config
-     * @param command
      * @return
      */
-    long getCount(ConnectorMapper config, Map<String, String> command);
+    Result writer(M connectorMapper, WriterBatchConfig config);
 
     /**
-     * 分页获取数据源数据
+     * 写入目标源数据
      *
      * @param config
      * @return
      */
-    Result reader(ReaderConfig config);
+    Result writer(M connectorMapper, WriterSingleConfig config);
 
     /**
-     * 批量写入目标源数据
+     * 获取数据源同步参数
      *
-     * @param config
+     * @param commandConfig
      * @return
      */
-    Result writer(WriterBatchConfig config);
+    default Map<String, String> getSourceCommand(CommandConfig commandConfig) {
+        return Collections.EMPTY_MAP;
+    }
 
     /**
-     * 写入目标源数据
+     * 获取目标源同步参数
      *
-     * @param config
+     * @param commandConfig
      * @return
      */
-    Result writer(WriterSingleConfig config);
-
+    default Map<String, String> getTargetCommand(CommandConfig commandConfig) {
+        return Collections.EMPTY_MAP;
+    }
 }

+ 13 - 18
dbsyncer-connector/src/main/java/org/dbsyncer/connector/ConnectorFactory.java

@@ -86,7 +86,7 @@ public class ConnectorFactory implements DisposableBean {
      */
     public List<String> getTable(ConnectorMapper config) {
         Assert.notNull(config, "ConnectorMapper can not be null.");
-        String type = config.getConfig().getConnectorType();
+        String type = config.getOriginalConfig().getConnectorType();
         return getConnector(type).getTable(config);
     }
 
@@ -112,10 +112,8 @@ public class ConnectorFactory implements DisposableBean {
         String sType = sourceCommandConfig.getType();
         String tType = targetCommandConfig.getType();
         Map<String, String> map = new HashMap<>();
-        Map<String, String> sCmd = getConnector(sType).getSourceCommand(sourceCommandConfig);
-        Map<String, String> tCmd = getConnector(tType).getTargetCommand(targetCommandConfig);
-        map.putAll(sCmd);
-        map.putAll(tCmd);
+        map.putAll(getConnector(sType).getSourceCommand(sourceCommandConfig));
+        map.putAll(getConnector(tType).getTargetCommand(targetCommandConfig));
         return map;
     }
 
@@ -130,29 +128,26 @@ public class ConnectorFactory implements DisposableBean {
         return getConnector(config).getCount(config, command);
     }
 
-    public Result reader(ReaderConfig config) {
-        Connector connector = getConnector(config.getConnectorMapper());
-        Result result = connector.reader(config);
+    public Result reader(ConnectorMapper connectionMapper, ReaderConfig config) {
+        Result result = getConnector(connectionMapper).reader(connectionMapper, config);
         Assert.notNull(result, "Connector reader result can not null");
         return result;
     }
 
-    public Result writer(WriterBatchConfig config) {
-        Connector connector = getConnector(config.getConnectorMapper());
-        Result result = connector.writer(config);
-        Assert.notNull(result, "Connector writer result can not null");
+    public Result writer(ConnectorMapper connectionMapper, WriterBatchConfig config) {
+        Result result = getConnector(connectionMapper).writer(connectionMapper, config);
+        Assert.notNull(result, "Connector writer batch result can not null");
         return result;
     }
 
-    public Result writer(WriterSingleConfig config) {
-        Connector connector = getConnector(config.getConnectorMapper());
-        Result result = connector.writer(config);
-        Assert.notNull(result, "Connector writer result can not null");
+    public Result writer(ConnectorMapper connectionMapper, WriterSingleConfig config) {
+        Result result = getConnector(connectionMapper).writer(connectionMapper, config);
+        Assert.notNull(result, "Connector writer single result can not null");
         return result;
     }
 
     public Connector getConnector(ConnectorMapper connectorMapper) {
-        return getConnector(connectorMapper.getConfig().getConnectorType());
+        return getConnector(connectorMapper.getOriginalConfig().getConnectorType());
     }
 
     /**
@@ -174,7 +169,7 @@ public class ConnectorFactory implements DisposableBean {
      */
     private void disconnect(ConnectorMapper connectorMapper) {
         Assert.notNull(connectorMapper, "ConnectorMapper can not be null.");
-        String type = connectorMapper.getConfig().getConnectorType();
+        String type = connectorMapper.getOriginalConfig().getConnectorType();
         getConnector(type).disconnect(connectorMapper);
     }
 

+ 5 - 27
dbsyncer-connector/src/main/java/org/dbsyncer/connector/ConnectorMapper.java

@@ -1,36 +1,14 @@
 package org.dbsyncer.connector;
 
 import org.dbsyncer.connector.config.ConnectorConfig;
-import org.dbsyncer.connector.database.DatabaseTemplate;
-import org.springframework.dao.EmptyResultDataAccessException;
 
-import java.sql.Connection;
+public interface ConnectorMapper<K, V> {
 
-public class ConnectorMapper {
-    protected ConnectorConfig config;
-    protected Connection connection;
-
-    public ConnectorMapper(ConnectorConfig config, Connection connection) {
-        this.config = config;
-        this.connection = connection;
-    }
-
-    public ConnectorConfig getConfig() {
-        return config;
+    default ConnectorConfig getOriginalConfig() {
+        return (ConnectorConfig) getConfig();
     }
 
-    public Connection getConnection() {
-        return connection;
-    }
-
-    public <T> T execute(HandleCallback callback) {
-        try {
-            return (T) callback.apply(new DatabaseTemplate(connection));
-        } catch (EmptyResultDataAccessException e) {
-            throw e;
-        }catch (Exception e) {
-            throw new ConnectorException(e.getMessage());
-        }
-    }
+    K getConfig();
 
+    V getConnection();
 }

+ 101 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/ESConfig.java

@@ -0,0 +1,101 @@
+package org.dbsyncer.connector.config;
+
+/**
+ * @author AE86
+ * @ClassName: ESConfig
+ * @Description: ES连接配置
+ * @date: 2021年8月23日 下午8:00:00
+ */
+public class ESConfig extends ConnectorConfig {
+
+    /**
+     * 集群地址192.168.1.100:9200,192.168.1.200:9200
+     */
+    private String url;
+
+    /**
+     * 协议9200(http),9300(tcp)
+     */
+    private String schema;
+
+    /**
+     * 帐号
+     */
+    private String username;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 索引(相当于数据库)
+     */
+    private String index;
+
+    /**
+     * 类型(相当于表)
+     */
+    private String type;
+
+    /**
+     * 主键
+     */
+    private String primaryKey;
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getSchema() {
+        return schema;
+    }
+
+    public void setSchema(String schema) {
+        this.schema = schema;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getIndex() {
+        return index;
+    }
+
+    public void setIndex(String index) {
+        this.index = index;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getPrimaryKey() {
+        return primaryKey;
+    }
+
+    public void setPrimaryKey(String primaryKey) {
+        this.primaryKey = primaryKey;
+    }
+}

+ 1 - 14
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/ReaderConfig.java

@@ -1,35 +1,22 @@
 package org.dbsyncer.connector.config;
 
-import org.dbsyncer.connector.ConnectorMapper;
-
 import java.util.List;
 import java.util.Map;
 
 public class ReaderConfig {
 
-    private ConnectorMapper connectorMapper;
     private Map<String, String> command;
     private List<Object> args;
     private int pageIndex;
     private int pageSize;
 
-    public ReaderConfig(ConnectorMapper connectorMapper, Map<String,String> command, List<Object> args, int pageIndex, int pageSize) {
-        this.connectorMapper = connectorMapper;
+    public ReaderConfig(Map<String,String> command, List<Object> args, int pageIndex, int pageSize) {
         this.command = command;
         this.args = args;
         this.pageIndex = pageIndex;
         this.pageSize = pageSize;
     }
 
-    public ConnectorMapper getConnectorMapper() {
-        return connectorMapper;
-    }
-
-    public ReaderConfig setConnectorMapper(ConnectorMapper connectorMapper) {
-        this.connectorMapper = connectorMapper;
-        return this;
-    }
-
     public Map<String, String> getCommand() {
         return command;
     }

+ 1 - 4
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/WriterBatchConfig.java

@@ -1,7 +1,5 @@
 package org.dbsyncer.connector.config;
 
-import org.dbsyncer.connector.ConnectorMapper;
-
 import java.util.List;
 import java.util.Map;
 
@@ -12,8 +10,7 @@ public class WriterBatchConfig extends WriterConfig {
      */
     private List<Map> data;
 
-    public WriterBatchConfig(ConnectorMapper connectorMapper, Map<String, String> command, List<Field> fields, List<Map> data) {
-        setConnectorMapper(connectorMapper);
+    public WriterBatchConfig(Map<String, String> command, List<Field> fields, List<Map> data) {
         setCommand(command);
         setFields(fields);
         setData(data);

+ 0 - 15
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/WriterConfig.java

@@ -1,16 +1,10 @@
 package org.dbsyncer.connector.config;
 
-import org.dbsyncer.connector.ConnectorMapper;
-
 import java.util.List;
 import java.util.Map;
 
 public class WriterConfig {
 
-    /**
-     * 连接配置
-     */
-    private ConnectorMapper connectorMapper;
     /**
      * 执行命令
      */
@@ -20,15 +14,6 @@ public class WriterConfig {
      */
     private List<Field> fields;
 
-    public ConnectorMapper getConnectorMapper() {
-        return connectorMapper;
-    }
-
-    public WriterConfig setConnectorMapper(ConnectorMapper connectorMapper) {
-        this.connectorMapper = connectorMapper;
-        return this;
-    }
-
     public Map<String, String> getCommand() {
         return command;
     }

+ 1 - 4
dbsyncer-connector/src/main/java/org/dbsyncer/connector/config/WriterSingleConfig.java

@@ -1,7 +1,5 @@
 package org.dbsyncer.connector.config;
 
-import org.dbsyncer.connector.ConnectorMapper;
-
 import java.util.List;
 import java.util.Map;
 
@@ -27,8 +25,7 @@ public class WriterSingleConfig extends WriterConfig {
      */
     private boolean retry;
 
-    public WriterSingleConfig(ConnectorMapper connectorMapper, List<Field> fields, Map<String, String> command, String event, Map<String, Object> data, String table) {
-        setConnectorMapper(connectorMapper);
+    public WriterSingleConfig(List<Field> fields, Map<String, String> command, String event, Map<String, Object> data, String table) {
         setCommand(command);
         setFields(fields);
         setData(data);

+ 5 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/constant/ConnectorConstant.java

@@ -27,6 +27,11 @@ public class ConnectorConstant {
      */
     public static final String OPERTION_QUERY = "QUERY";
 
+    /**
+     * 查询过滤条件
+     */
+    public static final String OPERTION_QUERY_FILTER = "QUERY_FILTER";
+
     /**
      * 查询总数
      */

+ 98 - 130
dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/AbstractDatabaseConnector.java

@@ -1,8 +1,10 @@
 package org.dbsyncer.connector.database;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.common.model.Result;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.AbstractConnector;
+import org.dbsyncer.connector.Connector;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.ConnectorMapper;
 import org.dbsyncer.connector.config.*;
@@ -21,117 +23,63 @@ import java.sql.PreparedStatement;
 import java.util.*;
 import java.util.stream.Collectors;
 
-public abstract class AbstractDatabaseConnector implements Database {
+public abstract class AbstractDatabaseConnector extends AbstractConnector implements Connector<DatabaseConnectorMapper, DatabaseConfig>, Database {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     protected abstract String getTableSql(DatabaseConfig config);
 
     @Override
-    public ConnectorMapper connect(ConnectorConfig config) {
-        DatabaseConfig cfg = (DatabaseConfig) config;
+    public ConnectorMapper connect(DatabaseConfig config) {
         try {
-            return new ConnectorMapper(config, DatabaseUtil.getConnection(cfg));
+            return new DatabaseConnectorMapper(config, DatabaseUtil.getConnection(config));
         } catch (Exception e) {
-            logger.error("Failed to connect:{}, message:{}", cfg.getUrl(), e.getMessage());
+            logger.error("Failed to connect:{}, message:{}", config.getUrl(), e.getMessage());
         }
-        throw new ConnectorException(String.format("Failed to connect:%s", cfg.getUrl()));
+        throw new ConnectorException(String.format("Failed to connect:%s", config.getUrl()));
     }
 
     @Override
-    public void disconnect(ConnectorMapper connectorMapper) {
+    public void disconnect(DatabaseConnectorMapper connectorMapper) {
         DatabaseUtil.close(connectorMapper.getConnection());
     }
 
     @Override
-    public boolean isAlive(ConnectorMapper connectorMapper) {
-        Integer count = connectorMapper.execute((databaseTemplate) -> databaseTemplate.queryForObject(getValidationQuery(), Integer.class));
+    public boolean isAlive(DatabaseConnectorMapper connectorMapper) {
+        Integer count = connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForObject(getValidationQuery(), Integer.class));
         return null != count && count > 0;
     }
 
     @Override
-    public String getConnectorMapperCacheKey(ConnectorConfig config) {
-        DatabaseConfig cfg = (DatabaseConfig) config;
-        return String.format("%s-%s", cfg.getUrl(), cfg.getUsername());
+    public String getConnectorMapperCacheKey(DatabaseConfig config) {
+        return String.format("%s-%s", config.getUrl(), config.getUsername());
     }
 
     @Override
-    public List<String> getTable(ConnectorMapper connectorMapper) {
-        String sql = getTableSql((DatabaseConfig) connectorMapper.getConfig());
-        return connectorMapper.execute((databaseTemplate) -> databaseTemplate.queryForList(sql, String.class));
+    public List<String> getTable(DatabaseConnectorMapper connectorMapper) {
+        String sql = getTableSql(connectorMapper.getConfig());
+        return connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForList(sql, String.class));
     }
 
     @Override
-    public MetaInfo getMetaInfo(ConnectorMapper connectorMapper, String tableName) {
+    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
         String quotation = buildSqlWithQuotation();
         StringBuilder queryMetaSql = new StringBuilder("SELECT * FROM ").append(quotation).append(tableName).append(quotation).append(" WHERE 1 != 1");
-        return connectorMapper.execute((databaseTemplate) -> DatabaseUtil.getMetaInfo(databaseTemplate, queryMetaSql.toString(), tableName));
+        return connectorMapper.execute(databaseTemplate -> DatabaseUtil.getMetaInfo(databaseTemplate, queryMetaSql.toString(), tableName));
     }
 
     @Override
-    public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
-        // 获取过滤SQL
-        List<Filter> filter = commandConfig.getFilter();
-        String queryFilterSql = getQueryFilterSql(filter);
-
-        // 获取查询SQL
-        Table table = commandConfig.getTable();
-        Map<String, String> map = new HashMap<>();
-
-        String query = ConnectorConstant.OPERTION_QUERY;
-        map.put(query, buildSql(query, table, commandConfig.getOriginalTable(), queryFilterSql));
-
-        // 获取查询总数SQL
-        String quotation = buildSqlWithQuotation();
-        String pk = DatabaseUtil.findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
-        StringBuilder queryCount = new StringBuilder();
-        queryCount.append("SELECT COUNT(1) FROM (SELECT 1 FROM ").append(quotation).append(table.getName()).append(quotation);
-        if (StringUtils.isNotBlank(queryFilterSql)) {
-            queryCount.append(queryFilterSql);
-        }
-        queryCount.append(" GROUP BY ").append(pk).append(") DBSYNCER_T");
-        map.put(ConnectorConstant.OPERTION_QUERY_COUNT, queryCount.toString());
-        return map;
-    }
-
-    @Override
-    public Map<String, String> getTargetCommand(CommandConfig commandConfig) {
-        // 获取增删改SQL
-        Map<String, String> map = new HashMap<>();
-        Table table = commandConfig.getTable();
-        Table originalTable = commandConfig.getOriginalTable();
-
-        String insert = SqlBuilderEnum.INSERT.getName();
-        map.put(insert, buildSql(insert, table, originalTable, null));
-
-        String update = SqlBuilderEnum.UPDATE.getName();
-        map.put(update, buildSql(update, table, originalTable, null));
-
-        String delete = SqlBuilderEnum.DELETE.getName();
-        map.put(delete, buildSql(delete, table, originalTable, null));
-
-        // 获取查询数据行是否存在
-        String quotation = buildSqlWithQuotation();
-        String pk = DatabaseUtil.findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
-        StringBuilder queryCount = new StringBuilder().append("SELECT COUNT(1) FROM ").append(quotation).append(table.getName()).append(
-                quotation).append(" WHERE ").append(pk).append(" = ?");
-        String queryCountExist = ConnectorConstant.OPERTION_QUERY_COUNT_EXIST;
-        map.put(queryCountExist, queryCount.toString());
-        return map;
-    }
-
-    @Override
-    public long getCount(ConnectorMapper config, Map<String, String> command) {
+    public long getCount(DatabaseConnectorMapper connectorMapper, Map<String, String> command) {
         // 1、获取select SQL
         String queryCountSql = command.get(ConnectorConstant.OPERTION_QUERY_COUNT);
         Assert.hasText(queryCountSql, "查询总数语句不能为空.");
 
         // 2、返回结果集
-        return config.execute((databaseTemplate) -> databaseTemplate.queryForObject(queryCountSql, Long.class));
+        return connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForObject(queryCountSql, Long.class));
     }
 
     @Override
-    public Result reader(ReaderConfig config) {
+    public Result reader(DatabaseConnectorMapper connectorMapper, ReaderConfig config) {
         // 1、获取select SQL
         String querySql = config.getCommand().get(SqlBuilderEnum.QUERY.getName());
         Assert.hasText(querySql, "查询语句不能为空.");
@@ -140,15 +88,14 @@ public abstract class AbstractDatabaseConnector implements Database {
         Collections.addAll(config.getArgs(), getPageArgs(config.getPageIndex(), config.getPageSize()));
 
         // 3、执行SQL
-        ConnectorMapper connectorMapper = config.getConnectorMapper();
-        List<Map<String, Object>> list = connectorMapper.execute((databaseTemplate) -> databaseTemplate.queryForList(querySql, config.getArgs().toArray()));
+        List<Map<String, Object>> list = connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForList(querySql, config.getArgs().toArray()));
 
         // 4、返回结果集
         return new Result(new ArrayList<>(list));
     }
 
     @Override
-    public Result writer(WriterBatchConfig config) {
+    public Result writer(DatabaseConnectorMapper connectorMapper, WriterBatchConfig config) {
         List<Field> fields = config.getFields();
         List<Map> data = config.getData();
 
@@ -168,11 +115,8 @@ public abstract class AbstractDatabaseConnector implements Database {
 
         Result result = new Result();
         try {
-            // 2、获取连接
-            ConnectorMapper connectorMapper = config.getConnectorMapper();
-
-            // 3、设置参数
-            connectorMapper.execute((databaseTemplate) -> {
+            // 2、设置参数
+            connectorMapper.execute(databaseTemplate -> {
                 databaseTemplate.batchUpdate(insertSql, new BatchPreparedStatementSetter() {
                     @Override
                     public void setValues(PreparedStatement preparedStatement, int i) {
@@ -197,7 +141,7 @@ public abstract class AbstractDatabaseConnector implements Database {
     }
 
     @Override
-    public Result writer(WriterSingleConfig config) {
+    public Result writer(DatabaseConnectorMapper connectorMapper, WriterSingleConfig config) {
         String event = config.getEvent();
         List<Field> fields = config.getFields();
         Map<String, Object> data = config.getData();
@@ -221,12 +165,10 @@ public abstract class AbstractDatabaseConnector implements Database {
 
         int size = fields.size();
         Result result = new Result();
-        // 2、获取连接
-        ConnectorMapper connectorMapper = config.getConnectorMapper();
         int update = 0;
         try {
-            // 3、设置参数
-            update = connectorMapper.execute((databaseTemplate) ->
+            // 2、设置参数
+            update = connectorMapper.execute(databaseTemplate ->
                     databaseTemplate.update(sql, (ps) -> {
                         Field f = null;
                         for (int i = 0; i < size; i++) {
@@ -254,22 +196,74 @@ public abstract class AbstractDatabaseConnector implements Database {
                 config.setEvent(ConnectorConstant.OPERTION_INSERT);
                 config.setRetry(true);
                 logger.warn("{}表执行{}失败, 尝试执行{}", config.getTable(), event, config.getEvent());
-                result = writer(config);
+                result = writer(connectorMapper, config);
             }
         }
         return result;
     }
 
+    @Override
+    public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
+        // 获取过滤SQL
+        List<Filter> filter = commandConfig.getFilter();
+        String queryFilterSql = getQueryFilterSql(filter);
+
+        // 获取查询SQL
+        Table table = commandConfig.getTable();
+        Map<String, String> map = new HashMap<>();
+
+        String query = ConnectorConstant.OPERTION_QUERY;
+        map.put(query, buildSql(query, table, commandConfig.getOriginalTable(), queryFilterSql));
+
+        // 获取查询总数SQL
+        String quotation = buildSqlWithQuotation();
+        String pk = DatabaseUtil.findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
+        StringBuilder queryCount = new StringBuilder();
+        queryCount.append("SELECT COUNT(1) FROM (SELECT 1 FROM ").append(quotation).append(table.getName()).append(quotation);
+        if (StringUtil.isNotBlank(queryFilterSql)) {
+            queryCount.append(queryFilterSql);
+        }
+        queryCount.append(" GROUP BY ").append(pk).append(") DBSYNCER_T");
+        map.put(ConnectorConstant.OPERTION_QUERY_COUNT, queryCount.toString());
+        return map;
+    }
+
+    @Override
+    public Map<String, String> getTargetCommand(CommandConfig commandConfig) {
+        // 获取增删改SQL
+        Map<String, String> map = new HashMap<>();
+        Table table = commandConfig.getTable();
+        Table originalTable = commandConfig.getOriginalTable();
+
+        String insert = SqlBuilderEnum.INSERT.getName();
+        map.put(insert, buildSql(insert, table, originalTable, null));
+
+        String update = SqlBuilderEnum.UPDATE.getName();
+        map.put(update, buildSql(update, table, originalTable, null));
+
+        String delete = SqlBuilderEnum.DELETE.getName();
+        map.put(delete, buildSql(delete, table, originalTable, null));
+
+        // 获取查询数据行是否存在
+        String quotation = buildSqlWithQuotation();
+        String pk = DatabaseUtil.findTablePrimaryKey(commandConfig.getOriginalTable(), quotation);
+        StringBuilder queryCount = new StringBuilder().append("SELECT COUNT(1) FROM ").append(quotation).append(table.getName()).append(
+                quotation).append(" WHERE ").append(pk).append(" = ?");
+        String queryCountExist = ConnectorConstant.OPERTION_QUERY_COUNT_EXIST;
+        map.put(queryCountExist, queryCount.toString());
+        return map;
+    }
+
     /**
      * 获取DQL表信息
      *
      * @param config
      * @return
      */
-    protected List<String> getDqlTable(ConnectorMapper config) {
+    protected List<String> getDqlTable(DatabaseConnectorMapper config) {
         MetaInfo metaInfo = getDqlMetaInfo(config);
         Assert.notNull(metaInfo, "SQL解析异常.");
-        DatabaseConfig cfg = (DatabaseConfig) config.getConfig();
+        DatabaseConfig cfg = config.getConfig();
         List<String> tables = new ArrayList<>();
         tables.add(cfg.getSql());
         return tables;
@@ -281,11 +275,11 @@ public abstract class AbstractDatabaseConnector implements Database {
      * @param config
      * @return
      */
-    protected MetaInfo getDqlMetaInfo(ConnectorMapper config) {
-        DatabaseConfig cfg = (DatabaseConfig) config.getConfig();
+    protected MetaInfo getDqlMetaInfo(DatabaseConnectorMapper config) {
+        DatabaseConfig cfg = config.getConfig();
         String sql = cfg.getSql().toUpperCase();
-        String queryMetaSql = StringUtils.contains(sql, " WHERE ") ? sql + " AND 1!=1 " : sql + " WHERE 1!=1 ";
-        return config.execute((databaseTemplate) -> DatabaseUtil.getMetaInfo(databaseTemplate, queryMetaSql, cfg.getTable()));
+        String queryMetaSql = StringUtil.contains(sql, " WHERE ") ? sql + " AND 1!=1 " : sql + " WHERE 1!=1 ";
+        return config.execute(databaseTemplate -> DatabaseUtil.getMetaInfo(databaseTemplate, queryMetaSql, cfg.getTable()));
     }
 
     /**
@@ -306,7 +300,7 @@ public abstract class AbstractDatabaseConnector implements Database {
         String querySql = table.getName();
 
         // 存在条件
-        if (StringUtils.isNotBlank(queryFilterSql)) {
+        if (StringUtil.isNotBlank(queryFilterSql)) {
             querySql += queryFilterSql;
         }
         String quotation = buildSqlWithQuotation();
@@ -316,7 +310,7 @@ public abstract class AbstractDatabaseConnector implements Database {
         // 获取查询总数SQL
         StringBuilder queryCount = new StringBuilder();
         queryCount.append("SELECT COUNT(1) FROM (").append(table.getName());
-        if (StringUtils.isNotBlank(queryFilterSql)) {
+        if (StringUtil.isNotBlank(queryFilterSql)) {
             queryCount.append(queryFilterSql);
         }
         // Mysql
@@ -353,20 +347,20 @@ public abstract class AbstractDatabaseConnector implements Database {
         // 拼接并且SQL
         String addSql = getFilterSql(OperationEnum.AND.getName(), filter);
         // 如果Add条件存在
-        if (StringUtils.isNotBlank(addSql)) {
+        if (StringUtil.isNotBlank(addSql)) {
             sql.append(addSql);
         }
 
         // 拼接或者SQL
         String orSql = getFilterSql(OperationEnum.OR.getName(), filter);
         // 如果Or条件和Add条件都存在
-        if (StringUtils.isNotBlank(orSql) && StringUtils.isNotBlank(addSql)) {
+        if (StringUtil.isNotBlank(orSql) && StringUtil.isNotBlank(addSql)) {
             sql.append(" OR ");
         }
         sql.append(orSql);
 
         // 如果有条件加上 WHERE
-        if (StringUtils.isNotBlank(sql.toString())) {
+        if (StringUtil.isNotBlank(sql.toString())) {
             // WHERE (USER.USERNAME = 'zhangsan' AND USER.AGE='20') OR (USER.TEL='18299996666')
             sql.insert(0, " WHERE ");
         }
@@ -397,7 +391,7 @@ public abstract class AbstractDatabaseConnector implements Database {
         List<Field> fields = new ArrayList<>();
         for (Field c : column) {
             String name = c.getName();
-            if (StringUtils.isBlank(name)) {
+            if (StringUtil.isBlank(name)) {
                 throw new ConnectorException("The field name can not be empty.");
             }
             if (c.isPk()) {
@@ -413,11 +407,11 @@ public abstract class AbstractDatabaseConnector implements Database {
             throw new ConnectorException("The fields can not be empty.");
         }
         String tableName = table.getName();
-        if (StringUtils.isBlank(tableName)) {
+        if (StringUtil.isBlank(tableName)) {
             logger.error("Table name can not be empty.");
             throw new ConnectorException("Table name can not be empty.");
         }
-        if (StringUtils.isBlank(pk)) {
+        if (StringUtil.isBlank(pk)) {
             pk = DatabaseUtil.findTablePrimaryKey(originalTable, "");
         }
 
@@ -442,7 +436,7 @@ public abstract class AbstractDatabaseConnector implements Database {
      * @return
      */
     private String getFilterSql(String queryOperator, List<Filter> filter) {
-        List<Filter> list = filter.stream().filter(f -> StringUtils.equals(f.getOperation(), queryOperator)).collect(Collectors.toList());
+        List<Filter> list = filter.stream().filter(f -> StringUtil.equals(f.getOperation(), queryOperator)).collect(Collectors.toList());
         if (CollectionUtils.isEmpty(list)) {
             return "";
         }
@@ -485,40 +479,14 @@ public abstract class AbstractDatabaseConnector implements Database {
         }
     }
 
-    private boolean existRow(ConnectorMapper connectorMapper, String sql, Object value) {
+    private boolean existRow(DatabaseConnectorMapper connectorMapper, String sql, Object value) {
         int rowNum = 0;
         try {
-            rowNum = connectorMapper.execute((databaseTemplate) -> databaseTemplate.queryForObject(sql, new Object[]{value}, Integer.class));
+            rowNum = connectorMapper.execute(databaseTemplate -> databaseTemplate.queryForObject(sql, new Object[] {value}, Integer.class));
         } catch (Exception e) {
             logger.error("检查数据行存在异常:{},SQL:{},参数:{}", e.getMessage(), sql, value);
         }
         return rowNum > 0;
     }
 
-    private Field getPrimaryKeyField(List<Field> fields) {
-        for (Field f : fields) {
-            if (f.isPk()) {
-                return f;
-            }
-        }
-        throw new ConnectorException("主键为空");
-    }
-
-    private boolean isUpdate(String event) {
-        return StringUtils.equals(ConnectorConstant.OPERTION_UPDATE, event);
-    }
-
-    private boolean isDelete(String event) {
-        return StringUtils.equals(ConnectorConstant.OPERTION_DELETE, event);
-    }
-
-    private void close(AutoCloseable closeable) {
-        if (null != closeable) {
-            try {
-                closeable.close();
-            } catch (Exception e) {
-                logger.error(e.getMessage());
-            }
-        }
-    }
 }

+ 1 - 2
dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/Database.java

@@ -1,9 +1,8 @@
 package org.dbsyncer.connector.database;
 
-import org.dbsyncer.connector.Connector;
 import org.dbsyncer.connector.config.PageSqlConfig;
 
-public interface Database extends Connector {
+public interface Database {
 
     /**
      * 获取分页SQL

+ 38 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/DatabaseConnectorMapper.java

@@ -0,0 +1,38 @@
+package org.dbsyncer.connector.database;
+
+import org.dbsyncer.connector.ConnectorException;
+import org.dbsyncer.connector.ConnectorMapper;
+import org.dbsyncer.connector.config.DatabaseConfig;
+import org.springframework.dao.EmptyResultDataAccessException;
+
+import java.sql.Connection;
+
+public class DatabaseConnectorMapper implements ConnectorMapper<DatabaseConfig, Connection> {
+    protected DatabaseConfig config;
+    protected Connection connection;
+
+    public DatabaseConnectorMapper(DatabaseConfig config, Connection connection) {
+        this.config = config;
+        this.connection = connection;
+    }
+
+    public <T> T execute(HandleCallback callback) {
+        try {
+            return (T) callback.apply(new DatabaseTemplate(connection));
+        } catch (EmptyResultDataAccessException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new ConnectorException(e.getMessage());
+        }
+    }
+
+    @Override
+    public DatabaseConfig getConfig() {
+        return config;
+    }
+
+    @Override
+    public Connection getConnection() {
+        return connection;
+    }
+}

+ 6 - 8
dbsyncer-connector/src/main/java/org/dbsyncer/connector/HandleCallback.java → dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/HandleCallback.java

@@ -1,9 +1,7 @@
-package org.dbsyncer.connector;
-
-import org.dbsyncer.connector.database.DatabaseTemplate;
-
-public interface HandleCallback {
-
-    Object apply(DatabaseTemplate databaseTemplate) throws Exception;
-
+package org.dbsyncer.connector.database;
+
+public interface HandleCallback {
+
+    Object apply(DatabaseTemplate databaseTemplate) throws Exception;
+
 }

+ 3 - 3
dbsyncer-connector/src/main/java/org/dbsyncer/connector/database/sqlbuilder/SqlBuilderQuery.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.connector.database.sqlbuilder;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.config.Field;
 import org.dbsyncer.connector.config.PageSqlConfig;
 import org.dbsyncer.connector.config.SqlBuilderConfig;
@@ -43,7 +43,7 @@ public class SqlBuilderQuery extends AbstractSqlBuilder {
             }
 
             // "USERNAME" as "myName"
-            if (StringUtils.isNotEmpty(field.getLabelName())) {
+            if (StringUtil.isNotBlank(field.getLabelName())) {
                 sql.append(" as ").append(quotation).append(field.getLabelName()).append(quotation);
             }
 
@@ -55,7 +55,7 @@ public class SqlBuilderQuery extends AbstractSqlBuilder {
         // SELECT "ID","NAME" FROM "USER"
         sql.insert(0, "SELECT ").append(" FROM ").append(quotation).append(tableName).append(quotation);
         // 解析查询条件
-        if (StringUtils.isNotBlank(queryFilter)) {
+        if (StringUtil.isNotBlank(queryFilter)) {
             sql.append(queryFilter);
         }
         return sql.toString();

+ 9 - 3
dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/ConnectorEnum.java

@@ -1,9 +1,11 @@
 package org.dbsyncer.connector.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.Connector;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.config.DatabaseConfig;
+import org.dbsyncer.connector.config.ESConfig;
+import org.dbsyncer.connector.es.ESConnector;
 import org.dbsyncer.connector.mysql.MysqlConnector;
 import org.dbsyncer.connector.oracle.OracleConnector;
 import org.dbsyncer.connector.sql.DQLMysqlConnector;
@@ -32,6 +34,10 @@ public enum ConnectorEnum {
      * SqlServer 连接器
      */
     SQL_SERVER("SqlServer", new SqlServerConnector(), DatabaseConfig.class),
+    /**
+     * Elasticsearch 连接器
+     */
+    ELASTIC_SEARCH("Elasticsearch", new ESConnector(), ESConfig.class),
     /**
      * DqlMysql 连接器
      */
@@ -69,7 +75,7 @@ public enum ConnectorEnum {
      */
     public static Connector getConnector(String type) throws ConnectorException {
         for (ConnectorEnum e : ConnectorEnum.values()) {
-            if (StringUtils.equals(type, e.getType())) {
+            if (StringUtil.equals(type, e.getType())) {
                 return e.getConnector();
             }
         }
@@ -85,7 +91,7 @@ public enum ConnectorEnum {
      */
     public static Class<?> getConfigClass(String type) throws ConnectorException {
         for (ConnectorEnum e : ConnectorEnum.values()) {
-            if (StringUtils.equals(type, e.getType())) {
+            if (StringUtil.equals(type, e.getType())) {
                 return e.getConfigClass();
             }
         }

+ 100 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/ESFieldTypeEnum.java

@@ -0,0 +1,100 @@
+package org.dbsyncer.connector.enums;
+
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.ConnectorException;
+
+import java.sql.Types;
+
+/**
+ * ES字段类型
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2021/08/26 21:13
+ */
+public enum ESFieldTypeEnum {
+
+    // 字符类型
+    KEYWORD("keyword", Types.VARCHAR),
+    TEXT("text", Types.LONGVARCHAR),
+    /**
+     * ES 5.X之后不再支持string, 由text或keyword取代
+     */
+    @Deprecated
+    STRING("string", Types.VARCHAR),
+
+    // 数字类型
+    /**
+     * 源库中的类型为unsigned int,建议使用long
+     */
+    INTEGER("integer", Types.INTEGER),
+    /**
+     * bit只有一位,建议使用boolean
+     */
+    LONG("long", Types.BIGINT),
+    /**
+     * 源库中的类型为unsigned tinyint 或 unsigned smallint,建议使用integer
+     */
+    SHORT("short", Types.TINYINT),
+    BYTE("byte", Types.BIT),
+    /**
+     * 为保证精度,建议使用text
+     */
+    DOUBLE("double", Types.DOUBLE),
+    FLOAT("float", Types.FLOAT),
+    HALF_FLOAT("half_float", Types.FLOAT),
+    SCALED_FLOAT("scaled_float", Types.FLOAT),
+    BOOLEAN("boolean", Types.BOOLEAN),
+
+    // 日期类型
+    /**
+     * 默认格式:"strict_date_optional_time||epoch_millis"
+     * "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"  “2021/01/01 12:10:30” or “2021-01-01”
+     */
+    DAte("date", Types.DATE),
+
+    // 范围类型
+    INTEGER_RANGE("integer_range", Types.INTEGER),
+    FLOAT_RANGE("float_range", Types.FLOAT),
+    LONG_RANGE("long_range", Types.BIGINT),
+    DOUBLE_RANGE("double_range", Types.DOUBLE),
+    DATE_RANGE("date_range", Types.DATE),
+
+    // 其他类型
+    /**
+     * 弥补object类型不足,格式出现list放object会变为array:"test": [{"a":"b},{}]
+     */
+    NESTED("nested", Types.VARCHAR),
+    OBJECT("object", Types.VARCHAR),
+    IP("ip", Types.VARCHAR),
+    TOKEN_COUNT("token_count", Types.BIGINT),
+    GEO_POINT("geo_point", Types.VARCHAR),
+    GEO_SHAPE("geo_shape", Types.VARCHAR),
+    BINARY("binary", Types.BINARY);
+
+    private String code;
+    private int type;
+
+    ESFieldTypeEnum(String code, int type) {
+        this.code = code;
+        this.type = type;
+    }
+
+    public static int getType(String code) throws ConnectorException {
+        for (ESFieldTypeEnum e : ESFieldTypeEnum.values()) {
+            if (StringUtil.equals(e.getCode(), code)) {
+                return e.getType();
+            }
+        }
+        return Types.VARCHAR;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+}

+ 9 - 9
dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/FilterEnum.java

@@ -1,7 +1,7 @@
 package org.dbsyncer.connector.enums;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.common.util.NumberUtil;
 import org.dbsyncer.connector.CompareFilter;
 import org.dbsyncer.connector.ConnectorException;
 
@@ -17,27 +17,27 @@ public enum FilterEnum {
     /**
      * 等于
      */
-    EQUAL("=", (value, filterValue) -> StringUtils.equals(value, filterValue)),
+    EQUAL("=", (value, filterValue) -> StringUtil.equals(value, filterValue)),
     /**
      * 不等于
      */
-    NOT_EQUAL("!=", (value, filterValue) -> !StringUtils.equals(value, filterValue)),
+    NOT_EQUAL("!=", (value, filterValue) -> !StringUtil.equals(value, filterValue)),
     /**
      * 大于
      */
-    GT(">", (value, filterValue) -> NumberUtils.toInt(value) > NumberUtils.toInt(filterValue)),
+    GT(">", (value, filterValue) -> NumberUtil.toInt(value) > NumberUtil.toInt(filterValue)),
     /**
      * 小于
      */
-    LT("<", (value, filterValue) -> NumberUtils.toInt(value) < NumberUtils.toInt(filterValue)),
+    LT("<", (value, filterValue) -> NumberUtil.toInt(value) < NumberUtil.toInt(filterValue)),
     /**
      * 大于等于
      */
-    GT_AND_EQUAL(">=", (value, filterValue) -> NumberUtils.toInt(value) >= NumberUtils.toInt(filterValue)),
+    GT_AND_EQUAL(">=", (value, filterValue) -> NumberUtil.toInt(value) >= NumberUtil.toInt(filterValue)),
     /**
      * 小于等于
      */
-    LT_AND_EQUAL("<=", (value, filterValue) -> NumberUtils.toInt(value) <= NumberUtils.toInt(filterValue));
+    LT_AND_EQUAL("<=", (value, filterValue) -> NumberUtil.toInt(value) <= NumberUtil.toInt(filterValue));
 
     // 运算符名称
     private String name;
@@ -58,7 +58,7 @@ public enum FilterEnum {
      */
     public static CompareFilter getCompareFilter(String filterName) throws ConnectorException {
         for (FilterEnum e : FilterEnum.values()) {
-            if (StringUtils.equals(filterName, e.getName())) {
+            if (StringUtil.equals(filterName, e.getName())) {
                 return e.getCompareFilter();
             }
         }

+ 8 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/OperationEnum.java

@@ -25,6 +25,14 @@ public enum OperationEnum {
         this.name = name;
     }
 
+    public static boolean isAnd(String name) {
+        return AND.getName().equals(name);
+    }
+
+    public static boolean isOr(String name) {
+        return OR.getName().equals(name);
+    }
+
     public String getName() {
         return name;
     }

+ 8 - 4
dbsyncer-connector/src/main/java/org/dbsyncer/connector/enums/SqlBuilderEnum.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.connector.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.constant.ConnectorConstant;
 import org.dbsyncer.connector.database.sqlbuilder.*;
@@ -30,10 +30,14 @@ public enum SqlBuilderEnum {
      */
     QUERY(ConnectorConstant.OPERTION_QUERY, new SqlBuilderQuery());
 
-    // SQL构造器名称
+    /**
+     * SQL构造器名称
+     */
     private String name;
 
-    // SQL构造器
+    /**
+     * SQL构造器
+     */
     private SqlBuilder sqlBuilder;
 
     SqlBuilderEnum(String name, SqlBuilder sqlBuilder) {
@@ -43,7 +47,7 @@ public enum SqlBuilderEnum {
 
     public static SqlBuilder getSqlBuilder(String name) throws ConnectorException {
         for (SqlBuilderEnum e : SqlBuilderEnum.values()) {
-            if (StringUtils.equals(name, e.getName())) {
+            if (StringUtil.equals(name, e.getName())) {
                 return e.getSqlBuilder();
             }
         }

+ 347 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/es/ESConnector.java

@@ -0,0 +1,347 @@
+package org.dbsyncer.connector.es;
+
+import org.dbsyncer.common.model.Result;
+import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.JsonUtil;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.AbstractConnector;
+import org.dbsyncer.connector.Connector;
+import org.dbsyncer.connector.ConnectorException;
+import org.dbsyncer.connector.ConnectorMapper;
+import org.dbsyncer.connector.config.*;
+import org.dbsyncer.connector.constant.ConnectorConstant;
+import org.dbsyncer.connector.enums.ESFieldTypeEnum;
+import org.dbsyncer.connector.enums.FilterEnum;
+import org.dbsyncer.connector.enums.OperationEnum;
+import org.dbsyncer.connector.util.ESUtil;
+import org.elasticsearch.ElasticsearchStatusException;
+import org.elasticsearch.action.bulk.BulkRequest;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.delete.DeleteRequest;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.GetIndexRequest;
+import org.elasticsearch.client.indices.GetIndexResponse;
+import org.elasticsearch.cluster.metadata.MappingMetaData;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+public final class ESConnector extends AbstractConnector implements Connector<ESConnectorMapper, ESConfig> {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private static Map<String, FilterMapper> map = new ConcurrentHashMap();
+
+    static {
+        map.putIfAbsent(FilterEnum.EQUAL.getName(), (builder, k, v) -> builder.must(QueryBuilders.matchQuery(k, v)));
+        map.putIfAbsent(FilterEnum.NOT_EQUAL.getName(), (builder, k, v) -> builder.mustNot(QueryBuilders.matchQuery(k, v)));
+        map.putIfAbsent(FilterEnum.GT.getName(), (builder, k, v) -> builder.filter(QueryBuilders.rangeQuery(k).gt(v)));
+        map.putIfAbsent(FilterEnum.LT.getName(), (builder, k, v) -> builder.filter(QueryBuilders.rangeQuery(k).lt(v)));
+        map.putIfAbsent(FilterEnum.GT_AND_EQUAL.getName(), (builder, k, v) -> builder.filter(QueryBuilders.rangeQuery(k).gte(v)));
+        map.putIfAbsent(FilterEnum.LT_AND_EQUAL.getName(), (builder, k, v) -> builder.filter(QueryBuilders.rangeQuery(k).lte(v)));
+    }
+
+    @Override
+    public ConnectorMapper connect(ESConfig config) {
+        return new ESConnectorMapper(config, ESUtil.getConnection(config));
+    }
+
+    @Override
+    public void disconnect(ESConnectorMapper connectorMapper) {
+        ESUtil.close(connectorMapper.getConnection());
+    }
+
+    @Override
+    public boolean isAlive(ESConnectorMapper connectorMapper) {
+        try {
+            RestHighLevelClient client = connectorMapper.getConnection();
+            return client.ping(RequestOptions.DEFAULT);
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+            return false;
+        }
+    }
+
+    @Override
+    public String getConnectorMapperCacheKey(ESConfig config) {
+        return String.format("%s-%s-%s-%s", config.getUrl(), config.getIndex(), config.getType(), config.getUsername());
+    }
+
+    @Override
+    public List<String> getTable(ESConnectorMapper connectorMapper) {
+        try {
+            ESConfig config = connectorMapper.getConfig();
+            GetIndexRequest request = new GetIndexRequest(config.getIndex());
+            GetIndexResponse indexResponse = connectorMapper.getConnection().indices().get(request, RequestOptions.DEFAULT);
+            MappingMetaData mappingMetaData = indexResponse.getMappings().get(config.getIndex());
+            List<String> tables = new ArrayList<>();
+            tables.add(mappingMetaData.type());
+            return tables;
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+            throw new ConnectorException(e);
+        }
+    }
+
+    @Override
+    public MetaInfo getMetaInfo(ESConnectorMapper connectorMapper, String tableName) {
+        ESConfig config = connectorMapper.getConfig();
+        List<Field> fields = new ArrayList<>();
+        try {
+            GetIndexRequest request = new GetIndexRequest(config.getIndex());
+            GetIndexResponse indexResponse = connectorMapper.getConnection().indices().get(request, RequestOptions.DEFAULT);
+            MappingMetaData mappingMetaData = indexResponse.getMappings().get(config.getIndex());
+            Map<String, Object> propertiesMap = mappingMetaData.getSourceAsMap();
+            Map<String, Map> properties = (Map<String, Map>) propertiesMap.get(ESUtil.PROPERTIES);
+            if (CollectionUtils.isEmpty(properties)) {
+                throw new ConnectorException("查询字段不能为空.");
+            }
+            properties.forEach((k, v) -> {
+                String columnType = (String) v.get("type");
+                fields.add(new Field(k, columnType, ESFieldTypeEnum.getType(columnType), StringUtil.equals(config.getPrimaryKey(), k)));
+            });
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+            throw new ConnectorException(e);
+        }
+        return new MetaInfo().setColumn(fields);
+    }
+
+    @Override
+    public long getCount(ESConnectorMapper connectorMapper, Map<String, String> command) {
+        try {
+            ESConfig config = connectorMapper.getConfig();
+            SearchSourceBuilder builder = new SearchSourceBuilder();
+            genSearchSourceBuilder(builder, command);
+            builder.trackTotalHits(true);
+            builder.from(0);
+            builder.size(0);
+            SearchRequest request = new SearchRequest(new String[] {config.getIndex()}, builder);
+            SearchResponse response = connectorMapper.getConnection().search(request, RequestOptions.DEFAULT);
+            return response.getHits().getTotalHits();
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+            throw new ConnectorException(e);
+        }
+    }
+
+    @Override
+    public Result reader(ESConnectorMapper connectorMapper, ReaderConfig config) {
+        ESConfig cfg = connectorMapper.getConfig();
+        SearchSourceBuilder builder = new SearchSourceBuilder();
+        genSearchSourceBuilder(builder, config.getCommand());
+        builder.from((config.getPageIndex() - 1) * config.getPageSize());
+        builder.size(config.getPageSize());
+        builder.timeout(TimeValue.timeValueMillis(10));
+
+        try {
+            SearchRequest rq = new SearchRequest(new String[] {cfg.getIndex()}, builder);
+            SearchResponse searchResponse = connectorMapper.getConnection().search(rq, RequestOptions.DEFAULT);
+            SearchHits hits = searchResponse.getHits();
+            SearchHit[] searchHits = hits.getHits();
+            List<Map<String, Object>> list = new ArrayList<>();
+            for (SearchHit hit : searchHits) {
+                list.add(hit.getSourceAsMap());
+            }
+            return new Result(new ArrayList<>(list));
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+            throw new ConnectorException(e.getMessage());
+        }
+    }
+
+    @Override
+    public Result writer(ESConnectorMapper connectorMapper, WriterBatchConfig config) {
+        List<Map> data = config.getData();
+        if (CollectionUtils.isEmpty(data) || CollectionUtils.isEmpty(config.getFields())) {
+            logger.error("writer data can not be empty.");
+            throw new ConnectorException("writer data can not be empty.");
+        }
+
+        Result result = new Result();
+        final ESConfig cfg = connectorMapper.getConfig();
+        Field pkField = getPrimaryKeyField(config.getFields());
+        try {
+            BulkRequest request = new BulkRequest();
+            data.forEach(row -> {
+                IndexRequest r = new IndexRequest(cfg.getIndex(), cfg.getType(), String.valueOf(row.get(pkField.getName())));
+                r.source(row, XContentType.JSON);
+                request.add(r);
+            });
+
+            BulkResponse response = connectorMapper.getConnection().bulk(request, RequestOptions.DEFAULT);
+            RestStatus restStatus = response.status();
+            if (restStatus.getStatus() != RestStatus.OK.getStatus()) {
+                throw new ConnectorException(String.format("error code:%s", restStatus.getStatus()));
+            }
+        } catch (IOException e) {
+            // 记录错误数据
+            result.getFailData().addAll(data);
+            result.getFail().set(data.size());
+            result.getError().append(e.getMessage()).append(System.lineSeparator());
+            logger.error(e.getMessage());
+        }
+        return result;
+    }
+
+    @Override
+    public Result writer(ESConnectorMapper connectorMapper, WriterSingleConfig config) {
+        Map<String, Object> data = config.getData();
+        Field pkField = getPrimaryKeyField(config.getFields());
+        String pk = String.valueOf(data.get(pkField.getName()));
+
+        if (isUpdate(config.getEvent())) {
+            return execute(connectorMapper, data, pk, (index, type, id) -> {
+                try {
+                    UpdateRequest request = new UpdateRequest(index, type, id);
+                    request.doc(data, XContentType.JSON);
+                    connectorMapper.getConnection().update(request, RequestOptions.DEFAULT);
+                } catch (ElasticsearchStatusException e) {
+                    // 数据不存在则写入
+                    if (RestStatus.NOT_FOUND.getStatus() == e.status().getStatus()) {
+                        IndexRequest r = new IndexRequest(index, type, id);
+                        r.source(data, XContentType.JSON);
+                        connectorMapper.getConnection().index(r, RequestOptions.DEFAULT);
+                        return;
+                    }
+                    throw new ConnectorException(e.getMessage());
+                }
+            });
+        }
+        if (isInsert(config.getEvent())) {
+            return execute(connectorMapper, data, pk, (index, type, id) -> {
+                IndexRequest request = new IndexRequest(index, type, id);
+                request.source(data, XContentType.JSON);
+                connectorMapper.getConnection().index(request, RequestOptions.DEFAULT);
+            });
+        }
+        if (isDelete(config.getEvent())) {
+            return execute(connectorMapper, data, pk, (index, type, id) ->
+                    connectorMapper.getConnection().delete(new DeleteRequest(index, type, id), RequestOptions.DEFAULT)
+            );
+        }
+
+        throw new ConnectorException(String.format("Unsupported event: %s", config.getEvent()));
+    }
+
+    @Override
+    public Map<String, String> getSourceCommand(CommandConfig commandConfig) {
+        Map<String, String> command = new HashMap<>();
+        // 查询字段
+        Table table = commandConfig.getTable();
+        List<Field> column = table.getColumn();
+        if (!CollectionUtils.isEmpty(column)) {
+            List<String> fieldNames = column.stream().map(c -> c.getName()).collect(Collectors.toList());
+            command.put(ConnectorConstant.OPERTION_QUERY, StringUtil.join(fieldNames, ","));
+        }
+
+        // 过滤条件
+        List<Filter> filter = commandConfig.getFilter();
+        if (!CollectionUtils.isEmpty(filter)) {
+            command.put(ConnectorConstant.OPERTION_QUERY_FILTER, JsonUtil.objToJson(filter));
+        }
+        return command;
+    }
+
+    private void genSearchSourceBuilder(SearchSourceBuilder builder, Map<String, String> command) {
+        // 查询字段
+        String fieldNamesJson = command.get(ConnectorConstant.OPERTION_QUERY);
+        if (!StringUtil.isBlank(fieldNamesJson)) {
+            builder.fetchSource(StringUtil.split(fieldNamesJson, ","), null);
+        }
+
+        // 过滤条件
+        String filterJson = command.get(ConnectorConstant.OPERTION_QUERY_FILTER);
+        List<Filter> filters = null;
+        if (!StringUtil.isBlank(filterJson)) {
+            filters = JsonUtil.jsonToArray(filterJson, Filter.class);
+        }
+        if (CollectionUtils.isEmpty(filters)) {
+            builder.query(QueryBuilders.matchAllQuery());
+            return;
+        }
+
+        List<Filter> and = filters.stream().filter(f -> OperationEnum.isAnd(f.getOperation())).collect(Collectors.toList());
+        List<Filter> or = filters.stream().filter(f -> OperationEnum.isOr(f.getOperation())).collect(Collectors.toList());
+        // where (id = 1 and name = 'tom') or id = 2 or id = 3
+        BoolQueryBuilder q = QueryBuilders.boolQuery();
+        if (!CollectionUtils.isEmpty(and) && !CollectionUtils.isEmpty(or)) {
+            BoolQueryBuilder andQuery = QueryBuilders.boolQuery();
+            and.forEach(f -> addFilter(andQuery, f));
+            q.should(andQuery);
+            genShouldQuery(q, or);
+            builder.query(q);
+            return;
+        }
+
+        if (!CollectionUtils.isEmpty(or)) {
+            genShouldQuery(q, or);
+            builder.query(q);
+            return;
+        }
+
+        and.forEach(f -> addFilter(q, f));
+        builder.query(q);
+    }
+
+    private void genShouldQuery(BoolQueryBuilder q, List<Filter> or) {
+        or.forEach(f -> {
+            BoolQueryBuilder orQuery = QueryBuilders.boolQuery();
+            addFilter(orQuery, f);
+            q.should(orQuery);
+        });
+    }
+
+    private void addFilter(BoolQueryBuilder builder, Filter f) {
+        if (map.containsKey(f.getFilter())) {
+            map.get(f.getFilter()).apply(builder, f.getName(), f.getValue());
+        }
+    }
+
+    private Result execute(ESConnectorMapper connectorMapper, Map<String, Object> data, String id, RequestMapper mapper) {
+        Result result = new Result();
+        final ESConfig config = connectorMapper.getConfig();
+        try {
+            mapper.apply(config.getIndex(), config.getType(), id);
+        } catch (Exception e) {
+            // 记录错误数据
+            result.getFailData().add(data);
+            result.getFail().set(1);
+            result.getError().append("INDEX:").append(config.getIndex()).append(System.lineSeparator())
+                    .append("TYPE:").append(config.getType()).append(System.lineSeparator())
+                    .append("ID:").append(id).append(System.lineSeparator())
+                    .append("DATA:").append(data).append(System.lineSeparator())
+                    .append("ERROR:").append(e.getMessage()).append(System.lineSeparator());
+            logger.error("INDEX:{}, TYPE:{}, ID:{}, DATA:{}, ERROR:{}", config.getIndex(), config.getType(), id, data, e.getMessage());
+        }
+        return result;
+    }
+
+    private interface RequestMapper {
+        void apply(String index, String type, String id) throws IOException;
+    }
+
+    private interface FilterMapper {
+        void apply(BoolQueryBuilder builder, String key, String value);
+    }
+}

+ 25 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/es/ESConnectorMapper.java

@@ -0,0 +1,25 @@
+package org.dbsyncer.connector.es;
+
+import org.dbsyncer.connector.ConnectorMapper;
+import org.dbsyncer.connector.config.ESConfig;
+import org.elasticsearch.client.RestHighLevelClient;
+
+public final class ESConnectorMapper implements ConnectorMapper<ESConfig, RestHighLevelClient> {
+    private ESConfig config;
+    private RestHighLevelClient client;
+
+    public ESConnectorMapper(ESConfig config, RestHighLevelClient client) {
+        this.config = config;
+        this.client = client;
+    }
+
+    @Override
+    public ESConfig getConfig() {
+        return config;
+    }
+
+    @Override
+    public RestHighLevelClient getConnection() {
+        return client;
+    }
+}

+ 7 - 4
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLMysqlConnector.java

@@ -1,9 +1,12 @@
 package org.dbsyncer.connector.sql;
 
-import org.dbsyncer.connector.ConnectorMapper;
-import org.dbsyncer.connector.config.*;
+import org.dbsyncer.connector.config.CommandConfig;
+import org.dbsyncer.connector.config.DatabaseConfig;
+import org.dbsyncer.connector.config.MetaInfo;
+import org.dbsyncer.connector.config.PageSqlConfig;
 import org.dbsyncer.connector.constant.DatabaseConstant;
 import org.dbsyncer.connector.database.AbstractDatabaseConnector;
+import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 
 import java.util.List;
 import java.util.Map;
@@ -26,12 +29,12 @@ public final class DQLMysqlConnector extends AbstractDatabaseConnector {
     }
 
     @Override
-    public List<String> getTable(ConnectorMapper config) {
+    public List<String> getTable(DatabaseConnectorMapper config) {
         return super.getDqlTable(config);
     }
 
     @Override
-    public MetaInfo getMetaInfo(ConnectorMapper connectorMapper, String tableName) {
+    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
         return super.getDqlMetaInfo(connectorMapper);
     }
 

+ 3 - 3
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLOracleConnector.java

@@ -1,9 +1,9 @@
 package org.dbsyncer.connector.sql;
 
-import org.dbsyncer.connector.ConnectorMapper;
 import org.dbsyncer.connector.config.*;
 import org.dbsyncer.connector.constant.DatabaseConstant;
 import org.dbsyncer.connector.database.AbstractDatabaseConnector;
+import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 
 import java.util.List;
 import java.util.Map;
@@ -26,12 +26,12 @@ public final class DQLOracleConnector extends AbstractDatabaseConnector {
     }
 
     @Override
-    public List<String> getTable(ConnectorMapper config) {
+    public List<String> getTable(DatabaseConnectorMapper config) {
         return super.getDqlTable(config);
     }
 
     @Override
-    public MetaInfo getMetaInfo(ConnectorMapper connectorMapper, String tableName) {
+    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
         return super.getDqlMetaInfo(connectorMapper);
     }
 

+ 7 - 6
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sql/DQLSqlServerConnector.java

@@ -1,11 +1,12 @@
 package org.dbsyncer.connector.sql;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.ConnectorMapper;
 import org.dbsyncer.connector.config.*;
 import org.dbsyncer.connector.constant.DatabaseConstant;
 import org.dbsyncer.connector.database.AbstractDatabaseConnector;
+import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 import org.dbsyncer.connector.sqlserver.SqlServerConnectorMapper;
 import org.dbsyncer.connector.util.DatabaseUtil;
 import org.slf4j.Logger;
@@ -19,9 +20,9 @@ public final class DQLSqlServerConnector extends AbstractDatabaseConnector {
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     @Override
-    public ConnectorMapper connect(ConnectorConfig config) {
+    public ConnectorMapper connect(DatabaseConfig config) {
         try {
-            return new SqlServerConnectorMapper(config, DatabaseUtil.getConnection((DatabaseConfig) config));
+            return new SqlServerConnectorMapper(config, DatabaseUtil.getConnection(config));
         } catch (Exception e) {
             logger.error(e.getMessage());
             throw new ConnectorException(e.getMessage());
@@ -35,7 +36,7 @@ public final class DQLSqlServerConnector extends AbstractDatabaseConnector {
 
     @Override
     public String getPageSql(PageSqlConfig config) {
-        if (StringUtils.isBlank(config.getPk())) {
+        if (StringUtil.isBlank(config.getPk())) {
             logger.error("Table primary key can not be empty.");
             throw new ConnectorException("Table primary key can not be empty.");
         }
@@ -48,12 +49,12 @@ public final class DQLSqlServerConnector extends AbstractDatabaseConnector {
     }
 
     @Override
-    public List<String> getTable(ConnectorMapper config) {
+    public List<String> getTable(DatabaseConnectorMapper config) {
         return super.getDqlTable(config);
     }
 
     @Override
-    public MetaInfo getMetaInfo(ConnectorMapper connectorMapper, String tableName) {
+    public MetaInfo getMetaInfo(DatabaseConnectorMapper connectorMapper, String tableName) {
         return super.getDqlMetaInfo(connectorMapper);
     }
 

+ 5 - 5
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sqlserver/SqlServerConnector.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.connector.sqlserver;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.ConnectorMapper;
 import org.dbsyncer.connector.config.*;
@@ -19,9 +19,9 @@ public final class SqlServerConnector extends AbstractDatabaseConnector implemen
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     @Override
-    public ConnectorMapper connect(ConnectorConfig config) {
+    public ConnectorMapper connect(DatabaseConfig config) {
         try {
-            return new SqlServerConnectorMapper(config, DatabaseUtil.getConnection((DatabaseConfig) config));
+            return new SqlServerConnectorMapper(config, DatabaseUtil.getConnection(config));
         } catch (Exception e) {
             logger.error(e.getMessage());
             throw new ConnectorException(e.getMessage());
@@ -35,7 +35,7 @@ public final class SqlServerConnector extends AbstractDatabaseConnector implemen
 
     @Override
     public String getPageSql(PageSqlConfig config) {
-        if (StringUtils.isBlank(config.getPk())) {
+        if (StringUtil.isBlank(config.getPk())) {
             logger.error("Table primary key can not be empty.");
             throw new ConnectorException("Table primary key can not be empty.");
         }
@@ -61,7 +61,7 @@ public final class SqlServerConnector extends AbstractDatabaseConnector implemen
 
         // 获取查询总数SQL
         StringBuilder queryCount = new StringBuilder();
-        if (StringUtils.isNotBlank(queryFilterSql)) {
+        if (StringUtil.isNotBlank(queryFilterSql)) {
             queryCount.append("SELECT COUNT(*) FROM ").append(table.getName()).append(queryFilterSql);
         } else {
             // 从存储过程查询(定时更新总数,可能存在误差)

+ 6 - 6
dbsyncer-connector/src/main/java/org/dbsyncer/connector/sqlserver/SqlServerConnectorMapper.java

@@ -1,9 +1,9 @@
 package org.dbsyncer.connector.sqlserver;
 
 import org.dbsyncer.connector.ConnectorException;
-import org.dbsyncer.connector.ConnectorMapper;
-import org.dbsyncer.connector.HandleCallback;
-import org.dbsyncer.connector.config.ConnectorConfig;
+import org.dbsyncer.connector.config.DatabaseConfig;
+import org.dbsyncer.connector.database.DatabaseConnectorMapper;
+import org.dbsyncer.connector.database.HandleCallback;
 import org.dbsyncer.connector.database.DatabaseTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -14,12 +14,12 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-public final class SqlServerConnectorMapper extends ConnectorMapper {
+public final class SqlServerConnectorMapper extends DatabaseConnectorMapper {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
     private final Lock   lock   = new ReentrantLock(true);
 
-    public SqlServerConnectorMapper(ConnectorConfig config, Connection connection) {
+    public SqlServerConnectorMapper(DatabaseConfig config, Connection connection) {
         super(config, connection);
     }
 
@@ -29,7 +29,6 @@ public final class SqlServerConnectorMapper extends ConnectorMapper {
      * @param callback
      * @return
      */
-    @Override
     public <T> T execute(HandleCallback callback) {
         final Lock connectionLock = lock;
         boolean locked = false;
@@ -51,4 +50,5 @@ public final class SqlServerConnectorMapper extends ConnectorMapper {
         }
         return (T) apply;
     }
+
 }

+ 3 - 7
dbsyncer-connector/src/main/java/org/dbsyncer/connector/util/DatabaseUtil.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.connector.util;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.connector.config.DatabaseConfig;
@@ -23,11 +23,7 @@ public abstract class DatabaseUtil {
     private DatabaseUtil() {
     }
 
-    public static Connection getConnection(DatabaseConfig config)
-            throws SQLException, ClassNotFoundException {
-        if (null != config.getDriverClassName()) {
-            Class.forName(config.getDriverClassName());
-        }
+    public static Connection getConnection(DatabaseConfig config) throws SQLException {
         return DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
     }
 
@@ -70,7 +66,7 @@ public abstract class DatabaseUtil {
             int columnType;
             boolean pk;
             for (int i = 1; i <= columnCount; i++) {
-                table = StringUtils.isNotBlank(tableName) ? tableName : metaData.getTableName(i);
+                table = StringUtil.isNotBlank(tableName) ? tableName : metaData.getTableName(i);
                 if (null == tables.get(table)) {
                     tables.putIfAbsent(table, findTablePrimaryKeys(md, table));
                 }

+ 67 - 0
dbsyncer-connector/src/main/java/org/dbsyncer/connector/util/ESUtil.java

@@ -0,0 +1,67 @@
+package org.dbsyncer.connector.util;
+
+import org.dbsyncer.common.util.StringUtil;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.dbsyncer.connector.ConnectorException;
+import org.dbsyncer.connector.config.ESConfig;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.elasticsearch.client.RestHighLevelClient;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Objects;
+
+public abstract class ESUtil {
+
+    public static final String PROPERTIES = "properties";
+    private static final int ADDRESS_LENGTH = 2;
+
+    private ESUtil() {
+    }
+
+    public static RestHighLevelClient getConnection(ESConfig config) {
+        String[] ipAddress = StringUtil.split(config.getUrl(), ",");
+        HttpHost[] hosts = Arrays.stream(ipAddress).map(node -> makeHttpHost(node, config.getSchema())).filter(Objects::nonNull).toArray(
+                HttpHost[]::new);
+        RestClientBuilder builder = RestClient.builder(hosts);
+        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+        Credentials credentials = new UsernamePasswordCredentials(config.getUsername(), config.getPassword());
+        credentialsProvider.setCredentials(AuthScope.ANY, credentials);
+        builder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
+        return new RestHighLevelClient(builder);
+    }
+
+    public static void close(RestHighLevelClient client) {
+        if (null != client) {
+            try {
+                client.close();
+            } catch (IOException e) {
+                throw new ConnectorException(e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * 根据配置创建HttpHost
+     *
+     * @param address
+     * @param scheme
+     * @return
+     */
+    private static HttpHost makeHttpHost(String address, String scheme) {
+        String[] arr = address.split(":");
+        if (arr.length == ADDRESS_LENGTH) {
+            String ip = arr[0];
+            int port = Integer.parseInt(arr[1]);
+            return new HttpHost(ip, port, scheme);
+        } else {
+            return null;
+        }
+    }
+}

+ 1 - 1
dbsyncer-listener/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-listener</artifactId>

+ 1 - 1
dbsyncer-listener/src/main/java/org/dbsyncer/listener/Listener.java

@@ -2,6 +2,6 @@ package org.dbsyncer.listener;
 
 public interface Listener {
 
-    <T> T getExtractor(String type, Class<T> valueType) throws IllegalAccessException, InstantiationException;
+    <T> T getExtractor(String groupType, String listenerType, Class<T> valueType) throws IllegalAccessException, InstantiationException;
 
 }

+ 2 - 2
dbsyncer-listener/src/main/java/org/dbsyncer/listener/ListenerFactory.java

@@ -7,8 +7,8 @@ import org.springframework.stereotype.Component;
 public class ListenerFactory implements Listener {
 
     @Override
-    public <T> T getExtractor(String type, Class<T> valueType) throws IllegalAccessException, InstantiationException {
-        Class<T> clazz = (Class<T>) ListenerEnum.getExtractor(type);
+    public <T> T getExtractor(String groupType, String listenerType, Class<T> valueType) throws IllegalAccessException, InstantiationException {
+        Class<T> clazz = (Class<T>) ListenerEnum.getExtractor(groupType + listenerType);
         return clazz.newInstance();
     }
 

+ 27 - 12
dbsyncer-listener/src/main/java/org/dbsyncer/listener/enums/ListenerEnum.java

@@ -1,14 +1,17 @@
 package org.dbsyncer.listener.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.enums.ConnectorEnum;
-import org.dbsyncer.listener.oracle.OracleExtractor;
-import org.dbsyncer.listener.quartz.QuartzExtractor;
 import org.dbsyncer.listener.ListenerException;
 import org.dbsyncer.listener.mysql.MysqlExtractor;
+import org.dbsyncer.listener.oracle.OracleExtractor;
+import org.dbsyncer.listener.quartz.DatabaseQuartzExtractor;
+import org.dbsyncer.listener.quartz.ESQuartzExtractor;
 import org.dbsyncer.listener.sqlserver.SqlServerExtractor;
 
 /**
+ * 监听器Extractor支持日志和定时模式
+ *
  * @author AE86
  * @version 1.0.0
  * @date 2020/04/24 14:19
@@ -16,21 +19,33 @@ import org.dbsyncer.listener.sqlserver.SqlServerExtractor;
 public enum ListenerEnum {
 
     /**
-     * 定时
+     * log_Mysql
+     */
+    LOG_MYSQL(ListenerTypeEnum.LOG.getType() + ConnectorEnum.MYSQL.getType(), MysqlExtractor.class),
+    /**
+     * log_Oracle
+     */
+    LOG_ORACLE(ListenerTypeEnum.LOG.getType() + ConnectorEnum.ORACLE.getType(), OracleExtractor.class),
+    /**
+     * log_SqlServer
+     */
+    LOG_SQL_SERVER(ListenerTypeEnum.LOG.getType() + ConnectorEnum.SQL_SERVER.getType(), SqlServerExtractor.class),
+    /**
+     * timing_Mysql
      */
-    DEFAULT(ListenerTypeEnum.TIMING.getType(), QuartzExtractor.class),
+    TIMING_MYSQL(ListenerTypeEnum.TIMING.getType() + ConnectorEnum.MYSQL.getType(), DatabaseQuartzExtractor.class),
     /**
-     * Mysql
+     * timing_Mysql
      */
-    MYSQL(ConnectorEnum.MYSQL.getType(), MysqlExtractor.class),
+    TIMING_ORACLE(ListenerTypeEnum.TIMING.getType() + ConnectorEnum.ORACLE.getType(), DatabaseQuartzExtractor.class),
     /**
-     * Oracle
+     * timing_SqlServer
      */
-    ORACLE(ConnectorEnum.ORACLE.getType(), OracleExtractor.class),
+    TIMING_SQL_SERVER(ListenerTypeEnum.TIMING.getType() + ConnectorEnum.SQL_SERVER.getType(), DatabaseQuartzExtractor.class),
     /**
-     * SqlServer
+     * timing_Elasticsearch
      */
-    SQL_SERVER(ConnectorEnum.SQL_SERVER.getType(), SqlServerExtractor.class);
+    TIMING_ELASTIC_SEARCH(ListenerTypeEnum.TIMING.getType() + ConnectorEnum.ELASTIC_SEARCH.getType(), ESQuartzExtractor.class);
 
     private String type;
     private Class<?> clazz;
@@ -49,7 +64,7 @@ public enum ListenerEnum {
      */
     public static Class<?> getExtractor(String type) throws ListenerException {
         for (ListenerEnum e : ListenerEnum.values()) {
-            if (StringUtils.equals(type, e.getType())) {
+            if (StringUtil.equals(type, e.getType())) {
                 return e.getClazz();
             }
         }

+ 3 - 3
dbsyncer-listener/src/main/java/org/dbsyncer/listener/enums/ListenerTypeEnum.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.listener.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 
 /**
  * @author AE86
@@ -25,11 +25,11 @@ public enum ListenerTypeEnum {
     }
 
     public static boolean isTiming(String type) {
-        return StringUtils.equals(TIMING.getType(), type);
+        return StringUtil.equals(TIMING.getType(), type);
     }
 
     public static boolean isLog(String type) {
-        return StringUtils.equals(LOG.getType(), type);
+        return StringUtil.equals(LOG.getType(), type);
     }
 
     public String getType() {

+ 25 - 62
dbsyncer-listener/src/main/java/org/dbsyncer/listener/enums/QuartzFilterEnum.java

@@ -1,11 +1,9 @@
 package org.dbsyncer.listener.enums;
 
-import org.dbsyncer.common.util.DateFormatUtil;
-import org.dbsyncer.listener.QuartzFilter;
-
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.util.Date;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.listener.quartz.QuartzFilter;
+import org.dbsyncer.listener.quartz.filter.DateFilter;
+import org.dbsyncer.listener.quartz.filter.TimestampFilter;
 
 /**
  * @author AE86
@@ -17,67 +15,19 @@ public enum QuartzFilterEnum {
     /**
      * 时间戳(开始)
      */
-    TIME_STAMP_BEGIN("$timestamp_begin$", "系统时间戳(开始)", new QuartzFilter() {
-        @Override
-        public Object getObject() {
-            return new Timestamp(Instant.now().toEpochMilli());
-        }
-
-        @Override
-        public Object getObject(String s) {
-            return new Timestamp(Long.parseLong(s));
-        }
-
-        @Override
-        public String toString(Object value) {
-            Timestamp ts = (Timestamp) value;
-            return String.valueOf(ts.getTime());
-        }
-    }),
+    TIME_STAMP_BEGIN("$timestamp_begin$", "系统时间戳(开始)", new TimestampFilter(true)),
     /**
      * 时间戳(结束)
      */
-    TIME_STAMP_END("$timestamp_end$", "系统时间戳(结束)", new QuartzFilter() {
-        @Override
-        public Object getObject() {
-            return new Timestamp(Instant.now().toEpochMilli());
-        }
-
-        @Override
-        public Object getObject(String s) {
-            return new Timestamp(Long.parseLong(s));
-        }
-
-        @Override
-        public String toString(Object value) {
-            Timestamp ts = (Timestamp) value;
-            return String.valueOf(ts.getTime());
-        }
-
-        @Override
-        public boolean begin() {
-            return false;
-        }
-    }),
+    TIME_STAMP_END("$timestamp_end$", "系统时间戳(结束)", new TimestampFilter(false)),
     /**
-     * 日期
+     * 日期(开始)
      */
-    DATE_BEGIN("$date$", "系统日期", new QuartzFilter() {
-        @Override
-        public Object getObject() {
-            return new Date();
-        }
-
-        @Override
-        public Object getObject(String s) {
-            return DateFormatUtil.stringToDate(s);
-        }
-
-        @Override
-        public String toString(Object value) {
-            return DateFormatUtil.dateToString((Date) value);
-        }
-    });
+    DATE_BEGIN("$date_begin$", "系统日期(开始)", new DateFilter(true)),
+    /**
+     * 日期(结束)
+     */
+    DATE_END("$date_end$", "系统日期(结束)", new DateFilter(false));
 
     private String type;
     private String message;
@@ -89,6 +39,19 @@ public enum QuartzFilterEnum {
         this.quartzFilter = quartzFilter;
     }
 
+    /**
+     * @param type
+     * @return
+     */
+    public static QuartzFilterEnum getQuartzFilterEnum(String type) {
+        for (QuartzFilterEnum e : QuartzFilterEnum.values()) {
+            if (StringUtil.equals(type, e.getType())) {
+                return e;
+            }
+        }
+        return null;
+    }
+
     public String getType() {
         return type;
     }

+ 16 - 16
dbsyncer-listener/src/main/java/org/dbsyncer/listener/mysql/MysqlExtractor.java

@@ -2,8 +2,8 @@ package org.dbsyncer.listener.mysql;
 
 import com.github.shyiko.mysql.binlog.event.*;
 import com.github.shyiko.mysql.binlog.network.ServerException;
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.common.event.RowChangedEvent;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.config.DatabaseConfig;
 import org.dbsyncer.connector.constant.ConnectorConstant;
 import org.dbsyncer.listener.AbstractExtractor;
@@ -46,7 +46,7 @@ public class MysqlExtractor extends AbstractExtractor {
     public void start() {
         try {
             connectLock.lock();
-            if(connected){
+            if (connected) {
                 logger.error("MysqlExtractor is already started");
                 return;
             }
@@ -86,7 +86,7 @@ public class MysqlExtractor extends AbstractExtractor {
         final String pos = snapshot.get(BINLOG_POSITION);
         client = new BinaryLogRemoteClient(host.getIp(), host.getPort(), username, password);
         client.setBinlogFilename(snapshot.get(BINLOG_FILENAME));
-        client.setBinlogPosition(StringUtils.isBlank(pos) ? 0 : Long.parseLong(pos));
+        client.setBinlogPosition(StringUtil.isBlank(pos) ? 0 : Long.parseLong(pos));
         client.setTableMapEventByTableId(tables);
         client.registerEventListener(new MysqlEventListener());
         client.registerLifecycleListener(new MysqlLifecycleListener());
@@ -95,7 +95,7 @@ public class MysqlExtractor extends AbstractExtractor {
     }
 
     private List<Host> readNodes(String url) {
-        if (StringUtils.isBlank(url)) {
+        if (StringUtil.isBlank(url)) {
             return Collections.EMPTY_LIST;
         }
         Matcher matcher = compile("(//)(?!(/)).+?(/)").matcher(url);
@@ -103,13 +103,13 @@ public class MysqlExtractor extends AbstractExtractor {
             url = matcher.group(0);
             break;
         }
-        url = StringUtils.replace(url, "/", "");
+        url = StringUtil.replace(url, "/", "");
 
         List<Host> cluster = new ArrayList<>();
-        String[] arr = StringUtils.split(url, ",");
+        String[] arr = StringUtil.split(url, ",");
         int size = arr.length;
         for (int i = 0; i < size; i++) {
-            String[] host = StringUtils.split(arr[i], ":");
+            String[] host = StringUtil.split(arr[i], ":");
             if (2 == host.length) {
                 cluster.add(new Host(host[0], Integer.parseInt(host[1])));
             }
@@ -149,7 +149,7 @@ public class MysqlExtractor extends AbstractExtractor {
     }
 
     private void refresh(String binlogFilename, long nextPosition) {
-        if (StringUtils.isNotBlank(binlogFilename)) {
+        if (StringUtil.isNotBlank(binlogFilename)) {
             client.setBinlogFilename(binlogFilename);
             snapshot.put(BINLOG_FILENAME, binlogFilename);
         }
@@ -169,7 +169,7 @@ public class MysqlExtractor extends AbstractExtractor {
 
         @Override
         public void onCommunicationFailure(BinaryLogRemoteClient client, Exception e) {
-            if(!connected){
+            if (!connected) {
                 return;
             }
             logger.error(e.getMessage());
@@ -179,9 +179,9 @@ public class MysqlExtractor extends AbstractExtractor {
              * case2> Got fatal error 1236 from master when reading data from binary log.
              * case3> Log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master.
              */
-            if(e instanceof ServerException){
+            if (e instanceof ServerException) {
                 ServerException serverException = (ServerException) e;
-                if(serverException.getErrorCode() == 1236){
+                if (serverException.getErrorCode() == 1236) {
                     close();
                     String log = String.format("线程[%s]执行异常。由于MySQL配置了过期binlog文件自动删除机制,已无法找到原binlog文件%s。建议先保存驱动(加载最新的binlog文件),再启动驱动。",
                             client.getWorkerThreadName(),
@@ -218,7 +218,7 @@ public class MysqlExtractor extends AbstractExtractor {
             if (EventType.isUpdate(header.getEventType())) {
                 UpdateRowsEventData data = event.getData();
                 String tableName = getTableName(data.getTableId());
-                if(isFilterTable(tableName, ConnectorConstant.OPERTION_UPDATE)){
+                if (isFilterTable(tableName, ConnectorConstant.OPERTION_UPDATE)) {
                     data.getRows().forEach(m -> {
                         List<Object> before = Stream.of(m.getKey()).collect(Collectors.toList());
                         List<Object> after = Stream.of(m.getValue()).collect(Collectors.toList());
@@ -231,7 +231,7 @@ public class MysqlExtractor extends AbstractExtractor {
             if (EventType.isWrite(header.getEventType())) {
                 WriteRowsEventData data = event.getData();
                 String tableName = getTableName(data.getTableId());
-                if(isFilterTable(tableName, ConnectorConstant.OPERTION_INSERT)){
+                if (isFilterTable(tableName, ConnectorConstant.OPERTION_INSERT)) {
                     data.getRows().forEach(m -> {
                         List<Object> after = Stream.of(m).collect(Collectors.toList());
                         asynSendRowChangedEvent(new RowChangedEvent(tableName, ConnectorConstant.OPERTION_INSERT, Collections.EMPTY_LIST, after));
@@ -243,7 +243,7 @@ public class MysqlExtractor extends AbstractExtractor {
             if (EventType.isDelete(header.getEventType())) {
                 DeleteRowsEventData data = event.getData();
                 String tableName = getTableName(data.getTableId());
-                if(isFilterTable(tableName, ConnectorConstant.OPERTION_DELETE)){
+                if (isFilterTable(tableName, ConnectorConstant.OPERTION_DELETE)) {
                     data.getRows().forEach(m -> {
                         List<Object> before = Stream.of(m).collect(Collectors.toList());
                         asynSendRowChangedEvent(new RowChangedEvent(tableName, ConnectorConstant.OPERTION_DELETE, before, Collections.EMPTY_LIST));
@@ -266,8 +266,8 @@ public class MysqlExtractor extends AbstractExtractor {
             return tables.get(tableId).getTable();
         }
 
-        private boolean isFilterTable(String tableName, String event){
-            if(!filterTable.contains(tableName)){
+        private boolean isFilterTable(String tableName, String event) {
+            if (!filterTable.contains(tableName)) {
                 logger.info("Table[{}] {}", tableName, event);
                 return false;
             }

+ 139 - 0
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/AbstractQuartzExtractor.java

@@ -0,0 +1,139 @@
+package org.dbsyncer.listener.quartz;
+
+import org.dbsyncer.common.event.RowChangedEvent;
+import org.dbsyncer.common.model.Result;
+import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.UUIDUtil;
+import org.dbsyncer.connector.ConnectorMapper;
+import org.dbsyncer.connector.config.ReaderConfig;
+import org.dbsyncer.connector.constant.ConnectorConstant;
+import org.dbsyncer.listener.AbstractExtractor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * 定时抽取
+ *
+ * @version 1.0.0
+ * @Author AE86
+ * @Date 2020-05-12 20:35
+ */
+public abstract class AbstractQuartzExtractor extends AbstractExtractor implements ScheduledTaskJob {
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private List<Map<String, String>> commands;
+    private int commandSize;
+
+    private int readNum;
+    private String eventFieldName;
+    private Set<String> update;
+    private Set<String> insert;
+    private Set<String> delete;
+    private String taskKey;
+    private long period;
+    private AtomicBoolean running;
+
+    /**
+     * 获取增量参数
+     *
+     * @param command
+     * @param index
+     * @return
+     */
+    protected abstract Point checkLastPoint(Map<String, String> command, int index);
+
+    @Override
+    public void start() {
+        commandSize = commands.size();
+
+        readNum = listenerConfig.getReadNum();
+        eventFieldName = listenerConfig.getEventFieldName();
+        update = Stream.of(listenerConfig.getUpdate().split(",")).collect(Collectors.toSet());
+        insert = Stream.of(listenerConfig.getInsert().split(",")).collect(Collectors.toSet());
+        delete = Stream.of(listenerConfig.getDelete().split(",")).collect(Collectors.toSet());
+
+        taskKey = UUIDUtil.getUUID();
+        period = listenerConfig.getPeriod();
+        running = new AtomicBoolean();
+        run();
+        scheduledTaskService.start(taskKey, period * 1000, this);
+        logger.info("启动定时任务:{} >> {}秒", taskKey, period);
+    }
+
+    @Override
+    public void run() {
+        try {
+            if (running.compareAndSet(false, true)) {
+                // 依次执行同步映射关系
+                for (int i = 0; i < commandSize; i++) {
+                    execute(commands.get(i), i);
+                }
+                running.compareAndSet(true, false);
+            }
+        } catch (Exception e) {
+            running.compareAndSet(true, false);
+            errorEvent(e);
+            logger.error(e.getMessage());
+        }
+    }
+
+    @Override
+    public void close() {
+        scheduledTaskService.stop(taskKey);
+    }
+
+    private void execute(Map<String, String> command, int index) {
+        // 检查增量点
+        ConnectorMapper connectionMapper = connectorFactory.connect(connectorConfig);
+        Point point = checkLastPoint(command, index);
+        int pageIndex = 1;
+        for (; ; ) {
+            Result reader = connectorFactory.reader(connectionMapper, new ReaderConfig(point.getCommand(), point.getArgs(), pageIndex++, readNum));
+            List<Map> data = reader.getData();
+            if (CollectionUtils.isEmpty(data)) {
+                break;
+            }
+
+            Object event = null;
+            for (Map<String, Object> row : data) {
+                event = row.get(eventFieldName);
+                if (update.contains(event)) {
+                    changedEvent(new RowChangedEvent(index, ConnectorConstant.OPERTION_UPDATE, Collections.EMPTY_MAP, row));
+                    continue;
+                }
+                if (insert.contains(event)) {
+                    changedEvent(new RowChangedEvent(index, ConnectorConstant.OPERTION_INSERT, Collections.EMPTY_MAP, row));
+                    continue;
+                }
+                if (delete.contains(event)) {
+                    changedEvent(new RowChangedEvent(index, ConnectorConstant.OPERTION_DELETE, row, Collections.EMPTY_MAP));
+                    continue;
+                }
+
+            }
+            // 更新记录点
+            point.refresh();
+
+        }
+
+        // 持久化
+        if (point.refreshed()) {
+            snapshot.putAll(point.getPosition());
+        }
+
+    }
+
+    public void setCommands(List<Map<String, String>> commands) {
+        this.commands = commands;
+    }
+
+}

+ 78 - 0
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/DatabaseQuartzExtractor.java

@@ -0,0 +1,78 @@
+package org.dbsyncer.listener.quartz;
+
+import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.constant.ConnectorConstant;
+import org.dbsyncer.listener.enums.QuartzFilterEnum;
+import org.springframework.util.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * 关系型数据库定时抽取
+ *
+ * @version 1.0.0
+ * @Author AE86
+ * @Date 2021-09-01 20:35
+ */
+public final class DatabaseQuartzExtractor extends AbstractQuartzExtractor {
+
+    @Override
+    protected Point checkLastPoint(Map<String, String> command, int index) {
+        // 检查是否存在系统参数
+        final String query = command.get(ConnectorConstant.OPERTION_QUERY);
+        List<QuartzFilterEnum> filterEnums = Stream.of(QuartzFilterEnum.values()).filter(f -> {
+            Assert.isTrue(appearNotMoreThanOnce(query, f.getType()), String.format("系统参数%s存在多个.", f.getType()));
+            return StringUtil.contains(query, f.getType());
+        }).collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(filterEnums)) {
+            return new Point(command, new ArrayList<>());
+        }
+
+        Point point = new Point();
+        // 存在系统参数,替换
+        String replaceQuery = query;
+        for (QuartzFilterEnum quartzFilter : filterEnums) {
+            final String type = quartzFilter.getType();
+            final QuartzFilter f = quartzFilter.getQuartzFilter();
+
+            // 替换字符
+            replaceQuery = StringUtil.replace(replaceQuery, "'" + type + "'", "?");
+
+            // 创建参数索引key
+            final String key = index + type;
+
+            // 开始位置
+            if(f.begin()){
+                if (!snapshot.containsKey(key)) {
+                    final Object val = f.getObject();
+                    point.addArg(val);
+                    snapshot.put(key, f.toString(val));
+                    continue;
+                }
+
+                // 读取历史增量点
+                Object val = f.getObject(snapshot.get(key));
+                point.addArg(val);
+                point.setBeginKey(key);
+                point.setBeginValue(f.toString(f.getObject()));
+                continue;
+            }
+            // 结束位置(刷新)
+            Object val = f.getObject();
+            point.addArg(val);
+            point.setBeginValue(f.toString(val));
+        }
+        point.setCommand(ConnectorConstant.OPERTION_QUERY, replaceQuery);
+
+        return point;
+    }
+
+    private boolean appearNotMoreThanOnce(String str, String searchStr) {
+        return StringUtil.indexOf(str, searchStr) == StringUtil.lastIndexOf(str, searchStr);
+    }
+}

+ 74 - 0
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/ESQuartzExtractor.java

@@ -0,0 +1,74 @@
+package org.dbsyncer.listener.quartz;
+
+import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.JsonUtil;
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.connector.config.Filter;
+import org.dbsyncer.connector.constant.ConnectorConstant;
+import org.dbsyncer.listener.ListenerException;
+import org.dbsyncer.listener.enums.QuartzFilterEnum;
+
+import java.util.*;
+
+/**
+ * ES定时抽取
+ *
+ * @version 1.0.0
+ * @Author AE86
+ * @Date 2021-09-01 20:35
+ */
+public final class ESQuartzExtractor extends AbstractQuartzExtractor {
+
+    @Override
+    protected Point checkLastPoint(Map<String, String> command, int index) {
+        // 检查是否存在系统参数
+        String filterJson = command.get(ConnectorConstant.OPERTION_QUERY_FILTER);
+        if (StringUtil.isBlank(filterJson)) {
+            return new Point(command, new ArrayList<>());
+        }
+        List<Filter> filters = JsonUtil.jsonToArray(filterJson, Filter.class);
+        if (CollectionUtils.isEmpty(filters)) {
+            return new Point(command, new ArrayList<>());
+        }
+
+        // 存在系统参数,替换
+        Point point = new Point();
+        Set<String> set = new HashSet<>();
+        for (Filter f : filters) {
+            if (set.contains(f.getValue())) {
+                throw new ListenerException(String.format("系统参数%s存在多个.", f.getValue()));
+            }
+            QuartzFilterEnum filterEnum = QuartzFilterEnum.getQuartzFilterEnum(f.getValue());
+            if (null != filterEnum) {
+                // 标记防重
+                set.add(f.getValue());
+
+                final QuartzFilter quartzFilter = filterEnum.getQuartzFilter();
+
+                // 创建参数索引key
+                final String key = index + filterEnum.getType();
+
+                // 开始位置
+                if (quartzFilter.begin()) {
+                    if (!snapshot.containsKey(key)) {
+                        f.setValue(quartzFilter.toString(quartzFilter.getObject()));
+                        snapshot.put(key, f.getValue());
+                        continue;
+                    }
+
+                    // 读取历史增量点
+                    f.setValue(snapshot.get(key));
+                    point.setBeginKey(key);
+                    point.setBeginValue(quartzFilter.toString(quartzFilter.getObject()));
+                    continue;
+                }
+                // 结束位置(刷新)
+                f.setValue(quartzFilter.toString(quartzFilter.getObject()));
+                point.setBeginValue(f.getValue());
+            }
+        }
+        point.setCommand(ConnectorConstant.OPERTION_QUERY, command.get(ConnectorConstant.OPERTION_QUERY));
+        point.setCommand(ConnectorConstant.OPERTION_QUERY_FILTER, JsonUtil.objToJson(filters));
+        return point;
+    }
+}

+ 69 - 0
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/Point.java

@@ -0,0 +1,69 @@
+package org.dbsyncer.listener.quartz;
+
+import org.dbsyncer.common.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Point {
+
+    private Map<String, String> position;
+    private Map<String, String> command;
+    private List<Object> args;
+    private String beginKey;
+    private String beginValue;
+    private boolean refreshed;
+
+    public Point() {
+        this.position = new HashMap<>();
+        this.command = new HashMap<>();
+        this.args = new ArrayList<>();
+    }
+
+    public Point(Map<String, String> command, List<Object> args) {
+        this.command = command;
+        this.args = args;
+    }
+
+    public void setCommand(String key, String value) {
+        command.put(key, value);
+    }
+
+    public void addArg(Object val) {
+        args.add(val);
+    }
+
+    public void refresh() {
+        if(StringUtil.isNotBlank(beginKey) && StringUtil.isNotBlank(beginValue)){
+            position.put(beginKey, beginValue);
+            refreshed = true;
+        }
+    }
+
+    public boolean refreshed() {
+        return refreshed;
+    }
+
+    public Map<String, String> getPosition() {
+        return position;
+    }
+
+    public Map<String, String> getCommand() {
+        return command;
+    }
+
+    public List<Object> getArgs() {
+        return new ArrayList<>(args);
+    }
+
+    public void setBeginKey(String beginKey) {
+        this.beginKey = beginKey;
+    }
+
+    public void setBeginValue(String beginValue) {
+        this.beginValue = beginValue;
+    }
+
+}

+ 0 - 249
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/QuartzExtractor.java

@@ -1,249 +0,0 @@
-package org.dbsyncer.listener.quartz;
-
-import org.apache.commons.lang.StringUtils;
-import org.dbsyncer.common.event.RowChangedEvent;
-import org.dbsyncer.common.model.Result;
-import org.dbsyncer.common.util.CollectionUtils;
-import org.dbsyncer.common.util.UUIDUtil;
-import org.dbsyncer.connector.ConnectorMapper;
-import org.dbsyncer.connector.config.ReaderConfig;
-import org.dbsyncer.connector.constant.ConnectorConstant;
-import org.dbsyncer.listener.AbstractExtractor;
-import org.dbsyncer.listener.QuartzFilter;
-import org.dbsyncer.listener.enums.QuartzFilterEnum;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.util.Assert;
-
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * 默认定时抽取
- *
- * @version 1.0.0
- * @Author AE86
- * @Date 2020-05-12 20:35
- */
-public class QuartzExtractor extends AbstractExtractor implements ScheduledTaskJob {
-
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-
-    private List<Map<String, String>> commands;
-    private int commandSize;
-
-    private int readNum;
-    private String eventFieldName;
-    private Set<String> update;
-    private Set<String> insert;
-    private Set<String> delete;
-    private String taskKey;
-    private long period;
-    private AtomicBoolean running;
-
-    @Override
-    public void start() {
-        init();
-        run();
-        scheduledTaskService.start(taskKey, period * 1000, this);
-        logger.info("启动定时任务:{} >> {}秒", taskKey, period);
-    }
-
-    @Override
-    public void run() {
-        try {
-            if (running.compareAndSet(false, true)) {
-                // 依次执行同步映射关系
-                for (int i = 0; i < commandSize; i++) {
-                    execute(commands.get(i), i);
-                }
-                running.compareAndSet(true, false);
-            }
-        } catch (Exception e) {
-            running.compareAndSet(true, false);
-            errorEvent(e);
-            logger.error(e.getMessage());
-        }
-    }
-
-    @Override
-    public void close() {
-        scheduledTaskService.stop(taskKey);
-    }
-
-    private void execute(Map<String, String> command, int index) {
-        // 检查增量点
-        ConnectorMapper connectionMapper = connectorFactory.connect(connectorConfig);
-        Point point = checkLastPoint(command, index);
-        int pageIndex = 1;
-        for (; ; ) {
-            Result reader = connectorFactory.reader(new ReaderConfig(connectionMapper, point.getCommand(), point.getArgs(), pageIndex++, readNum));
-            List<Map> data = reader.getData();
-            if (CollectionUtils.isEmpty(data)) {
-                break;
-            }
-
-            Object event = null;
-            for (Map<String, Object> row : data) {
-                event = row.get(eventFieldName);
-                if (update.contains(event)) {
-                    changedEvent(new RowChangedEvent(index, ConnectorConstant.OPERTION_UPDATE, Collections.EMPTY_MAP, row));
-                    continue;
-                }
-                if (insert.contains(event)) {
-                    changedEvent(new RowChangedEvent(index, ConnectorConstant.OPERTION_INSERT, Collections.EMPTY_MAP, row));
-                    continue;
-                }
-                if (delete.contains(event)) {
-                    changedEvent(new RowChangedEvent(index, ConnectorConstant.OPERTION_DELETE, row, Collections.EMPTY_MAP));
-                    continue;
-                }
-
-            }
-            // 更新记录点
-            point.refresh();
-
-        }
-
-        // 持久化
-        if (point.refreshed()) {
-            snapshot.putAll(point.getPosition());
-        }
-
-    }
-
-    private Point checkLastPoint(Map<String, String> command, int index) {
-        // 检查是否存在系统参数
-        final String query = command.get(ConnectorConstant.OPERTION_QUERY);
-        List<QuartzFilterEnum> filterEnums = Stream.of(QuartzFilterEnum.values()).filter(f -> {
-            Assert.isTrue(appearNotMoreThanOnce(query, f.getType()), String.format("系统参数%s存在多个.", f.getType()));
-            return StringUtils.contains(query, f.getType());
-        }).collect(Collectors.toList());
-        if (CollectionUtils.isEmpty(filterEnums)) {
-            return new Point(command, new ArrayList<>());
-        }
-
-        Point point = new Point();
-        // 存在系统参数,替换
-        String replaceQuery = query;
-        for (QuartzFilterEnum quartzFilter : filterEnums) {
-            final String type = quartzFilter.getType();
-            final QuartzFilter f = quartzFilter.getQuartzFilter();
-
-            // 替换字符
-            replaceQuery = StringUtils.replace(replaceQuery, "'" + type + "'", "?");
-
-            // 创建参数索引key
-            final String key = index + type;
-
-            // 开始位置
-            if(f.begin()){
-                if (!snapshot.containsKey(key)) {
-                    final Object val = f.getObject();
-                    point.addArg(val);
-                    snapshot.put(key, f.toString(val));
-                    continue;
-                }
-
-                // 读取历史增量点
-                Object val = f.getObject(snapshot.get(key));
-                point.addArg(val);
-                point.setBeginKey(key);
-                point.setBeginValue(f.toString(f.getObject()));
-                continue;
-            }
-            // 结束位置(刷新)
-            Object val = f.getObject();
-            point.addArg(val);
-            point.setBeginValue(f.toString(val));
-        }
-        point.setCommand(ConnectorConstant.OPERTION_QUERY, replaceQuery);
-
-        return point;
-    }
-
-    private void init() {
-        commandSize = commands.size();
-
-        readNum = listenerConfig.getReadNum();
-        eventFieldName = listenerConfig.getEventFieldName();
-        update = Stream.of(listenerConfig.getUpdate().split(",")).collect(Collectors.toSet());
-        insert = Stream.of(listenerConfig.getInsert().split(",")).collect(Collectors.toSet());
-        delete = Stream.of(listenerConfig.getDelete().split(",")).collect(Collectors.toSet());
-
-        taskKey = UUIDUtil.getUUID();
-        period = listenerConfig.getPeriod();
-        running = new AtomicBoolean();
-    }
-
-    private boolean appearNotMoreThanOnce(String str, String searchStr) {
-        return StringUtils.indexOf(str, searchStr) == StringUtils.lastIndexOf(str, searchStr);
-    }
-
-    public void setCommands(List<Map<String, String>> commands) {
-        this.commands = commands;
-    }
-
-    final class Point {
-
-        private Map<String, String> position;
-        private Map<String, String> command;
-        private List<Object> args;
-        private String beginKey;
-        private String beginValue;
-        private boolean refreshed;
-
-        public Point() {
-            this.position = new HashMap<>();
-            this.command = new HashMap<>();
-            this.args = new ArrayList<>();
-        }
-
-        public Point(Map<String, String> command, List<Object> args) {
-            this.command = command;
-            this.args = args;
-        }
-
-        public void setCommand(String key, String value) {
-            command.put(key, value);
-        }
-
-        public void addArg(Object val) {
-            args.add(val);
-        }
-
-        public void refresh() {
-            if(StringUtils.isNotBlank(beginKey) && StringUtils.isNotBlank(beginValue)){
-                position.put(beginKey, beginValue);
-                refreshed = true;
-            }
-        }
-
-        public boolean refreshed() {
-            return refreshed;
-        }
-
-        public Map<String, String> getPosition() {
-            return position;
-        }
-
-        public Map<String, String> getCommand() {
-            return command;
-        }
-
-        public List<Object> getArgs() {
-            return new ArrayList<>(args);
-        }
-
-        public void setBeginKey(String beginKey) {
-            this.beginKey = beginKey;
-        }
-
-        public void setBeginValue(String beginValue) {
-            this.beginValue = beginValue;
-        }
-    }
-
-}

+ 2 - 4
dbsyncer-listener/src/main/java/org/dbsyncer/listener/QuartzFilter.java → dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/QuartzFilter.java

@@ -1,4 +1,4 @@
-package org.dbsyncer.listener;
+package org.dbsyncer.listener.quartz;
 
 public interface QuartzFilter {
 
@@ -30,7 +30,5 @@ public interface QuartzFilter {
      *
      * @return
      */
-    default boolean begin(){
-        return true;
-    }
+    boolean begin();
 }

+ 35 - 0
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/filter/DateFilter.java

@@ -0,0 +1,35 @@
+package org.dbsyncer.listener.quartz.filter;
+
+import org.dbsyncer.common.util.DateFormatUtil;
+import org.dbsyncer.listener.quartz.QuartzFilter;
+
+import java.util.Date;
+
+public class DateFilter implements QuartzFilter {
+
+    private boolean begin;
+
+    public DateFilter(boolean begin) {
+        this.begin = begin;
+    }
+
+    @Override
+    public Object getObject() {
+        return new Date();
+    }
+
+    @Override
+    public Object getObject(String s) {
+        return DateFormatUtil.stringToDate(s);
+    }
+
+    @Override
+    public String toString(Object value) {
+        return DateFormatUtil.dateToString((Date) value);
+    }
+
+    @Override
+    public boolean begin() {
+        return begin;
+    }
+}

+ 36 - 0
dbsyncer-listener/src/main/java/org/dbsyncer/listener/quartz/filter/TimestampFilter.java

@@ -0,0 +1,36 @@
+package org.dbsyncer.listener.quartz.filter;
+
+import org.dbsyncer.listener.quartz.QuartzFilter;
+
+import java.sql.Timestamp;
+import java.time.Instant;
+
+public class TimestampFilter implements QuartzFilter {
+
+    private boolean begin;
+
+    public TimestampFilter(boolean begin) {
+        this.begin = begin;
+    }
+
+    @Override
+    public Object getObject() {
+        return new Timestamp(Instant.now().toEpochMilli());
+    }
+
+    @Override
+    public Object getObject(String s) {
+        return new Timestamp(Long.parseLong(s));
+    }
+
+    @Override
+    public String toString(Object value) {
+        Timestamp ts = (Timestamp) value;
+        return String.valueOf(ts.getTime());
+    }
+
+    @Override
+    public boolean begin() {
+        return begin;
+    }
+}

+ 18 - 18
dbsyncer-listener/src/main/java/org/dbsyncer/listener/sqlserver/SqlServerExtractor.java

@@ -1,12 +1,12 @@
 package org.dbsyncer.listener.sqlserver;
 
 import com.microsoft.sqlserver.jdbc.SQLServerException;
-import org.apache.commons.lang.math.RandomUtils;
 import org.dbsyncer.common.event.RowChangedEvent;
 import org.dbsyncer.common.util.CollectionUtils;
-import org.dbsyncer.connector.ConnectorMapper;
+import org.dbsyncer.common.util.RandomUtil;
 import org.dbsyncer.connector.config.DatabaseConfig;
 import org.dbsyncer.connector.constant.ConnectorConstant;
+import org.dbsyncer.connector.database.DatabaseConnectorMapper;
 import org.dbsyncer.listener.AbstractExtractor;
 import org.dbsyncer.listener.ListenerException;
 import org.dbsyncer.listener.enums.TableOperationEnum;
@@ -47,18 +47,18 @@ public class SqlServerExtractor extends AbstractExtractor {
 
     private static final String LSN_POSITION = "position";
     private static final long DEFAULT_POLL_INTERVAL_MILLIS = 300;
-    private static final int PREPARED_STATEMENT_CACHE_CAPACITY = 500;
-    private static final int OFFSET_COLUMNS = 4;
-    private final Map<String, PreparedStatement> preparedStatementCache = new ConcurrentHashMap<>(PREPARED_STATEMENT_CACHE_CAPACITY);
-    private final Lock connectLock = new ReentrantLock();
-    private volatile boolean connected;
-    private volatile boolean connectionClosed;
-    private static Set<String> tables;
-    private static Set<SqlServerChangeTable> changeTables;
-    private ConnectorMapper connectorMapper;
-    private Worker worker;
-    private Lsn lastLsn;
-    private String serverName;
+    private static final int                            PREPARED_STATEMENT_CACHE_CAPACITY = 500;
+    private static final int                            OFFSET_COLUMNS = 4;
+    private final        Map<String, PreparedStatement> preparedStatementCache = new ConcurrentHashMap<>(PREPARED_STATEMENT_CACHE_CAPACITY);
+    private final        Lock                           connectLock = new ReentrantLock();
+    private volatile     boolean                        connected;
+    private volatile     boolean                        connectionClosed;
+    private static       Set<String>                    tables;
+    private static       Set<SqlServerChangeTable>      changeTables;
+    private              DatabaseConnectorMapper        connectorMapper;
+    private              Worker                         worker;
+    private              Lsn                            lastLsn;
+    private              String                         serverName;
 
     @Override
     public void start() {
@@ -82,7 +82,7 @@ public class SqlServerExtractor extends AbstractExtractor {
             readLastLsn();
 
             worker = new Worker();
-            worker.setName(new StringBuilder("cdc-parser-").append(serverName).append("_").append(RandomUtils.nextInt(100)).toString());
+            worker.setName(new StringBuilder("cdc-parser-").append(serverName).append("_").append(RandomUtil.nextInt(1, 100)).toString());
             worker.setDaemon(false);
             worker.start();
         } catch (Exception e) {
@@ -121,7 +121,7 @@ public class SqlServerExtractor extends AbstractExtractor {
     private void connect() {
         DatabaseConfig cfg = (DatabaseConfig) connectorConfig;
         if (connectorFactory.isAlive(cfg)) {
-            connectorMapper = connectorFactory.connect(cfg);
+            connectorMapper = (DatabaseConnectorMapper) connectorFactory.connect(cfg);
             serverName = cfg.getUrl();
             connectionClosed = false;
         }
@@ -210,7 +210,7 @@ public class SqlServerExtractor extends AbstractExtractor {
     }
 
     private void execute(String... sqlStatements) {
-        connectorMapper.execute((databaseTemplate) -> {
+        connectorMapper.execute(databaseTemplate -> {
             for (String sqlStatement : sqlStatements) {
                 if (sqlStatement != null) {
                     logger.info("executing '{}'", sqlStatement);
@@ -304,7 +304,7 @@ public class SqlServerExtractor extends AbstractExtractor {
             connect();
             return null;
         }
-        Object execute = connectorMapper.execute((databaseTemplate) -> {
+        Object execute = connectorMapper.execute(databaseTemplate -> {
             if (!preparedStatementCache.containsKey(preparedQuerySql)) {
                 preparedStatementCache.putIfAbsent(preparedQuerySql, databaseTemplate.getConnection().prepareStatement(preparedQuerySql));
             }

+ 263 - 0
dbsyncer-listener/src/main/test/ESClientTest.java

@@ -0,0 +1,263 @@
+import org.dbsyncer.connector.config.ESConfig;
+import org.dbsyncer.connector.util.ESUtil;
+import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.bulk.BulkItemResponse;
+import org.elasticsearch.action.bulk.BulkRequest;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.delete.DeleteRequest;
+import org.elasticsearch.action.delete.DeleteResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.CreateIndexRequest;
+import org.elasticsearch.client.indices.CreateIndexResponse;
+import org.elasticsearch.client.indices.GetIndexRequest;
+import org.elasticsearch.client.indices.GetIndexResponse;
+import org.elasticsearch.cluster.metadata.MappingMetaData;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ESClientTest {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+    private RestHighLevelClient client;
+    private String indexName = "test_index";
+    private String type = "_doc";
+
+    @Before
+    public void init() {
+        ESConfig config = new ESConfig();
+        config.setUrl("127.0.0.1:9200");
+        config.setSchema("http");
+        config.setUsername("ae86");
+        config.setPassword("123456");
+        client = ESUtil.getConnection(config);
+        try {
+            boolean ret = client.ping(RequestOptions.DEFAULT);
+            logger.info("es ping ret:{}", ret);
+        } catch (Exception e) {
+            logger.error(e.getMessage());
+        }
+    }
+
+    @After
+    public void close() {
+        ESUtil.close(client);
+    }
+
+    @Test
+    public void isExistsIndexTest() {
+        try {
+            GetIndexRequest request = new GetIndexRequest(indexName);
+            boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
+            logger.info("es exist index:{}", exists);
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+        }
+    }
+
+    @Test
+    public void createIndexTest() throws IOException {
+        CreateIndexRequest request = new CreateIndexRequest(indexName);
+        request.settings(Settings.builder()
+                .put("index.number_of_shards", 1)
+                .put("index.number_of_replicas", 0)
+        );
+        // 构建索引字段
+        XContentBuilder builder = XContentFactory.jsonBuilder();
+        builder.startObject();
+        {
+            // 是否容许对象下面的属性自由扩展,(值true/false/strict,默认true)
+            builder.field("dynamic", "strict");
+            builder.startObject("properties");
+            {
+                builder.startObject("id");
+                {
+                    builder.field("type", "integer");
+                }
+                builder.endObject();
+            }
+            {
+                builder.startObject("name");
+                {
+                    builder.field("type", "text");
+                }
+                builder.endObject();
+            }
+            {
+                builder.startObject("content");
+                {
+                    builder.field("type", "keyword");
+                    // 字符串长度限定(针对keyword),keyword类型下,字符过于长,检索意义不大,索引会被禁用,数据不可被检索,默认值256
+                    builder.field("ignore_above", 256);
+                }
+                builder.endObject();
+            }
+            {
+                builder.startObject("tags");
+                {
+                    builder.field("type", "long");
+                }
+                builder.endObject();
+            }
+            builder.endObject();
+        }
+        builder.endObject();
+        // 7版本开始去掉type
+        request.mapping(builder);
+        // 这里创建索引结构
+        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
+        // 指示是否所有节点都已确认请求
+        boolean acknowledged = response.isAcknowledged();
+        // 指示是否在超时之前为索引中的每个分片启动了必需的分片副本数
+        boolean shardsAcknowledged = response.isShardsAcknowledged();
+        if (acknowledged || shardsAcknowledged) {
+            logger.info("创建索引成功!索引名称为{}", indexName);
+        }
+    }
+
+    @Test
+    public void getIndexTest() throws IOException {
+        GetIndexRequest request = new GetIndexRequest(indexName);
+        GetIndexResponse indexResponse = client.indices().get(request, RequestOptions.DEFAULT);
+        // 获取索引
+        String[] indices = indexResponse.getIndices();
+        for (String index : indices) {
+            logger.info(index);
+        }
+
+        // 字段信息
+        MappingMetaData mappingMetaData = indexResponse.getMappings().get(indexName);
+        Map<String, Object> propertiesMap = mappingMetaData.getSourceAsMap();
+        Map<String, Map> properties = (Map<String, Map>) propertiesMap.get(ESUtil.PROPERTIES);
+        logger.info(properties.toString());
+    }
+
+    @Test
+    public void deleteIndexTest() throws IOException {
+        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
+        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
+        logger.info(response.toString());
+    }
+
+    @Test
+    public void pushTest() throws IOException {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", 2);
+        map.put("name", "刘备关羽张飞");
+        map.put("content", "桃园结义");
+        map.put("tags", new Long[]{200L});
+        map.put("update_time", System.currentTimeMillis());
+        IndexRequest request = new IndexRequest(indexName, type, "2");
+        request.source(map, XContentType.JSON);
+
+        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
+        RestStatus status = indexResponse.status();
+        logger.info(status.name());
+    }
+
+    @Test
+    public void bulkPushTest() throws IOException {
+        BulkRequest request = new BulkRequest();
+        Map<String, Object> m1 = new HashMap<>();
+        m1.put("id", 1);
+        m1.put("name", "刘备关羽张飞");
+        m1.put("content", "桃园结义");
+        m1.put("tags", new Long[]{200L});
+        m1.put("update_time", System.currentTimeMillis());
+        IndexRequest r1 = new IndexRequest(indexName, type, "1");
+        r1.source(m1, XContentType.JSON);
+        request.add(r1);
+
+        Map<String, Object> m2 = new HashMap<>();
+        m2.put("id", 2);
+        m2.put("name", "曹阿瞒");
+        m2.put("content", "火烧");
+        m2.put("tags", new Long[]{200L, 300L});
+        m2.put("update_time", System.currentTimeMillis());
+        IndexRequest r2 = new IndexRequest(indexName, type, "2");
+        r2.source(m2, XContentType.JSON);
+        request.add(r2);
+
+        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
+        BulkItemResponse[] items = response.getItems();
+        for (BulkItemResponse r : items) {
+            logger.info(r.status().name());
+        }
+        logger.info(response.toString());
+    }
+
+    @Test
+    public void deleteTest() throws IOException {
+        DeleteRequest request = new DeleteRequest(indexName, type, "2");
+        DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
+        logger.info(delete.toString());
+    }
+
+    @Test
+    public void bulkDeleteTest() throws IOException {
+        BulkRequest request = new BulkRequest();
+        request.add(new DeleteRequest(indexName, type, "1"));
+        request.add(new DeleteRequest(indexName, type, "2"));
+
+        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
+        BulkItemResponse[] items = response.getItems();
+        for (BulkItemResponse r : items) {
+            logger.info(r.status().name());
+        }
+        logger.info(response.toString());
+    }
+
+    @Test
+    public void searchTest() throws IOException {
+        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
+        sourceBuilder.query(QueryBuilders.boolQuery().filter(QueryBuilders.termsQuery("tags", Arrays.asList(200L, 300L))));
+        sourceBuilder.from(0);
+        sourceBuilder.size(10);
+        sourceBuilder.timeout(TimeValue.timeValueMillis(10));
+        sourceBuilder.fetchSource(new String[]{"id", "name"}, null);
+
+        SearchRequest rq = new SearchRequest(new String[]{indexName}, sourceBuilder);
+        SearchResponse searchResponse = client.search(rq, RequestOptions.DEFAULT);
+        SearchHits hits = searchResponse.getHits();
+        long totalHits = hits.getTotalHits();
+        logger.info("result:{}", totalHits);
+        SearchHit[] searchHits = hits.getHits();
+        for (SearchHit hit : searchHits) {
+            logger.info(hit.getSourceAsMap().toString());
+        }
+    }
+
+    @Test
+    public void getCountTest() throws IOException {
+        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
+        // 取消限制返回查询条数10000
+        sourceBuilder.trackTotalHits(true);
+        SearchRequest request = new SearchRequest(new String[]{indexName}, sourceBuilder);
+        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);
+        SearchHits hits = searchResponse.getHits();
+        long totalHits = hits.getTotalHits();
+        logger.info("result:{}", totalHits);
+    }
+}

+ 4 - 4
dbsyncer-listener/src/main/test/LinkedBlockingQueueTest.java

@@ -1,5 +1,5 @@
 import oracle.jdbc.dcn.TableChangeDescription;
-import org.apache.commons.lang.math.RandomUtils;
+import org.dbsyncer.common.util.RandomUtil;
 import org.dbsyncer.listener.oracle.event.DCNEvent;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit;
 
 public class LinkedBlockingQueueTest {
 
-    private final Logger                  logger = LoggerFactory.getLogger(getClass());
+    private final Logger        logger = LoggerFactory.getLogger(getClass());
     private       BlockingQueue queue  = new LinkedBlockingQueue<>(10);
 
     @Test
@@ -61,7 +61,7 @@ public class LinkedBlockingQueueTest {
         BlockingQueue<DCNEvent> queue;
 
         public Consumer(BlockingQueue<DCNEvent> queue) {
-            setName("Consumer-thread-" + RandomUtils.nextInt(100));
+            setName("Consumer-thread-" + RandomUtil.nextInt(1, 100));
             this.queue = queue;
         }
 
@@ -72,7 +72,7 @@ public class LinkedBlockingQueueTest {
             while (true) {
                 try {
                     // 模拟耗时
-                    TimeUnit.SECONDS.sleep(RandomUtils.nextInt(3));
+                    TimeUnit.SECONDS.sleep(RandomUtil.nextInt(0, 3));
                     // 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止
                     DCNEvent event = queue.take();
                     logger.error("消费线程{}接受消息:{}", threadName, event.getTableName());

+ 1 - 1
dbsyncer-manager/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-manager</artifactId>

+ 4 - 4
dbsyncer-manager/src/main/java/org/dbsyncer/manager/config/FieldPicker.java

@@ -1,7 +1,7 @@
 package org.dbsyncer.manager.config;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.CompareFilter;
 import org.dbsyncer.connector.config.Field;
 import org.dbsyncer.connector.config.Filter;
@@ -97,9 +97,9 @@ public class FieldPicker {
 
         // 解析过滤条件
         if ((filterSwitch = !CollectionUtils.isEmpty(filter))) {
-            add = filter.stream().filter(f -> StringUtils.equals(f.getOperation(), OperationEnum.AND.getName())).collect(
+            add = filter.stream().filter(f -> StringUtil.equals(f.getOperation(), OperationEnum.AND.getName())).collect(
                     Collectors.toList());
-            or = filter.stream().filter(f -> StringUtils.equals(f.getOperation(), OperationEnum.OR.getName())).collect(Collectors.toList());
+            or = filter.stream().filter(f -> StringUtil.equals(f.getOperation(), OperationEnum.OR.getName())).collect(Collectors.toList());
         }
 
         // 记录字段索引 [{"ID":0},{"NAME":1}]
@@ -128,7 +128,7 @@ public class FieldPicker {
         // 属性
         String name;
         // 索引
-        int    i;
+        int i;
 
         public Node(String name, int i) {
             this.name = name;

+ 5 - 5
dbsyncer-manager/src/main/java/org/dbsyncer/manager/puller/impl/IncrementPuller.java

@@ -1,9 +1,9 @@
 package org.dbsyncer.manager.puller.impl;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.common.event.Event;
 import org.dbsyncer.common.event.RowChangedEvent;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.common.util.UUIDUtil;
 import org.dbsyncer.connector.ConnectorFactory;
 import org.dbsyncer.connector.config.ConnectorConfig;
@@ -15,7 +15,7 @@ import org.dbsyncer.listener.Extractor;
 import org.dbsyncer.listener.Listener;
 import org.dbsyncer.listener.config.ListenerConfig;
 import org.dbsyncer.listener.enums.ListenerTypeEnum;
-import org.dbsyncer.listener.quartz.QuartzExtractor;
+import org.dbsyncer.listener.quartz.AbstractQuartzExtractor;
 import org.dbsyncer.listener.quartz.ScheduledTaskJob;
 import org.dbsyncer.listener.quartz.ScheduledTaskService;
 import org.dbsyncer.manager.Manager;
@@ -154,7 +154,7 @@ public class IncrementPuller extends AbstractPuller implements ScheduledTaskJob,
 
         // 默认定时抽取
         if (ListenerTypeEnum.isTiming(listenerType)) {
-            QuartzExtractor extractor = listener.getExtractor(listenerType, QuartzExtractor.class);
+            AbstractQuartzExtractor extractor = listener.getExtractor(ListenerTypeEnum.TIMING.getType(), connectorConfig.getConnectorType(), AbstractQuartzExtractor.class);
             List<Map<String, String>> commands = list.stream().map(t -> t.getCommand()).collect(Collectors.toList());
             extractor.setCommands(commands);
             setExtractorConfig(extractor, connectorConfig, listenerConfig, meta.getMap(), new QuartzListener(mapping, list));
@@ -163,7 +163,7 @@ public class IncrementPuller extends AbstractPuller implements ScheduledTaskJob,
 
         // 基于日志抽取
         if (ListenerTypeEnum.isLog(listenerType)) {
-            AbstractExtractor extractor = listener.getExtractor(connectorConfig.getConnectorType(), AbstractExtractor.class);
+            AbstractExtractor extractor = listener.getExtractor(ListenerTypeEnum.LOG.getType(), connectorConfig.getConnectorType(), AbstractExtractor.class);
             LogListener logListener = new LogListener(mapping, list, extractor);
             Set<String> filterTable = new HashSet<>();
             logListener.getTablePicker().forEach((k, fieldPickers) -> filterTable.add(k));
@@ -315,7 +315,7 @@ public class IncrementPuller extends AbstractPuller implements ScheduledTaskJob,
                 pickers.parallelStream().forEach(picker -> {
                     final Map<String, Object> before = picker.getColumns(rowChangedEvent.getBeforeData());
                     final Map<String, Object> after = picker.getColumns(rowChangedEvent.getAfterData());
-                    if (picker.filter(StringUtils.equals(ConnectorConstant.OPERTION_DELETE, rowChangedEvent.getEvent()) ? before : after)) {
+                    if (picker.filter(StringUtil.equals(ConnectorConstant.OPERTION_DELETE, rowChangedEvent.getEvent()) ? before : after)) {
                         rowChangedEvent.setBefore(before);
                         rowChangedEvent.setAfter(after);
                         parser.execute(mapping, picker.getTableGroup(), rowChangedEvent);

+ 2 - 2
dbsyncer-manager/src/main/java/org/dbsyncer/manager/template/impl/OperationTemplate.java

@@ -1,8 +1,8 @@
 package org.dbsyncer.manager.template.impl;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.cache.CacheService;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.manager.ManagerException;
 import org.dbsyncer.manager.config.OperationCallBack;
 import org.dbsyncer.manager.config.OperationConfig;
@@ -64,7 +64,7 @@ public final class OperationTemplate extends AbstractTemplate {
     }
 
     public <T> T queryObject(Class<T> clazz, String id) {
-        if (StringUtils.isBlank(id)) {
+        if (StringUtil.isBlank(id)) {
             return null;
         }
         Object o = cacheService.get(id, clazz);

+ 1 - 1
dbsyncer-monitor/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-monitor</artifactId>

+ 5 - 5
dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/MonitorFactory.java

@@ -1,8 +1,8 @@
 package org.dbsyncer.monitor;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.common.model.Paging;
 import org.dbsyncer.common.util.CollectionUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.constant.ConnectorConstant;
 import org.dbsyncer.manager.Manager;
 import org.dbsyncer.monitor.enums.MetricEnum;
@@ -75,17 +75,17 @@ public class MonitorFactory implements Monitor {
     @Override
     public Paging queryData(String id, int pageNum, int pageSize, String error, String success) {
         // 没有驱动
-        if (StringUtils.isBlank(id)) {
+        if (StringUtil.isBlank(id)) {
             return new Paging(pageNum, pageSize);
         }
 
         // 查询异常信息
         Query query = new Query(pageNum, pageSize);
-        if (StringUtils.isNotBlank(error)) {
+        if (StringUtil.isNotBlank(error)) {
             query.addFilter(ConfigConstant.DATA_ERROR, error, true);
         }
         // 查询是否成功, 默认查询失败
-        query.addFilter(ConfigConstant.DATA_SUCCESS, StringUtils.isNotBlank(success) ? success : StorageDataStatusEnum.FAIL.getCode(), false, true);
+        query.addFilter(ConfigConstant.DATA_SUCCESS, StringUtil.isNotBlank(success) ? success : StorageDataStatusEnum.FAIL.getCode(), false, true);
         return manager.queryData(query, id);
     }
 
@@ -97,7 +97,7 @@ public class MonitorFactory implements Monitor {
     @Override
     public Paging queryLog(int pageNum, int pageSize, String json) {
         Query query = new Query(pageNum, pageSize);
-        if (StringUtils.isNotBlank(json)) {
+        if (StringUtil.isNotBlank(json)) {
             query.addFilter(ConfigConstant.CONFIG_MODEL_JSON, json, true);
         }
         return manager.queryLog(query);

+ 2 - 2
dbsyncer-monitor/src/main/java/org/dbsyncer/monitor/enums/MetricEnum.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.monitor.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.ConnectorException;
 import org.dbsyncer.monitor.MonitorException;
 
@@ -60,7 +60,7 @@ public enum MetricEnum {
 
     public static MetricEnum getMetric(String code) throws ConnectorException {
         for (MetricEnum e : MetricEnum.values()) {
-            if (StringUtils.equals(code, e.getCode())) {
+            if (StringUtil.equals(code, e.getCode())) {
                 return e;
             }
         }

+ 1 - 1
dbsyncer-parser/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>dbsyncer</artifactId>
         <groupId>org.ghi</groupId>
-		<version>1.1.1-Alpha</version>
+		<version>1.1.2-Alpha</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>dbsyncer-parser</artifactId>

+ 8 - 6
dbsyncer-parser/src/main/java/org/dbsyncer/parser/ParserFactory.java

@@ -1,6 +1,5 @@
 package org.dbsyncer.parser;
 
-import org.apache.commons.lang.StringUtils;
 import org.dbsyncer.cache.CacheService;
 import org.dbsyncer.common.event.FullRefreshEvent;
 import org.dbsyncer.common.event.RowChangedEvent;
@@ -8,6 +7,7 @@ import org.dbsyncer.common.model.Result;
 import org.dbsyncer.common.model.Task;
 import org.dbsyncer.common.util.CollectionUtils;
 import org.dbsyncer.common.util.JsonUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.connector.ConnectorFactory;
 import org.dbsyncer.connector.ConnectorMapper;
 import org.dbsyncer.connector.config.*;
@@ -31,6 +31,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Component;
 import org.springframework.util.Assert;
@@ -64,6 +65,7 @@ public class ParserFactory implements Parser {
     private FlushService flushService;
 
     @Autowired
+    @Qualifier("taskExecutor")
     private Executor taskExecutor;
 
     @Autowired
@@ -231,7 +233,7 @@ public class ParserFactory implements Parser {
 
             // 1、获取数据源数据
             int pageIndex = Integer.parseInt(params.get(ParserEnum.PAGE_INDEX.getCode()));
-            Result reader = connectorFactory.reader(new ReaderConfig(sConnectionMapper, command, new ArrayList<>(), pageIndex, pageSize));
+            Result reader = connectorFactory.reader(sConnectionMapper, new ReaderConfig(command, new ArrayList<>(), pageIndex, pageSize));
             List<Map> data = reader.getData();
             if (CollectionUtils.isEmpty(data)) {
                 params.clear();
@@ -268,7 +270,7 @@ public class ParserFactory implements Parser {
         ConnectorMapper tConnectorMapper = connectorFactory.connect(getConnectorConfig(mapping.getTargetConnectorId()));
         // 1、获取映射字段
         final String event = rowChangedEvent.getEvent();
-        Map<String, Object> data = StringUtils.equals(ConnectorConstant.OPERTION_DELETE, event) ? rowChangedEvent.getBefore() : rowChangedEvent.getAfter();
+        Map<String, Object> data = StringUtil.equals(ConnectorConstant.OPERTION_DELETE, event) ? rowChangedEvent.getBefore() : rowChangedEvent.getAfter();
         Picker picker = new Picker(tableGroup.getFieldMapping(), data);
         Map target = picker.getTargetMap();
 
@@ -279,7 +281,7 @@ public class ParserFactory implements Parser {
         pluginFactory.convert(tableGroup.getPlugin(), event, data, target);
 
         // 4、写入目标源
-        Result writer = connectorFactory.writer(new WriterSingleConfig(tConnectorMapper, picker.getTargetFields(), tableGroup.getCommand(), event, target, rowChangedEvent.getTableName()));
+        Result writer = connectorFactory.writer(tConnectorMapper, new WriterSingleConfig(picker.getTargetFields(), tableGroup.getCommand(), event, target, rowChangedEvent.getTableName()));
 
         // 5、更新结果
         flush(metaId, writer, event, picker.getTargetMapList());
@@ -362,7 +364,7 @@ public class ParserFactory implements Parser {
         int total = target.size();
         // 单次任务
         if (total <= batchSize) {
-            return connectorFactory.writer(new WriterBatchConfig(connectorMapper, command, fields, target));
+            return connectorFactory.writer(connectorMapper, new WriterBatchConfig(command, fields, target));
         }
 
         // 批量任务, 拆分
@@ -406,7 +408,7 @@ public class ParserFactory implements Parser {
             }
             data.add(poll);
         }
-        return connectorFactory.writer(new WriterBatchConfig(connectorMapper, command, fields, data));
+        return connectorFactory.writer(connectorMapper, new WriterBatchConfig(command, fields, data));
     }
 
 }

+ 21 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/DateHandler.java

@@ -0,0 +1,21 @@
+package org.dbsyncer.parser.convert.handler;
+
+import org.dbsyncer.common.util.StringUtil;
+import org.dbsyncer.parser.convert.Handler;
+
+import java.util.Date;
+
+/**
+ * 系统日期
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2019/10/8 23:03
+ */
+public class DateHandler implements Handler {
+
+    @Override
+    public Object handle(String args, Object value) {
+        return null == value || StringUtil.isBlank(String.valueOf(value)) ? new Date() : value;
+    }
+}

+ 2 - 2
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/DefaultHandler.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.Handler;
 
 /**
@@ -14,6 +14,6 @@ public class DefaultHandler implements Handler {
 
     @Override
     public Object handle(String args, Object value) {
-        return null == value || StringUtils.isBlank(String.valueOf(value)) ? args : value;
+        return null == value || StringUtil.isBlank(String.valueOf(value)) ? args : value;
     }
 }

+ 25 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/LongToTimestampHandler.java

@@ -0,0 +1,25 @@
+package org.dbsyncer.parser.convert.handler;
+
+import org.dbsyncer.parser.convert.AbstractHandler;
+
+import java.sql.Timestamp;
+
+/**
+ * Long转Timestamp
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2021/9/2 23:04
+ */
+public class LongToTimestampHandler extends AbstractHandler {
+
+    @Override
+    public Object convert(String args, Object value) {
+        if (value instanceof Long) {
+            Long l = (Long) value;
+            value = new Timestamp(l);
+        }
+        return value;
+    }
+
+}

+ 2 - 2
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/RemStrFirstHandler.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.AbstractHandler;
 
 /**
@@ -14,6 +14,6 @@ public class RemStrFirstHandler extends AbstractHandler {
 
     @Override
     protected Object convert(String args, Object value) {
-        return StringUtils.substring(String.valueOf(value), 1);
+        return StringUtil.substring(String.valueOf(value), 1);
     }
 }

+ 2 - 2
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/RemStrLastHandler.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.AbstractHandler;
 
 /**
@@ -15,6 +15,6 @@ public class RemStrLastHandler extends AbstractHandler {
     @Override
     protected Object convert(String args, Object value) {
         String s = String.valueOf(value);
-        return StringUtils.substring(s, 0, s.length() - 1);
+        return StringUtil.substring(s, 0, s.length() - 1);
     }
 }

+ 3 - 3
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/ReplaceHandler.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.AbstractHandler;
 import org.springframework.util.Assert;
 
@@ -16,9 +16,9 @@ public class ReplaceHandler extends AbstractHandler {
     @Override
     protected Object convert(String args, Object value) {
         Assert.hasText(args, "缺少替换参数.");
-        String[] split = StringUtils.split(args, ",");
+        String[] split = StringUtil.split(args, ",");
         String a = split[0];
         String b = split.length == 2 ? split[1] : "";
-        return StringUtils.replace(String.valueOf(value), a, b);
+        return StringUtil.replace(String.valueOf(value), a, b);
     }
 }

+ 5 - 5
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/SubStrFirstHandler.java

@@ -1,7 +1,7 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
+import org.dbsyncer.common.util.NumberUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.AbstractHandler;
 import org.springframework.util.Assert;
 
@@ -16,9 +16,9 @@ public class SubStrFirstHandler extends AbstractHandler {
 
     @Override
     protected Object convert(String args, Object value) {
-        Assert.isTrue(NumberUtils.isNumber(args), "参数必须为正整数.");
+        Assert.isTrue(NumberUtil.isCreatable(args), "参数必须为正整数.");
         String s = String.valueOf(value);
-        int size = NumberUtils.toInt(args);
-        return StringUtils.substring(s, 0, size);
+        int size = NumberUtil.toInt(args);
+        return StringUtil.substring(s, 0, size);
     }
 }

+ 5 - 5
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/SubStrLastHandler.java

@@ -1,7 +1,7 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.math.NumberUtils;
+import org.dbsyncer.common.util.NumberUtil;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.AbstractHandler;
 import org.springframework.util.Assert;
 
@@ -16,10 +16,10 @@ public class SubStrLastHandler extends AbstractHandler {
 
     @Override
     protected Object convert(String args, Object value) {
-        Assert.isTrue(NumberUtils.isNumber(args), "参数必须为正整数.");
+        Assert.isTrue(NumberUtil.isCreatable(args), "参数必须为正整数.");
         String s = String.valueOf(value);
-        int size = NumberUtils.toInt(args);
+        int size = NumberUtil.toInt(args);
         int length = s.length();
-        return StringUtils.substring(s, length - size, length);
+        return StringUtil.substring(s, length - size, length);
     }
 }

+ 5 - 3
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/DefaultTimestampHandler.java → dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/TimestampHandler.java

@@ -1,20 +1,22 @@
 package org.dbsyncer.parser.convert.handler;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.convert.Handler;
 
 import java.sql.Timestamp;
 import java.time.Instant;
 
 /**
+ * 系统时间戳
+ *
  * @author AE86
  * @version 1.0.0
  * @date 2019/10/8 23:03
  */
-public class DefaultTimestampHandler implements Handler {
+public class TimestampHandler implements Handler {
 
     @Override
     public Object handle(String args, Object value) {
-        return null == value || StringUtils.isBlank(String.valueOf(value)) ? new Timestamp(Instant.now().toEpochMilli()) : value;
+        return null == value || StringUtil.isBlank(String.valueOf(value)) ? new Timestamp(Instant.now().toEpochMilli()) : value;
     }
 }

+ 27 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/TimestampToDateHandler.java

@@ -0,0 +1,27 @@
+package org.dbsyncer.parser.convert.handler;
+
+import org.dbsyncer.parser.convert.AbstractHandler;
+
+import java.sql.Timestamp;
+import java.time.ZoneId;
+import java.util.Date;
+
+/**
+ * 时间戳转日期
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2021/9/2 23:04
+ */
+public class TimestampToDateHandler extends AbstractHandler {
+
+    @Override
+    public Object convert(String args, Object value) {
+        if (value instanceof Timestamp) {
+            Timestamp t = (Timestamp) value;
+            value = Date.from(t.toLocalDateTime().atZone(ZoneId.systemDefault()).toInstant());
+        }
+        return value;
+    }
+
+}

+ 25 - 0
dbsyncer-parser/src/main/java/org/dbsyncer/parser/convert/handler/TimestampToLongHandler.java

@@ -0,0 +1,25 @@
+package org.dbsyncer.parser.convert.handler;
+
+import org.dbsyncer.parser.convert.AbstractHandler;
+
+import java.sql.Timestamp;
+
+/**
+ * Timestamp转Long
+ *
+ * @author AE86
+ * @version 1.0.0
+ * @date 2021/9/2 23:04
+ */
+public class TimestampToLongHandler extends AbstractHandler {
+
+    @Override
+    public Object convert(String args, Object value) {
+        if (value instanceof Timestamp) {
+            Timestamp t = (Timestamp) value;
+            value = t.getTime();
+        }
+        return value;
+    }
+
+}

+ 20 - 4
dbsyncer-parser/src/main/java/org/dbsyncer/parser/enums/ConvertEnum.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.parser.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.ParserException;
 import org.dbsyncer.parser.convert.Handler;
 import org.dbsyncer.parser.convert.handler.*;
@@ -19,9 +19,25 @@ public enum ConvertEnum {
      */
     DEFAULT("DEFAULT", "默认值", 1, new DefaultHandler()),
     /**
-     * 默认系统时间
+     * 系统时间
      */
-    DEFAULT_SYSTEM_TIMESTAMP("DEFAULT_SYSTEM_TIMESTAMP", "默认系统时间", 0, new DefaultTimestampHandler()),
+    SYSTEM_TIMESTAMP("SYSTEM_TIMESTAMP", "系统时间戳", 0, new TimestampHandler()),
+    /**
+     * 系统日期date
+     */
+    SYSTEM_DATE("SYSTEM_DATE", "系统日期", 0, new DateHandler()),
+    /**
+     * Timestamp转date
+     */
+    TIMESTAMP_TO_DATE("TIMESTAMP_TO_DATE", "Timestamp转date", 0, new TimestampToDateHandler()),
+    /**
+     * Timestamp转Long
+     */
+    TIMESTAMP_TO_LONG("TIMESTAMP_TO_LONG", "Timestamp转Long", 0, new TimestampToLongHandler()),
+    /**
+     * Long转Timestamp
+     */
+    LONG_TO_TIMESTAMP("LONG_TO_TIMESTAMP", "Long转Timestamp", 0, new LongToTimestampHandler()),
     /**
      * 替换
      */
@@ -89,7 +105,7 @@ public enum ConvertEnum {
 
     public static Handler getHandler(String code) throws ParserException {
         for (ConvertEnum e : ConvertEnum.values()) {
-            if (StringUtils.equals(code, e.getCode())) {
+            if (StringUtil.equals(code, e.getCode())) {
                 return e.getHandler();
             }
         }

+ 3 - 3
dbsyncer-parser/src/main/java/org/dbsyncer/parser/enums/ModelEnum.java

@@ -1,6 +1,6 @@
 package org.dbsyncer.parser.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.dbsyncer.common.util.StringUtil;
 import org.dbsyncer.parser.ParserException;
 
 /**
@@ -31,7 +31,7 @@ public enum ModelEnum {
 
     public static ModelEnum getModelEnum(String code) throws ParserException {
         for (ModelEnum e : ModelEnum.values()) {
-            if (StringUtils.equals(code, e.getCode())) {
+            if (StringUtil.equals(code, e.getCode())) {
                 return e;
             }
         }
@@ -39,7 +39,7 @@ public enum ModelEnum {
     }
 
     public static boolean isFull(String model) {
-        return StringUtils.equals(FULL.getCode(), model);
+        return StringUtil.equals(FULL.getCode(), model);
     }
 
     public String getCode() {

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.