You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by le...@apache.org on 2021/11/30 06:03:26 UTC

[dolphinscheduler] branch 2.0.1-prepare updated: [2.0.1-cherrypick] SPI(Task , Alert , DataSource) (#7041)

This is an automated email from the ASF dual-hosted git repository.

leonbao pushed a commit to branch 2.0.1-prepare
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/2.0.1-prepare by this push:
     new 2bf3b22  [2.0.1-cherrypick] SPI(Task ,Alert ,DataSource) (#7041)
2bf3b22 is described below

commit 2bf3b22d645f7bed248b313fddad5fefed0f91c1
Author: Kirs <ac...@163.com>
AuthorDate: Tue Nov 30 14:03:21 2021 +0800

    [2.0.1-cherrypick] SPI(Task ,Alert ,DataSource) (#7041)
    
    * data source spi
    
    * Fix datasource not work in tests and standalone server, and run all tests by default (#6743)
    
    * Refactor alert plugins and simplify its usage (#6723)
    
    * [Fix-6792] resolve API and alert port conflicts (#6792) (#6815)
    
    * [Fix-6792]Multiple ApplicationRunners on classpath make SpringApplication.run only run one (#6792)
    
    * [Feature][datasource] Change DataSource Connection Pool from Druid to HiKariCP (#6490) (#6828)
    
    * [Feature][datasource] Change DataSource Connection Pool from Druid to HiKariCP (#6490)
    
    * fix pom dep scope
    
    * filter alert
    
    * filter alert
    
    * filter alert
    
    * fix checkstyle
    
    * remove hikaricp version
    
    * update pom
    
    * add properties
    
    * add properties
    
    * rename properties
    
    * fix e2e fail
    
    * rename properties
    
    * [Fix-6792] resolve API and alert port conflicts (#6792) (#6815)
    
    [Fix-6792]Multiple ApplicationRunners on classpath make SpringApplication.run only run one (#6792)
    
    * fix ut fail
    
    * fix license
    
    * fix license
    
    * update package
    
    * update package
    
    * remove unused license
    
    Co-authored-by: mask <39...@users.noreply.github.com>
    Co-authored-by: kezhenxu94 <ke...@apache.org>
---
 .github/CODEOWNERS                                 |   1 +
 .github/workflows/unit-test.yml                    |   7 -
 .licenserc.yaml                                    |   2 +-
 .../conf/dolphinscheduler/alert.properties.tpl     |  30 -
 .../conf/dolphinscheduler/quartz.properties.tpl    |   2 +-
 docker/build/startup-init-conf.sh                  |   1 -
 docker/docker-swarm/config.env.sh                  |   1 -
 docker/kubernetes/dolphinscheduler/values.yaml     |   1 -
 .../dolphinscheduler-alert-dingtalk/pom.xml        |  82 ---
 .../dolphinscheduler-alert-email/pom.xml           | 115 ----
 .../alert/email/EmailAlertChannelFactory.java      | 140 ----
 .../plugin/alert/email/EmailAlertChannelTest.java  | 163 -----
 .../dolphinscheduler-alert-feishu/pom.xml          |  82 ---
 .../plugin/alert/http/HttpAlertChannelFactory.java |  78 ---
 .../plugin/alert/slack/SlackAlertPluginTest.java   |  36 -
 .../dolphinscheduler-alert-wechat/pom.xml          |  77 ---
 .../alert/wechat/WeChatAlertChannelFactory.java    |  94 ---
 .../dolphinscheduler-alert-api/pom.xml             |  38 ++
 .../dolphinscheduler/alert/api/AlertChannel.java   |  30 +-
 .../alert/api/AlertChannelFactory.java             |  37 +-
 .../dolphinscheduler/alert/api/AlertConstants.java |  33 +-
 .../dolphinscheduler/alert/api/AlertData.java      | 168 +++++
 .../dolphinscheduler/alert/api/AlertInfo.java      | 125 ++++
 .../dolphinscheduler/alert/api/AlertResult.java    | 123 ++++
 .../dolphinscheduler/alert/api/ShowType.java       |  49 +-
 .../dolphinscheduler-alert-dingtalk}/pom.xml       |  27 +-
 .../alert/dingtalk/DingTalkAlertChannel.java       |  14 +-
 .../dingtalk/DingTalkAlertChannelFactory.java      |  74 +-
 .../alert/dingtalk/DingTalkParamsConstants.java    |  30 +-
 .../plugin/alert/dingtalk/DingTalkSender.java      |  82 ++-
 .../dingtalk/DingTalkAlertChannelFactoryTest.java  |  10 +-
 .../plugin/alert/dingtalk/DingTalkSenderTest.java  |   9 +-
 .../dolphinscheduler-alert-email}/pom.xml          |  32 +-
 .../plugin/alert/email/EmailAlertChannel.java      |  25 +-
 .../alert/email/EmailAlertChannelFactory.java      | 139 ++++
 .../plugin/alert/email/EmailConstants.java         |  49 +-
 .../plugin/alert/email/ExcelUtils.java             |  18 +-
 .../plugin/alert/email/MailParamsConstants.java    |  36 +-
 .../plugin/alert/email/MailSender.java             | 133 ++--
 .../alert/email/exception/AlertEmailException.java |  12 -
 .../plugin/alert/email/template/AlertTemplate.java |  11 +-
 .../alert/email/template/DefaultHTMLTemplate.java  |   7 +-
 .../alert/email/EmailAlertChannelFactoryTest.java  |  17 +-
 .../plugin/alert/email/EmailAlertChannelTest.java  | 156 +++++
 .../plugin/alert/email/ExcelUtilsTest.java         |   0
 .../plugin/alert/email/MailUtilsTest.java          |  50 +-
 .../email/template/DefaultHTMLTemplateTest.java    |  33 +-
 .../dolphinscheduler-alert-feishu}/pom.xml         |  26 +-
 .../plugin/alert/feishu/FeiShuAlertChannel.java    |  11 +-
 .../alert/feishu/FeiShuAlertChannelFactory.java    |  67 +-
 .../plugin/alert/feishu/FeiShuParamsConstants.java |  36 +-
 .../plugin/alert/feishu/FeiShuSender.java          |  91 ++-
 .../plugin/alert/feishu/HttpRequestUtil.java       |   5 +-
 .../feishu/FeiShuAlertChannelFactoryTest.java      |   4 +-
 .../plugin/alert/feishu/FeiShuSenderTest.java      |  40 +-
 .../dolphinscheduler-alert-http}/pom.xml           |  31 +-
 .../plugin/alert/http/HttpAlertChannel.java        |  14 +-
 .../plugin/alert/http/HttpAlertChannelFactory.java |  78 +++
 .../plugin/alert/http/HttpAlertConstants.java      |  25 +-
 .../plugin/alert/http/HttpSender.java              |  60 +-
 .../alert/http/HttpAlertChannelFactoryTest.java    |   7 +-
 .../plugin/alert/http/HttpAlertChannelTest.java    |  41 +-
 .../plugin/alert/http/HttpSenderTest.java          |  21 +-
 .../dolphinscheduler-alert-script}/pom.xml         |  26 +-
 .../plugin/alert/script/OSUtils.java               |   8 +-
 .../plugin/alert/script/ProcessUtils.java          |  13 +-
 .../plugin/alert/script/ScriptAlertChannel.java    |  16 +-
 .../alert/script/ScriptAlertChannelFactory.java    |  48 +-
 .../plugin/alert/script/ScriptParamsConstants.java |  20 +-
 .../plugin/alert/script/ScriptSender.java          |  25 +-
 .../plugin/alert/script/ScriptType.java            |  13 +-
 .../plugin/alert/script/StreamGobbler.java         |  17 +-
 .../plugin/alert/script/ProcessUtilsTest.java      |   2 +-
 .../script/ScriptAlertChannelFactoryTest.java      |   4 +-
 .../plugin/alert/script/ScriptSenderTest.java      |   6 +-
 .../src/test/script/shell/scriptExample.sh         |   0
 .../src/test/script/shell/test.sh                  |   0
 .../dolphinscheduler-alert-slack}/pom.xml          |  27 +-
 .../plugin/alert/slack/SlackAlertChannel.java      |  14 +-
 .../alert/slack/SlackAlertChannelFactory.java      |  37 +-
 .../plugin/alert/slack/SlackParamsConstants.java   |  15 +-
 .../plugin/alert/slack/SlackSender.java            |  25 +-
 .../alert/slack/SlackAlertChannelFactoryTest.java  |   8 +-
 .../plugin/alert/slack/SlackSenderTest.java        |   4 +-
 .../dolphinscheduler-alert-wechat}/pom.xml         |  36 +-
 .../plugin/alert/wechat/WeChatAlertChannel.java    |  14 +-
 .../alert/wechat/WeChatAlertChannelFactory.java    |  93 +++
 .../plugin/alert/wechat/WeChatAlertConstants.java  |  14 +-
 .../alert/wechat/WeChatAlertParamsConstants.java   |  42 +-
 .../plugin/alert/wechat/WeChatSender.java          | 286 ++++----
 .../wechat/WeChatAlertChannelFactoryTest.java      |   4 +-
 .../plugin/alert/wechat/WeChatSenderTest.java      |  57 +-
 .../dolphinscheduler-alert-plugins}/pom.xml        |  14 +-
 .../{ => dolphinscheduler-alert-server}/pom.xml    |  91 +--
 .../dolphinscheduler/alert/AlertPluginManager.java |  89 +++
 .../alert}/AlertRequestProcessor.java              |  39 +-
 .../dolphinscheduler/alert}/AlertSender.java       |  83 +--
 .../apache/dolphinscheduler/alert/AlertServer.java | 125 ++++
 .../src/main/resources/logback-alert.xml           |   4 +-
 .../alert/plugin/EmailAlertPluginTest.java         | 174 +++--
 .../alert/processor/AlertRequestProcessorTest.java |  20 +-
 .../alert/runner/AlertSenderTest.java              |  85 +--
 dolphinscheduler-alert/pom.xml                     | 129 +---
 .../apache/dolphinscheduler/alert/AlertServer.java | 156 -----
 .../alert/plugin/AlertPluginManager.java           | 115 ----
 .../dolphinscheduler/alert/utils/Constants.java    |  38 --
 .../dolphinscheduler/alert/AlertServerTest.java    |  91 ---
 .../alert/plugin/AlertPluginManagerTest.java       |  67 --
 .../alert/plugin/DolphinPluginLoaderTest.java      |  55 --
 .../alert/utils/PropertyUtilsTest.java             | 221 ------
 dolphinscheduler-api/pom.xml                       |  45 +-
 .../dolphinscheduler/api/ApiApplicationServer.java |  16 +-
 .../api/controller/DataSourceController.java       |   8 +-
 .../api/service/DataSourceService.java             |   6 +-
 .../api/service/impl/DataSourceServiceImpl.java    |  13 +-
 .../dolphinscheduler/api/HttpClientTest.java       | 157 -----
 .../api/controller/AbstractControllerTest.java     |  34 +-
 .../api/controller/DataSourceControllerTest.java   |   2 +-
 .../api/controller/EnvironmentControllerTest.java  |   7 +-
 .../api/security/SecurityConfigLDAPTest.java~dev   |  45 --
 .../security/impl/ldap/LdapAuthenticatorTest.java  |   1 +
 .../api/security/impl/ldap/LdapServiceTest.java    |   7 +-
 .../impl/pwd/PasswordAuthenticatorTest.java        |   1 +
 .../api/service/DataAnalysisServiceTest.java       |  38 +-
 .../api/service/DataSourceServiceTest.java         |  48 +-
 .../api/service/MonitorServiceTest.java            |   2 +-
 dolphinscheduler-common/pom.xml                    |  38 --
 .../apache/dolphinscheduler/common/Constants.java  |  68 +-
 .../datasource/BaseHdfsDatasourceParamDTO.java     |  61 --
 .../common/datasource/DatasourceProcessor.java     |  81 ---
 .../clickhouse/ClickHouseDatasourceParamDTO.java   |  41 --
 .../datasource/db2/Db2DatasourceParamDTO.java      |  43 --
 .../datasource/hive/HiveConnectionParam.java       |  38 --
 .../datasource/hive/HiveDataSourceParamDTO.java    |  45 --
 .../datasource/mysql/MysqlConnectionParam.java     |  34 -
 .../datasource/mysql/MysqlDatasourceParamDTO.java  |  43 --
 .../datasource/oracle/OracleConnectionParam.java   |  46 --
 .../oracle/OracleDatasourceParamDTO.java           |  55 --
 .../postgresql/PostgreSqlDatasourceParamDTO.java   |  41 --
 .../presto/PrestoDatasourceParamDTO.java           |  43 --
 .../datasource/spark/SparkDatasourceParamDTO.java  |  45 --
 .../sqlserver/SqlServerDatasourceParamDTO.java     |  43 --
 .../dolphinscheduler/common/enums/DbType.java      |  60 --
 .../dolphinscheduler/common/enums/ProfileType.java |  17 +-
 .../dolphinscheduler/common/utils/CommonUtils.java |   2 +-
 .../common/utils/PropertyUtils.java                |  57 +-
 .../src/main/resources/common.properties           |   3 +
 .../apache/dolphinscheduler/common/CommonTest.java |  46 --
 .../threadutils/ThreadPoolExecutorsTest.java       |   9 +-
 .../common/utils/CommonUtilsTest.java              |  76 +--
 .../common/utils/NetUtilsTest.java                 |  20 +-
 .../dolphinscheduler/common/utils/OSUtilsTest.java | 112 ---
 .../placeholder/TimePlaceholderUtilsTest.java      |   9 +-
 dolphinscheduler-dao/pom.xml                       |  81 +--
 .../org/apache/dolphinscheduler/dao/AlertDao.java  |  39 +-
 .../apache/dolphinscheduler/dao/DaoFactory.java    |   2 +-
 .../apache/dolphinscheduler/dao/MonitorDBDao.java  |  15 +-
 .../org/apache/dolphinscheduler/dao/PluginDao.java |  32 +-
 .../dao/datasource/ConnectionFactory.java          | 149 ----
 .../dao/datasource/SpringConnectionFactory.java    | 141 ++--
 .../dolphinscheduler/dao/entity/DataSource.java    |   9 +-
 .../dolphinscheduler/dao/entity/MonitorRecord.java |   5 +-
 .../dao/mapper/PluginDefineMapper.java             |   6 +-
 .../dao/upgrade/DolphinSchedulerManager.java       |  91 +--
 .../dao/upgrade/MysqlUpgradeDao.java               |  30 +-
 .../dao/upgrade/PostgresqlUpgradeDao.java          |  60 +-
 .../dolphinscheduler/dao/upgrade/UpgradeDao.java   | 254 ++-----
 .../dao/upgrade/shell/CreateDolphinScheduler.java  |  60 +-
 .../dao/upgrade/shell/InitDolphinScheduler.java    |  49 +-
 .../dao/upgrade/shell/UpgradeDolphinScheduler.java |  56 +-
 .../dao/utils/MysqlPerformance.java                |   9 +-
 .../dao/utils/PostgrePerformance.java              |   8 +-
 .../mysql/dolphinscheduler_ddl.sql                 |   0
 .../mysql/dolphinscheduler_dml.sql                 |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../main/resources/sql}/dolphinscheduler_h2.sql    |   0
 .../main/resources/sql}/dolphinscheduler_mysql.sql |   0
 .../resources/sql}/dolphinscheduler_postgre.sql    |   0
 .../src/main/resources/sql}/soft_version           |   0
 .../1.0.1_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.0.1_schema/mysql}/dolphinscheduler_dml.sql   |   0
 .../1.0.2_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.0.2_schema/mysql/dolphinscheduler_dml.sql    |   0
 .../1.1.0_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.1.0_schema}/mysql/dolphinscheduler_dml.sql   |   0
 .../1.2.0_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.2.0_schema/mysql/dolphinscheduler_dml.sql    |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../1.3.0_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.3.0_schema/mysql/dolphinscheduler_dml.sql    |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../1.3.2_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.3.2_schema/mysql/dolphinscheduler_dml.sql    |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../1.3.3_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.3.3_schema}/mysql/dolphinscheduler_dml.sql   |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../1.3.5_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.3.5_schema}/mysql/dolphinscheduler_dml.sql   |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../1.3.6_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.3.6_schema}/mysql/dolphinscheduler_dml.sql   |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../1.3.7_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../1.3.7_schema}/mysql/dolphinscheduler_dml.sql   |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_dml.sql            |   0
 .../2.0.0_schema/mysql/dolphinscheduler_ddl.sql    |   0
 .../mysql/dolphinscheduler_ddl_post.sql            |   0
 .../2.0.0_schema}/mysql/dolphinscheduler_dml.sql   |   0
 .../postgresql/dolphinscheduler_ddl.sql            |   0
 .../postgresql/dolphinscheduler_ddl_post.sql       |   0
 .../postgresql}/dolphinscheduler_dml.sql           |   0
 .../apache/dolphinscheduler/dao/AlertDaoTest.java  |  30 +-
 .../apache/dolphinscheduler/dao/BaseDaoTest.java   |  31 +-
 .../dao/mapper/DataSourceMapperTest.java           |   2 +-
 .../dao/mapper/PluginDefineTest.java               |  26 +-
 .../dao/upgrade/ProcessDefinitionDaoTest.java      |  13 +-
 .../dao/upgrade/WorkerGroupDaoTest.java            |  21 +-
 .../dolphinscheduler-datasource-all}/pom.xml       |  38 +-
 .../dolphinscheduler-datasource-api/pom.xml        | 153 +++++
 .../api/client/CommonDataSourceClient.java         | 128 ++++
 .../datasource/AbstractDatasourceProcessor.java    |  12 +-
 .../api}/datasource/BaseDataSourceParamDTO.java    |  24 +-
 .../api}/datasource/BaseHdfsConnectionParam.java   |   4 +-
 .../datasource/BaseHdfsDatasourceParamDTO.java     |   2 +-
 .../api}/datasource/DatasourceProcessor.java       |  14 +-
 .../clickhouse/ClickHouseDatasourceParamDTO.java   |   4 +-
 .../clickhouse/ClickHouseDatasourceProcessor.java  |  30 +-
 .../clickhouse/ClickhouseConnectionParam.java      |   7 +-
 .../api}/datasource/db2/Db2ConnectionParam.java    |   7 +-
 .../api}/datasource/db2/Db2DatasourceParamDTO.java |   4 +-
 .../datasource/db2/Db2DatasourceProcessor.java     |  34 +-
 .../api}/datasource/hive/HiveConnectionParam.java  |   7 +-
 .../datasource/hive/HiveDataSourceParamDTO.java    |   4 +-
 .../datasource/hive/HiveDatasourceProcessor.java   |  42 +-
 .../datasource/mysql/MysqlConnectionParam.java     |   8 +-
 .../datasource/mysql/MysqlDatasourceParamDTO.java  |   4 +-
 .../datasource/mysql/MysqlDatasourceProcessor.java |  36 +-
 .../datasource/oracle/OracleConnectionParam.java   |   8 +-
 .../oracle/OracleDatasourceParamDTO.java           |   4 +-
 .../oracle/OracleDatasourceProcessor.java          |  34 +-
 .../postgresql/PostgreSqlConnectionParam.java      |   7 +-
 .../postgresql/PostgreSqlDatasourceParamDTO.java   |   4 +-
 .../postgresql/PostgreSqlDatasourceProcessor.java  |  30 +-
 .../datasource/presto/PrestoConnectionParam.java   |   7 +-
 .../presto/PrestoDatasourceParamDTO.java           |   4 +-
 .../presto/PrestoDatasourceProcessor.java          |  30 +-
 .../datasource/spark/SparkConnectionParam.java     |   7 +-
 .../datasource/spark/SparkDatasourceParamDTO.java  |   4 +-
 .../datasource/spark/SparkDatasourceProcessor.java |  36 +-
 .../sqlserver/SqlServerConnectionParam.java        |   7 +-
 .../sqlserver/SqlServerDatasourceParamDTO.java     |   4 +-
 .../sqlserver/SqlServerDatasourceProcessor.java    |  30 +-
 .../api/plugin/DataSourceClientProvider.java       |  73 ++
 .../api/plugin/DataSourcePluginManager.java        |  66 ++
 .../api/provider/JdbcDataSourceProvider.java       |  83 +++
 .../plugin/datasource/api/utils}/CommonUtils.java  |   5 +-
 .../datasource/api/utils}/DatasourceUtil.java      |  43 +-
 .../datasource/api/utils}/PasswordUtils.java       |   2 +-
 .../api/client/CommonDataSourceClientTest.java     | 100 +++
 .../ClickHouseDatasourceProcessorTest.java         |  26 +-
 .../datasource/db2/Db2DatasourceProcessorTest.java |  25 +-
 .../hive/HiveDatasourceProcessorTest.java          |  31 +-
 .../mysql/MysqlDatasourceProcessorTest.java        |  40 +-
 .../oracle/OracleDatasourceProcessorTest.java      |  29 +-
 .../PostgreSqlDatasourceProcessorTest.java         |  27 +-
 .../presto/PrestoDatasourceProcessorTest.java      |  27 +-
 .../spark/SparkDatasourceProcessorTest.java        |  29 +-
 .../SqlServerDatasourceProcessorTest.java          |  29 +-
 .../api/provider/JdbcDataSourceProviderTest.java   |  52 ++
 .../datasource/api/utils/CommonUtilsTest.java      | 124 ++++
 .../datasource/api/utils}/DatasourceUtilTest.java  |  42 +-
 .../dolphinscheduler-datasource-clickhouse/pom.xml |  89 +++
 .../clickhouse/ClickhouseDataSourceChannel.java    |  18 +-
 .../ClickhouseDataSourceChannelFactory.java        |  23 +-
 .../clickhouse/ClickhouseDataSourceClient.java     |  20 +-
 .../ClickhouseDataSourceChannelFactoryTest.java    |  19 +-
 .../ClickhouseDataSourceChannelTest.java           |  43 ++
 .../dolphinscheduler-datasource-db2}/pom.xml       |  37 +-
 .../datasource/db2/DB2DataSourceChannel.java       |  19 +-
 .../db2/DB2DataSourceChannelFactory.java           |  24 +-
 .../plugin/datasource/db2/DB2DataSourceClient.java |  14 +-
 .../db2/DB2DataSourceChannelFactoryTest.java       |  24 +-
 .../datasource/db2/DB2DataSourceChannelTest.java   |  43 ++
 .../dolphinscheduler-datasource-hive}/pom.xml      | 120 +++-
 .../datasource/hive/HiveDataSourceChannel.java     |  18 +-
 .../hive/HiveDataSourceChannelFactory.java         |  23 +-
 .../datasource/hive/HiveDataSourceClient.java      | 112 +++
 .../plugin/datasource/utils/CommonUtil.java        |  65 ++
 .../hive/HiveDataSourceChannelFactoryTest.java     |  19 +-
 .../datasource/hive/HiveDataSourceChannelTest.java |  43 ++
 .../dolphinscheduler-datasource-mysql}/pom.xml     |  48 +-
 .../datasource/mysql/MysqlDataSourceChannel.java   |  18 +-
 .../mysql/MysqlDataSourceChannelFactory.java       |  23 +-
 .../datasource/mysql/MysqlDataSourceClient.java    |  14 +-
 .../mysql/MysqlDataSourceChannelFactoryTest.java   |  19 +-
 .../mysql/MysqlDataSourceChannelTest.java          |  43 ++
 .../dolphinscheduler-datasource-oracle}/pom.xml    |  37 +-
 .../datasource/oracle/OracleDataSourceChannel.java |  14 +-
 .../oracle/OracleDataSourceChannelFactory.java     |  23 +-
 .../datasource/oracle/OracleDataSourceClient.java  |  17 +-
 .../oracle/OracleDataSourceChannelFactoryTest.java |  19 +-
 .../oracle/OracleDataSourceChannelTest.java        |  43 ++
 .../pom.xml                                        |  50 +-
 .../postgresql/PostgresqlDataSourceChannel.java    |  18 +-
 .../PostgresqlDataSourceChannelFactory.java        |  23 +-
 .../postgresql/PostgresqlDataSourceClient.java     |  14 +-
 .../PostgresqlDataSourceChannelFactoryTest.java    |  19 +-
 .../PostgresqlDataSourceChannelTest.java           |  43 ++
 .../dolphinscheduler-datasource-sqlserver}/pom.xml |  64 +-
 .../sqlserver/SqlServerDataSourceChannel.java      |  17 +-
 .../SqlServerDataSourceChannelFactory.java         |  23 +-
 .../sqlserver/SqlserverDataSourceClient.java       |  14 +-
 .../SqlserverDataSourceChannelFactoryTest.java     |  19 +-
 .../sqlserver/SqlserverDataSourceChannelTest.java  |  43 ++
 .../pom.xml                                        |  32 +-
 dolphinscheduler-dist/pom.xml                      |  10 +-
 dolphinscheduler-dist/release-docs/LICENSE         | 147 ++--
 dolphinscheduler-dist/release-docs/NOTICE          |  47 --
 .../release-docs/licenses/LICENSE-LatencyUtils.txt |  38 ++
 .../release-docs/licenses/LICENSE-aether-api.txt   |  86 ---
 .../LICENSE-aether-connector-asynchttpclient.txt   |  86 ---
 .../licenses/LICENSE-aether-connector-file.txt     |  86 ---
 .../release-docs/licenses/LICENSE-aether-impl.txt  |  86 ---
 .../release-docs/licenses/LICENSE-aether-spi.txt   |  86 ---
 .../release-docs/licenses/LICENSE-aether-util.txt  |  86 ---
 .../release-docs/licenses/LICENSE-apache-el.txt    | 202 ------
 .../licenses/LICENSE-async-http-client.txt         |  13 -
 .../licenses/LICENSE-hamcrest-core.txt             |  27 -
 .../licenses/LICENSE-hibernate-validator.txt       | 203 ------
 .../licenses/LICENSE-javax.activation-api.txt      | 758 ---------------------
 .../licenses/LICENSE-javax.servlet-api.txt         | 263 -------
 .../licenses/LICENSE-jboss-logging.txt             | 202 ------
 .../release-docs/licenses/LICENSE-junit.txt        | 213 ------
 .../licenses/LICENSE-maven-aether-provider.txt     | 202 ------
 .../licenses/LICENSE-maven-artifact.txt            | 202 ------
 .../release-docs/licenses/LICENSE-maven-compat.txt | 202 ------
 .../release-docs/licenses/LICENSE-maven-core.txt   | 202 ------
 .../licenses/LICENSE-maven-embedder.txt            | 202 ------
 .../licenses/LICENSE-maven-model-builder.txt       | 202 ------
 .../release-docs/licenses/LICENSE-maven-model.txt  | 202 ------
 .../licenses/LICENSE-maven-plugin-api.txt          | 202 ------
 .../licenses/LICENSE-maven-repository-metadata.txt | 202 ------
 .../licenses/LICENSE-maven-settings-builder.txt    | 202 ------
 .../licenses/LICENSE-maven-settings.txt            | 202 ------
 .../licenses/LICENSE-plexus-cipher.txt             | 202 ------
 .../licenses/LICENSE-plexus-classworlds.txt        | 202 ------
 .../LICENSE-plexus-component-annotations.txt       | 202 ------
 .../licenses/LICENSE-plexus-container-default.txt  | 202 ------
 .../licenses/LICENSE-plexus-interpolation.txt      | 202 ------
 .../licenses/LICENSE-plexus-sec-dispatcher.txt     | 202 ------
 .../release-docs/licenses/LICENSE-plexus-utils.txt | 202 ------
 .../release-docs/licenses/LICENSE-resolver.txt     | 202 ------
 .../licenses/LICENSE-validation-api.txt            |   4 -
 .../licenses/LICENSE-wagon-provider-api.txt        | 202 ------
 .../release-docs/licenses/LICENSE-xmlbeans.txt     | 201 ------
 .../src/main/assembly/dolphinscheduler-bin.xml     |  54 +-
 .../src/main/provisio/dolphinscheduler.xml         |  98 ---
 .../dolphinscheduler/registry/api/Event.java       | 107 ++-
 .../dolphinscheduler-registry-zookeeper/pom.xml    |  13 -
 .../ZookeeperConnectionStateListener.java          |  11 +-
 dolphinscheduler-registry/pom.xml                  |  14 -
 dolphinscheduler-remote/pom.xml                    |  17 -
 dolphinscheduler-server/pom.xml                    | 115 ++--
 .../dolphinscheduler/server/log/LoggerServer.java  |   6 +-
 .../server/master/MasterServer.java                |  11 +-
 .../server/worker/WorkerServer.java                |  66 +-
 .../server/worker/plugin/TaskPluginManager.java    |  93 +--
 .../server/worker/runner/TaskExecuteThread.java    |  39 +-
 .../src/main/resources/config/install_config.conf  |   6 -
 .../server/master/WorkflowExecuteThreadTest.java   |  69 +-
 .../consumer/TaskPriorityQueueConsumerTest.java    |   2 +-
 .../runner/task/CommonTaskProcessorTest.java       |   2 +-
 dolphinscheduler-service/pom.xml                   |  65 +-
 ...Provider.java => HikariConnectionProvider.java} |  19 +-
 .../service/quartz/QuartzExecutors.java            |   2 +-
 .../src/main/resources/quartz.properties           |   2 +-
 dolphinscheduler-spi/pom.xml                       |  59 +-
 .../spi/DolphinSchedulerPlugin.java                |  52 --
 .../spi/alert/AlertChannelFactory.java             |  33 -
 .../dolphinscheduler/spi/alert/AlertData.java      |  77 ---
 .../dolphinscheduler/spi/alert/AlertInfo.java      |  52 --
 .../dolphinscheduler/spi/alert/AlertResult.java    |  49 --
 .../dolphinscheduler/spi/alert/ShowType.java       |  51 --
 .../spi/classloader/ThreadContextClassLoader.java  |  35 -
 .../spi}/datasource/BaseConnectionParam.java       |  58 +-
 .../spi}/datasource/ConnectionParam.java           |   2 +-
 .../DataSourceChannel.java}                        |  11 +-
 .../spi/datasource/DataSourceChannelFactory.java   |  16 +-
 .../DataSourceClient.java}                         |  13 +-
 .../apache/dolphinscheduler/spi/enums/DbType.java  |  36 +-
 .../spi/plugin/DolphinPluginClassLoader.java       | 140 ----
 .../spi/plugin/DolphinPluginDiscovery.java         | 150 ----
 .../spi/plugin/DolphinPluginLoader.java            | 211 ------
 .../spi/plugin/DolphinPluginManagerConfig.java     | 119 ----
 .../spi/task/AbstractParameters.java               |  19 +-
 .../dolphinscheduler/spi/task/TaskConstants.java   |   2 +-
 .../spi/utils/CollectionUtils.java                 | 152 -----
 .../dolphinscheduler/spi/utils/Constants.java      | 121 ++++
 .../dolphinscheduler/spi/utils/DateUtils.java      | 307 ---------
 .../dolphinscheduler/spi/utils/JSONUtils.java      |  72 --
 .../dolphinscheduler/spi/utils/PropertyUtils.java  | 120 +---
 .../dolphinscheduler/spi/utils/StringUtils.java    |  52 --
 dolphinscheduler-standalone-server/pom.xml         |   2 +-
 .../dolphinscheduler/server/StandaloneServer.java  |  96 +--
 .../src/main/resources/application-h2.properties   |  16 +-
 .../dolphinscheduler-task-api/pom.xml              |   7 +-
 .../datasource/AbstractDatasourceProcessor.java    |  79 ---
 .../task/datasource/BaseConnectionParam.java       | 108 ---
 .../task/datasource/BaseDataSourceParamDTO.java    | 161 -----
 .../task/datasource/BaseHdfsConnectionParam.java   |  57 --
 .../plugin/task/datasource/DatasourceUtil.java     |  94 ---
 .../plugin/task/datasource/HiveConfUtils.java      |  87 ---
 .../clickhouse/ClickHouseDatasourceProcessor.java  | 131 ----
 .../clickhouse/ClickhouseConnectionParam.java      |  34 -
 .../task/datasource/db2/Db2ConnectionParam.java    |  34 -
 .../datasource/db2/Db2DatasourceProcessor.java     | 132 ----
 .../datasource/hive/HiveDatasourceProcessor.java   | 192 ------
 .../datasource/mysql/MysqlDatasourceProcessor.java | 176 -----
 .../oracle/OracleDatasourceProcessor.java          | 149 ----
 .../postgresql/PostgreSqlConnectionParam.java      |  34 -
 .../postgresql/PostgreSqlDatasourceProcessor.java  | 132 ----
 .../datasource/presto/PrestoConnectionParam.java   |  34 -
 .../presto/PrestoDatasourceProcessor.java          | 134 ----
 .../datasource/spark/SparkConnectionParam.java     |  38 --
 .../datasource/spark/SparkDatasourceProcessor.java | 161 -----
 .../sqlserver/SqlServerConnectionParam.java        |  34 -
 .../sqlserver/SqlServerDatasourceProcessor.java    | 129 ----
 .../dolphinscheduler-task-datax/pom.xml            |  21 +-
 .../plugin/task/datax/DataxTask.java               |  11 +-
 .../plugin/task/datax/DataxTaskChannelFactory.java |   3 +
 .../plugin/task/datax/DataxTaskPlugin.java         |  31 -
 .../dolphinscheduler-task-flink/pom.xml            |  10 +-
 .../plugin/task/flink/FlinkTaskChannelFactory.java |   3 +
 .../plugin/task/flink/FlinkTaskPlugin.java         |  30 -
 .../dolphinscheduler-task-http/pom.xml             |  15 +-
 .../plugin/task/http/HttpTask.java                 |   2 +-
 .../plugin/task/http/HttpTaskChannelFactory.java   |   3 +
 .../plugin/task/http/HttpTaskPlugin.java           |  31 -
 .../dolphinscheduler-task-mr/pom.xml               |  12 +-
 .../task/mr/MapReduceTaskChannelFactory.java       |   3 +
 .../plugin/task/mr/MapReduceTaskPlugin.java        |  31 -
 .../dolphinscheduler-task-pigeon/pom.xml           |  33 +-
 .../plugin/task/pigeon/PigeonTask.java             |   4 +-
 .../task/pigeon/PigeonTaskChannelFactory.java      |   3 +
 .../plugin/task/pigeon/PigeonTaskPlugin.java       |  31 -
 .../dolphinscheduler-task-procedure/pom.xml        |  21 +-
 .../plugin/task/procedure/ProcedureTask.java       |  12 +-
 .../procedure/ProcedureTaskChannelFactory.java     |   3 +
 .../plugin/task/procedure/ProcedureTaskPlugin.java |  31 -
 .../dolphinscheduler-task-python/pom.xml           |  28 +-
 .../plugin/task/python/PythonCommandExecutor.java  | 205 ------
 .../plugin/task/python/PythonTask.java             |  77 ++-
 .../task/python/PythonTaskChannelFactory.java      |   3 +
 .../plugin/task/python/PythonTaskPlugin.java       |  31 -
 .../dolphinscheduler-task-shell/pom.xml            |  10 +-
 .../plugin/task/shell/ShellTaskChannelFactory.java |   3 +
 .../plugin/task/shell/ShellTaskPlugin.java         |  31 -
 .../dolphinscheduler-task-spark/pom.xml            |  10 +-
 .../plugin/task/spark/SparkTaskChannelFactory.java |   3 +
 .../plugin/task/spark/SparkTaskPlugin.java         |  31 -
 .../dolphinscheduler-task-sql/pom.xml              |  20 +-
 .../plugin/task/sql/SqlParameters.java             |   3 +-
 .../dolphinscheduler/plugin/task/sql/SqlTask.java  |  22 +-
 .../plugin/task/sql/SqlTaskChannelFactory.java     |   3 +
 .../plugin/task/sql/SqlTaskPlugin.java             |  31 -
 .../dolphinscheduler-task-sqoop/pom.xml            |  21 +-
 .../plugin/task/sqoop/SqoopTaskChannelFactory.java |   3 +
 .../plugin/task/sqoop/SqoopTaskPlugin.java         |  31 -
 .../task/sqoop/generator/CommonGenerator.java      |   3 +-
 .../generator/sources/MysqlSourceGenerator.java    |   6 +-
 .../generator/targets/MysqlTargetGenerator.java    |   6 +-
 dolphinscheduler-task-plugin/pom.xml               |   6 +-
 install.sh                                         |   3 -
 pom.xml                                            | 591 +++++++---------
 script/dolphinscheduler-daemon.sh                  |   9 +-
 tools/dependencies/known-dependencies.txt          | 138 ++--
 485 files changed, 6498 insertions(+), 18561 deletions(-)

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9def4be..ec6c33c 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -15,6 +15,7 @@
 # limitations under the License.
 #
 
+dolphinscheduler/dolphinscheduler-alert @kezhenxu94
 dolphinscheduler/dolphinscheduler-e2e @kezhenxu94
 dolphinscheduler/dolphinscheduler-registry @kezhenxu94
 dolphinscheduler/dolphinscheduler-standalone-server @kezhenxu94
diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml
index daf24fc..c20632d 100644
--- a/.github/workflows/unit-test.yml
+++ b/.github/workflows/unit-test.yml
@@ -55,13 +55,6 @@ jobs:
         with:
           path: ~/.m2/repository
           key: ${{ runner.os }}-maven
-      - name: Bootstrap database
-        run: |
-          sed -i "/image: bitnami\/postgresql/a\    ports:\n    - 5432:5432" $(pwd)/docker/docker-swarm/docker-compose.yml
-          sed -i "/image: bitnami\/zookeeper/a\    ports:\n    - 2181:2181" $(pwd)/docker/docker-swarm/docker-compose.yml
-          docker-compose -f $(pwd)/docker/docker-swarm/docker-compose.yml up -d dolphinscheduler-zookeeper dolphinscheduler-postgresql
-          until docker logs docker-swarm_dolphinscheduler-postgresql_1 2>&1 | grep 'listening on IPv4 address'; do echo "waiting for postgresql ready ..."; sleep 1; done
-          docker run --rm --network docker-swarm_dolphinscheduler -v $(pwd)/sql/dolphinscheduler_postgre.sql:/docker-entrypoint-initdb.d/dolphinscheduler_postgre.sql bitnami/postgresql:11.11.0 bash -c "PGPASSWORD=root psql -h docker-swarm_dolphinscheduler-postgresql_1 -U root -d dolphinscheduler -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/dolphinscheduler_postgre.sql"
 
       - name: Run Unit tests
         run: ./mvnw clean verify -B -Dmaven.test.skip=false
diff --git a/.licenserc.yaml b/.licenserc.yaml
index b82839b..aabeaf6 100644
--- a/.licenserc.yaml
+++ b/.licenserc.yaml
@@ -28,7 +28,7 @@ header:
     - dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/ScriptRunner.java
     - dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/CodeGenerateUtils.java
     - mvnw.cmd
-    - sql/soft_version
+    - dolphinscheduler-dao/src/main/resources/sql/soft_version
     - .mvn
     - .gitattributes
     - '**/licenses/**/LICENSE-*'
diff --git a/docker/build/conf/dolphinscheduler/alert.properties.tpl b/docker/build/conf/dolphinscheduler/alert.properties.tpl
deleted file mode 100644
index 1ff6fe7..0000000
--- a/docker/build/conf/dolphinscheduler/alert.properties.tpl
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-#This configuration file configures the configuration parameters related to the AlertServer.
-#These parameters are only related to the AlertServer, and it has nothing to do with the specific Alert Plugin.
-#eg : max retry num.
-#eg : Alert Server Listener port
-
-#alert.plugin.dir config the Alert Plugin dir . AlertServer while find and load the Alert Plugin Jar from this dir when deploy and start AlertServer on the server .
-alert.plugin.dir=${ALERT_PLUGIN_DIR}
-
-#maven.local.repository=/Users/gaojun/Documents/jianguoyun/localRepository
-
-#alert.plugin.binding config the Alert Plugin need be load when development and run in IDE
-#alert.plugin.binding=\
-#  ./dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml
diff --git a/docker/build/conf/dolphinscheduler/quartz.properties.tpl b/docker/build/conf/dolphinscheduler/quartz.properties.tpl
index 10f1812..45c61a6 100644
--- a/docker/build/conf/dolphinscheduler/quartz.properties.tpl
+++ b/docker/build/conf/dolphinscheduler/quartz.properties.tpl
@@ -51,4 +51,4 @@
 #============================================================================
 # Configure Datasources
 #============================================================================
-#org.quartz.dataSource.myDs.connectionProvider.class = org.apache.dolphinscheduler.service.quartz.DruidConnectionProvider
+#org.quartz.dataSource.myDs.connectionProvider.class = org.apache.dolphinscheduler.service.quartz.HikariConnectionProvider
diff --git a/docker/build/startup-init-conf.sh b/docker/build/startup-init-conf.sh
index 4717834..23f5cff 100755
--- a/docker/build/startup-init-conf.sh
+++ b/docker/build/startup-init-conf.sh
@@ -107,7 +107,6 @@ export ALERT_LISTEN_HOST=${ALERT_LISTEN_HOST:-"localhost"}
 # Alert Server
 #============================================================================
 export ALERT_SERVER_OPTS=${ALERT_SERVER_OPTS:-"-Xms512m -Xmx512m -Xmn256m"}
-export ALERT_PLUGIN_DIR=${ALERT_PLUGIN_DIR:-"lib/plugin/alert"}
 
 #============================================================================
 # Api Server
diff --git a/docker/docker-swarm/config.env.sh b/docker/docker-swarm/config.env.sh
index 0c79a04..4127102 100755
--- a/docker/docker-swarm/config.env.sh
+++ b/docker/docker-swarm/config.env.sh
@@ -109,7 +109,6 @@ ALERT_LISTEN_HOST=dolphinscheduler-alert
 # Alert Server
 #============================================================================
 ALERT_SERVER_OPTS=-Xms512m -Xmx512m -Xmn256m
-ALERT_PLUGIN_DIR=lib/plugin/alert
 
 #============================================================================
 # Api Server
diff --git a/docker/kubernetes/dolphinscheduler/values.yaml b/docker/kubernetes/dolphinscheduler/values.yaml
index 4c90cc2..60ffedd 100644
--- a/docker/kubernetes/dolphinscheduler/values.yaml
+++ b/docker/kubernetes/dolphinscheduler/values.yaml
@@ -299,7 +299,6 @@ alert:
   ## Configmap
   configmap:
     ALERT_SERVER_OPTS: "-Xms512m -Xmx512m -Xmn256m"
-    ALERT_PLUGIN_DIR: "lib/plugin/alert"
   ## Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated.
   ## More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
   livenessProbe:
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml
deleted file mode 100644
index 96257e5..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/pom.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>dolphinscheduler-alert-plugin</artifactId>
-        <groupId>org.apache.dolphinscheduler</groupId>
-        <version>2.0.1-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.apache.dolphinscheduler</groupId>
-    <artifactId>dolphinscheduler-alert-dingtalk</artifactId>
-    <packaging>dolphinscheduler-plugin</packaging>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <type>jar</type>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>dolphinscheduler-alert-dingtalk-${project.version}</finalName>
-    </build>
-
-</project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml
deleted file mode 100644
index 9d008e5..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>dolphinscheduler-alert-plugin</artifactId>
-        <groupId>org.apache.dolphinscheduler</groupId>
-        <version>2.0.1-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.apache.dolphinscheduler</groupId>
-    <artifactId>dolphinscheduler-alert-email</artifactId>
-    <!-- can be load as a Alert Plugin when development and run server in IDE -->
-    <packaging>dolphinscheduler-plugin</packaging>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-collections4</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi-ooxml</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-email</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <type>jar</type>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-module-junit4</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-api-mockito2</artifactId>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.mockito</groupId>
-                    <artifactId>mockito-core</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>dolphinscheduler-alert-email-${project.version}</finalName>
-    </build>
-
-</project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java
deleted file mode 100644
index 2eefb49..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.plugin.alert.email;
-
-import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_FALSE;
-import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_NO;
-import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_TRUE;
-import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_YES;
-
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
-import org.apache.dolphinscheduler.spi.params.PasswordParam;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
-import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
-import org.apache.dolphinscheduler.spi.params.base.PluginParams;
-import org.apache.dolphinscheduler.spi.params.base.Validate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * email alert factory
- */
-public class EmailAlertChannelFactory implements AlertChannelFactory {
-    @Override
-    public String getName() {
-        return "Email";
-    }
-
-    @Override
-    public List<PluginParams> getParams() {
-
-        List<PluginParams> paramsList = new ArrayList<>();
-        InputParam receivesParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS)
-                .setPlaceholder("please input receives")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam receiveCcsParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERCCS)
-                .build();
-
-        InputParam mailSmtpHost = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_HOST, MailParamsConstants.MAIL_SMTP_HOST)
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        InputParam mailSmtpPort = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_PORT, MailParamsConstants.MAIL_SMTP_PORT)
-                .setValue("25")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam mailSender = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SENDER, MailParamsConstants.MAIL_SENDER)
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        RadioParam enableSmtpAuth = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_AUTH, MailParamsConstants.MAIL_SMTP_AUTH)
-                .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
-                .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
-                .setValue(STRING_TRUE)
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        InputParam mailUser = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_USER, MailParamsConstants.MAIL_USER)
-                .setPlaceholder("if enable use authentication, you need input user")
-                .build();
-
-        PasswordParam mailPassword = PasswordParam.newBuilder(MailParamsConstants.NAME_MAIL_PASSWD, MailParamsConstants.MAIL_PASSWD)
-                .setPlaceholder("if enable use authentication, you need input password")
-                .build();
-
-        RadioParam enableTls = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE)
-                .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
-                .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
-                .setValue(STRING_FALSE)
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        RadioParam enableSsl = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, MailParamsConstants.MAIL_SMTP_SSL_ENABLE)
-                .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
-                .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
-                .setValue(STRING_FALSE)
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        InputParam sslTrust = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, MailParamsConstants.MAIL_SMTP_SSL_TRUST)
-                .setValue("*")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE)
-                .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false))
-                .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false))
-                .addParamsOptions(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false))
-                .addParamsOptions(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false))
-                .setValue(ShowType.TABLE.getDescp())
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        paramsList.add(receivesParam);
-        paramsList.add(receiveCcsParam);
-        paramsList.add(mailSmtpHost);
-        paramsList.add(mailSmtpPort);
-        paramsList.add(mailSender);
-        paramsList.add(enableSmtpAuth);
-        paramsList.add(mailUser);
-        paramsList.add(mailPassword);
-        paramsList.add(enableTls);
-        paramsList.add(enableSsl);
-        paramsList.add(sslTrust);
-        paramsList.add(showType);
-
-        return paramsList;
-    }
-
-    @Override
-    public AlertChannel create() {
-        return new EmailAlertChannel();
-    }
-}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java
deleted file mode 100644
index 9a87709..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.plugin.alert.email;
-
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
-import org.apache.dolphinscheduler.spi.params.PasswordParam;
-import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
-import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
-import org.apache.dolphinscheduler.spi.params.base.PluginParams;
-import org.apache.dolphinscheduler.spi.params.base.Validate;
-import org.apache.dolphinscheduler.spi.utils.JSONUtils;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * EmailAlertChannel Tester.
- */
-public class EmailAlertChannelTest {
-
-    /**
-     * Method: process(AlertInfo info)
-     */
-    @Test
-    public void testProcess() {
-        EmailAlertChannel emailAlertChannel = new EmailAlertChannel();
-        AlertData alertData = new AlertData();
-        LinkedHashMap<String, Object> map1 = new LinkedHashMap<>();
-        map1.put("mysql service name", "mysql200");
-        map1.put("mysql address", "192.168.xx.xx");
-        map1.put("port", "3306");
-        map1.put("no index of number", "80");
-        map1.put("database client connections", "190");
-        List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
-        maps.add(0, map1);
-        String mapjson = JSONUtils.toJsonString(maps);
-
-        alertData.setId(10)
-                .setContent(mapjson)
-                .setLog("10")
-                .setTitle("test");
-        AlertInfo alertInfo = new AlertInfo();
-        alertInfo.setAlertData(alertData);
-        Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(getEmailAlertParams());
-
-        alertInfo.setAlertParams(paramsMap);
-        AlertResult alertResult = emailAlertChannel.process(alertInfo);
-        Assert.assertNotNull(alertResult);
-        Assert.assertEquals("false", alertResult.getStatus());
-    }
-
-    public String getEmailAlertParams() {
-        List<PluginParams> paramsList = new ArrayList<>();
-        InputParam receivesParam = InputParam.newBuilder("receivers", "receivers")
-                .setValue("540957506@qq.com")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        InputParam mailSmtpHost = InputParam.newBuilder("serverHost", "smtp.host")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("smtp.126.com")
-                .build();
-
-        InputParam mailSmtpPort = InputParam.newBuilder("serverPort", "smtp.port")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .setValue("25")
-                .build();
-
-        InputParam mailSender = InputParam.newBuilder("sender", "sender")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("dolphinscheduler@126.com")
-                .build();
-
-        RadioParam enableSmtpAuth = RadioParam.newBuilder("enableSmtpAuth", "smtp.auth")
-                .addParamsOptions(new ParamsOptions("YES", "true", false))
-                .addParamsOptions(new ParamsOptions("NO", "false", false))
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("false")
-                .build();
-
-        InputParam mailUser = InputParam.newBuilder("user", "user")
-                .setPlaceholder("if enable use authentication, you need input user")
-                .setValue("dolphinscheduler@126.com")
-                .build();
-
-        PasswordParam mailPassword = PasswordParam.newBuilder("passwd", "passwd")
-                .setPlaceholder("if enable use authentication, you need input password")
-                .setValue("escheduler123")
-                .build();
-
-        RadioParam enableTls = RadioParam.newBuilder("starttlsEnable", "starttls.enable")
-                .addParamsOptions(new ParamsOptions("YES", "true", false))
-                .addParamsOptions(new ParamsOptions("NO", "false", false))
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("true")
-                .build();
-
-        RadioParam enableSsl = RadioParam.newBuilder("sslEnable", "smtp.ssl.enable")
-                .addParamsOptions(new ParamsOptions("YES", "true", false))
-                .addParamsOptions(new ParamsOptions("NO", "false", false))
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("true")
-                .build();
-
-        InputParam sslTrust = InputParam.newBuilder("smtpSslTrust", "smtp.ssl.trust")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("smtp.126.com")
-                .build();
-
-        List<ParamsOptions> emailShowTypeList = new ArrayList<>();
-        emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false));
-        emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false));
-        emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false));
-        emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false));
-        RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, "showType")
-                .setOptions(emailShowTypeList)
-                .setValue(ShowType.TABLE.getDescp())
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        paramsList.add(receivesParam);
-        paramsList.add(mailSmtpHost);
-        paramsList.add(mailSmtpPort);
-        paramsList.add(mailSender);
-        paramsList.add(enableSmtpAuth);
-        paramsList.add(mailUser);
-        paramsList.add(mailPassword);
-        paramsList.add(enableTls);
-        paramsList.add(enableSsl);
-        paramsList.add(sslTrust);
-        paramsList.add(showType);
-
-        return JSONUtils.toJsonString(paramsList);
-    }
-}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/pom.xml
deleted file mode 100644
index d6238ab..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/pom.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>dolphinscheduler-alert-plugin</artifactId>
-        <groupId>org.apache.dolphinscheduler</groupId>
-        <version>2.0.1-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.apache.dolphinscheduler</groupId>
-    <artifactId>dolphinscheduler-alert-feishu</artifactId>
-    <packaging>dolphinscheduler-plugin</packaging>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <type>jar</type>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <finalName>dolphinscheduler-alert-feishu-${project.version}</finalName>
-    </build>
-
-</project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java
deleted file mode 100644
index d54885e..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.plugin.alert.http;
-
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
-import org.apache.dolphinscheduler.spi.params.base.PluginParams;
-import org.apache.dolphinscheduler.spi.params.base.Validate;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * http alert factory
- */
-public class HttpAlertChannelFactory implements AlertChannelFactory {
-    @Override
-    public String getName() {
-        return "Http";
-    }
-
-    @Override
-    public List<PluginParams> getParams() {
-
-        InputParam url = InputParam.newBuilder(HttpAlertConstants.URL, HttpAlertConstants.URL)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam headerParams = InputParam.newBuilder(HttpAlertConstants.HEADER_PARAMS, HttpAlertConstants.HEADER_PARAMS)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam bodyParams = InputParam.newBuilder(HttpAlertConstants.BODY_PARAMS, HttpAlertConstants.BODY_PARAMS)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam contentField = InputParam.newBuilder(HttpAlertConstants.CONTENT_FIELD, HttpAlertConstants.CONTENT_FIELD)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam requestType = InputParam.newBuilder(HttpAlertConstants.REQUEST_TYPE, HttpAlertConstants.REQUEST_TYPE)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        return Arrays.asList(url, requestType, headerParams, bodyParams, contentField);
-    }
-
-    @Override
-    public AlertChannel create() {
-        return new HttpAlertChannel();
-    }
-}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPluginTest.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPluginTest.java
deleted file mode 100644
index 5086352..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertPluginTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.plugin.alert.slack;
-
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class SlackAlertPluginTest {
-
-    private SlackAlertPlugin slackAlertPlugin = new SlackAlertPlugin();
-
-    @Test
-    public void testGetAlertChannelFactorys() {
-        Iterable<AlertChannelFactory> alertChannelFactorys = slackAlertPlugin.getAlertChannelFactorys();
-        for (AlertChannelFactory alertChannelFactory : alertChannelFactorys) {
-            Assert.assertTrue(alertChannelFactory instanceof SlackAlertChannelFactory);
-        }
-    }
-}
\ No newline at end of file
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml
deleted file mode 100644
index 8d8ad43..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/pom.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~     http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>dolphinscheduler-alert-plugin</artifactId>
-        <groupId>org.apache.dolphinscheduler</groupId>
-        <version>2.0.1-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.apache.dolphinscheduler</groupId>
-    <artifactId>dolphinscheduler-alert-wechat</artifactId>
-    <packaging>dolphinscheduler-plugin</packaging>
-     <dependencies>
-
-         <dependency>
-             <groupId>com.google.guava</groupId>
-             <artifactId>guava</artifactId>
-         </dependency>
-
-         <dependency>
-             <groupId>ch.qos.logback</groupId>
-             <artifactId>logback-classic</artifactId>
-         </dependency>
-
-         <dependency>
-             <groupId>org.apache.httpcomponents</groupId>
-             <artifactId>httpclient</artifactId>
-         </dependency>
-
-         <dependency>
-             <groupId>com.fasterxml.jackson.core</groupId>
-             <artifactId>jackson-databind</artifactId>
-             <scope>provided</scope>
-         </dependency>
-
-         <dependency>
-             <groupId>junit</groupId>
-             <artifactId>junit</artifactId>
-             <scope>test</scope>
-         </dependency>
-
-         <dependency>
-             <groupId>org.mockito</groupId>
-             <artifactId>mockito-core</artifactId>
-             <type>jar</type>
-             <scope>test</scope>
-         </dependency>
-
-         <dependency>
-             <groupId>org.jacoco</groupId>
-             <artifactId>org.jacoco.agent</artifactId>
-             <classifier>runtime</classifier>
-             <scope>test</scope>
-         </dependency>
-
-     </dependencies>
-
-    <build>
-        <finalName>dolphinscheduler-alert-wechat-${project.version}</finalName>
-    </build>
-</project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java b/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java
deleted file mode 100644
index 25b1318..0000000
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.plugin.alert.wechat;
-
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
-import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
-import org.apache.dolphinscheduler.spi.params.base.PluginParams;
-import org.apache.dolphinscheduler.spi.params.base.Validate;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * WeChatAlertChannelFactory
- */
-public class WeChatAlertChannelFactory implements AlertChannelFactory {
-
-    @Override
-    public String getName() {
-        return "WeChat";
-    }
-
-    @Override
-    public List<PluginParams> getParams() {
-        InputParam corpIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_CORP_ID)
-                .setPlaceholder("please input corp id ")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam secretParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_SECRET)
-                .setPlaceholder("please input secret ")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam usersParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USERS)
-                .setPlaceholder("please input users ")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam userSendMsgParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USER_SEND_MSG)
-                .setPlaceholder("please input corp id ")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        InputParam agentIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_AGENT_ID)
-                .setPlaceholder("please input agent id ")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
-
-        RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, AlertConstants.SHOW_TYPE)
-                .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false))
-                .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false))
-                .setValue(ShowType.TABLE.getDescp())
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
-
-        return Arrays.asList(corpIdParam, secretParam, usersParam, userSendMsgParam, agentIdParam, showType);
-    }
-
-    @Override
-    public AlertChannel create() {
-        return new WeChatAlertChannel();
-    }
-}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-api/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-api/pom.xml
new file mode 100644
index 0000000..c678bcd
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to Apache Software Foundation (ASF) under one or more contributor
+  ~ license agreements. See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright
+  ~ ownership. Apache Software Foundation (ASF) licenses this file to you under
+  ~ the Apache License, Version 2.0 (the "License"); you may
+  ~ not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dolphinscheduler-alert</artifactId>
+        <groupId>org.apache.dolphinscheduler</groupId>
+        <version>2.0.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>dolphinscheduler-alert-api</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-spi</artifactId> <!-- TODO should get rid off this -->
+        </dependency>
+    </dependencies>
+</project>
diff --git a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertChannel.java
similarity index 60%
copy from dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
copy to dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertChannel.java
index be781db..fceff92 100644
--- a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertChannel.java
@@ -17,32 +17,8 @@
  * under the License.
  */
 
-package org.apache.dolphinscheduler.registry.api;
+package org.apache.dolphinscheduler.alert.api;
 
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import lombok.experimental.Accessors;
-
-@Getter
-@Setter
-@Builder
-@ToString
-@NoArgsConstructor
-@AllArgsConstructor
-@Accessors(fluent = true)
-public class Event {
-    private String key;
-    private String path;
-    private String data;
-    private Type type;
-
-    public enum Type {
-        ADD,
-        REMOVE,
-        UPDATE
-    }
+public interface AlertChannel {
+    AlertResult process(AlertInfo info);
 }
diff --git a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertChannelFactory.java
similarity index 60%
copy from dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
copy to dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertChannelFactory.java
index be781db..a55c7ff 100644
--- a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertChannelFactory.java
@@ -17,32 +17,19 @@
  * under the License.
  */
 
-package org.apache.dolphinscheduler.registry.api;
+package org.apache.dolphinscheduler.alert.api;
 
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import lombok.experimental.Accessors;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 
-@Getter
-@Setter
-@Builder
-@ToString
-@NoArgsConstructor
-@AllArgsConstructor
-@Accessors(fluent = true)
-public class Event {
-    private String key;
-    private String path;
-    private String data;
-    private Type type;
+import java.util.List;
 
-    public enum Type {
-        ADD,
-        REMOVE,
-        UPDATE
-    }
+public interface AlertChannelFactory {
+    String name();
+
+    AlertChannel create();
+
+    /**
+     * Returns the configurable parameters that this plugin needs to display on the web ui
+     */
+    List<PluginParams> params();
 }
diff --git a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertConstants.java
similarity index 61%
copy from dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
copy to dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertConstants.java
index be781db..9d85fd2 100644
--- a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertConstants.java
@@ -17,32 +17,17 @@
  * under the License.
  */
 
-package org.apache.dolphinscheduler.registry.api;
+package org.apache.dolphinscheduler.alert.api;
 
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import lombok.experimental.Accessors;
+public final class AlertConstants {
+    /**
+     * the field name of alert show type
+     **/
+    public static final String SHOW_TYPE = "$t('showType')";
 
-@Getter
-@Setter
-@Builder
-@ToString
-@NoArgsConstructor
-@AllArgsConstructor
-@Accessors(fluent = true)
-public class Event {
-    private String key;
-    private String path;
-    private String data;
-    private Type type;
+    public static final String NAME_SHOW_TYPE = "showType";
 
-    public enum Type {
-        ADD,
-        REMOVE,
-        UPDATE
+    private AlertConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
     }
 }
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertData.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertData.java
new file mode 100644
index 0000000..9d1db84
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertData.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to Apache Software Foundation (ASF) under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Apache Software Foundation (ASF) licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dolphinscheduler.alert.api;
+
+public class AlertData {
+    private int id;
+    private String title;
+    private String content;
+    private String log;
+
+    public AlertData(int id, String title, String content, String log) {
+        this.id = id;
+        this.title = title;
+        this.content = content;
+        this.log = log;
+    }
+
+    public AlertData() {
+    }
+
+    public static AlertDataBuilder builder() {
+        return new AlertDataBuilder();
+    }
+
+    public int getId() {
+        return this.id;
+    }
+
+    public AlertData setId(int id) {
+        this.id = id;
+        return this;
+    }
+
+    public String getTitle() {
+        return this.title;
+    }
+
+    public AlertData setTitle(String title) {
+        this.title = title;
+        return this;
+    }
+
+    public String getContent() {
+        return this.content;
+    }
+
+    public AlertData setContent(String content) {
+        this.content = content;
+        return this;
+    }
+
+    public String getLog() {
+        return this.log;
+    }
+
+    public AlertData setLog(String log) {
+        this.log = log;
+        return this;
+    }
+
+    public boolean equals(final Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof AlertData)) {
+            return false;
+        }
+        final AlertData other = (AlertData) o;
+        if (!other.canEqual((Object) this)) {
+            return false;
+        }
+        if (this.getId() != other.getId()) {
+            return false;
+        }
+        final Object this$title = this.getTitle();
+        final Object other$title = other.getTitle();
+        if (this$title == null ? other$title != null : !this$title.equals(other$title)) {
+            return false;
+        }
+        final Object this$content = this.getContent();
+        final Object other$content = other.getContent();
+        if (this$content == null ? other$content != null : !this$content.equals(other$content)) {
+            return false;
+        }
+        final Object this$log = this.getLog();
+        final Object other$log = other.getLog();
+        if (this$log == null ? other$log != null : !this$log.equals(other$log)) {
+            return false;
+        }
+        return true;
+    }
+
+    protected boolean canEqual(final Object other) {
+        return other instanceof AlertData;
+    }
+
+    public int hashCode() {
+        final int PRIME = 59;
+        int result = 1;
+        result = result * PRIME + this.getId();
+        final Object $title = this.getTitle();
+        result = result * PRIME + ($title == null ? 43 : $title.hashCode());
+        final Object $content = this.getContent();
+        result = result * PRIME + ($content == null ? 43 : $content.hashCode());
+        final Object $log = this.getLog();
+        result = result * PRIME + ($log == null ? 43 : $log.hashCode());
+        return result;
+    }
+
+    public String toString() {
+        return "AlertData(id=" + this.getId() + ", title=" + this.getTitle() + ", content=" + this.getContent() + ", log=" + this.getLog() + ")";
+    }
+
+    public static class AlertDataBuilder {
+        private int id;
+        private String title;
+        private String content;
+        private String log;
+
+        AlertDataBuilder() {
+        }
+
+        public AlertDataBuilder id(int id) {
+            this.id = id;
+            return this;
+        }
+
+        public AlertDataBuilder title(String title) {
+            this.title = title;
+            return this;
+        }
+
+        public AlertDataBuilder content(String content) {
+            this.content = content;
+            return this;
+        }
+
+        public AlertDataBuilder log(String log) {
+            this.log = log;
+            return this;
+        }
+
+        public AlertData build() {
+            return new AlertData(id, title, content, log);
+        }
+
+        public String toString() {
+            return "AlertData.AlertDataBuilder(id=" + this.id + ", title=" + this.title + ", content=" + this.content + ", log=" + this.log + ")";
+        }
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertInfo.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertInfo.java
new file mode 100644
index 0000000..6dbc820
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertInfo.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to Apache Software Foundation (ASF) under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Apache Software Foundation (ASF) licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dolphinscheduler.alert.api;
+
+import java.util.Map;
+
+public class AlertInfo {
+    private Map<String, String> alertParams;
+    private AlertData alertData;
+
+    public AlertInfo(Map<String, String> alertParams, AlertData alertData) {
+        this.alertParams = alertParams;
+        this.alertData = alertData;
+    }
+
+    public AlertInfo() {
+    }
+
+    public static AlertInfoBuilder builder() {
+        return new AlertInfoBuilder();
+    }
+
+    public Map<String, String> getAlertParams() {
+        return this.alertParams;
+    }
+
+    public AlertInfo setAlertParams(Map<String, String> alertParams) {
+        this.alertParams = alertParams;
+        return this;
+    }
+
+    public AlertData getAlertData() {
+        return this.alertData;
+    }
+
+    public AlertInfo setAlertData(AlertData alertData) {
+        this.alertData = alertData;
+        return this;
+    }
+
+    public boolean equals(final Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof AlertInfo)) {
+            return false;
+        }
+        final AlertInfo other = (AlertInfo) o;
+        if (!other.canEqual((Object) this)) {
+            return false;
+        }
+        final Object this$alertParams = this.getAlertParams();
+        final Object other$alertParams = other.getAlertParams();
+        if (this$alertParams == null ? other$alertParams != null : !this$alertParams.equals(other$alertParams)) {
+            return false;
+        }
+        final Object this$alertData = this.getAlertData();
+        final Object other$alertData = other.getAlertData();
+        if (this$alertData == null ? other$alertData != null : !this$alertData.equals(other$alertData)) {
+            return false;
+        }
+        return true;
+    }
+
+    protected boolean canEqual(final Object other) {
+        return other instanceof AlertInfo;
+    }
+
+    public int hashCode() {
+        final int PRIME = 59;
+        int result = 1;
+        final Object $alertParams = this.getAlertParams();
+        result = result * PRIME + ($alertParams == null ? 43 : $alertParams.hashCode());
+        final Object $alertData = this.getAlertData();
+        result = result * PRIME + ($alertData == null ? 43 : $alertData.hashCode());
+        return result;
+    }
+
+    public String toString() {
+        return "AlertInfo(alertParams=" + this.getAlertParams() + ", alertData=" + this.getAlertData() + ")";
+    }
+
+    public static class AlertInfoBuilder {
+        private Map<String, String> alertParams;
+        private AlertData alertData;
+
+        AlertInfoBuilder() {
+        }
+
+        public AlertInfoBuilder alertParams(Map<String, String> alertParams) {
+            this.alertParams = alertParams;
+            return this;
+        }
+
+        public AlertInfoBuilder alertData(AlertData alertData) {
+            this.alertData = alertData;
+            return this;
+        }
+
+        public AlertInfo build() {
+            return new AlertInfo(alertParams, alertData);
+        }
+
+        public String toString() {
+            return "AlertInfo.AlertInfoBuilder(alertParams=" + this.alertParams + ", alertData=" + this.alertData + ")";
+        }
+    }
+}
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertResult.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertResult.java
new file mode 100644
index 0000000..4343c13
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/AlertResult.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to Apache Software Foundation (ASF) under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Apache Software Foundation (ASF) licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dolphinscheduler.alert.api;
+
+public class AlertResult {
+    private String status;
+    private String message;
+
+    public AlertResult(String status, String message) {
+        this.status = status;
+        this.message = message;
+    }
+
+    public AlertResult() {
+    }
+
+    public static AlertResultBuilder builder() {
+        return new AlertResultBuilder();
+    }
+
+    public String getStatus() {
+        return this.status;
+    }
+
+    public AlertResult setStatus(String status) {
+        this.status = status;
+        return this;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public AlertResult setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+
+    public boolean equals(final Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof AlertResult)) {
+            return false;
+        }
+        final AlertResult other = (AlertResult) o;
+        if (!other.canEqual((Object) this)) {
+            return false;
+        }
+        final Object this$status = this.getStatus();
+        final Object other$status = other.getStatus();
+        if (this$status == null ? other$status != null : !this$status.equals(other$status)) {
+            return false;
+        }
+        final Object this$message = this.getMessage();
+        final Object other$message = other.getMessage();
+        if (this$message == null ? other$message != null : !this$message.equals(other$message)) {
+            return false;
+        }
+        return true;
+    }
+
+    protected boolean canEqual(final Object other) {
+        return other instanceof AlertResult;
+    }
+
+    public int hashCode() {
+        final int PRIME = 59;
+        int result = 1;
+        final Object $status = this.getStatus();
+        result = result * PRIME + ($status == null ? 43 : $status.hashCode());
+        final Object $message = this.getMessage();
+        result = result * PRIME + ($message == null ? 43 : $message.hashCode());
+        return result;
+    }
+
+    public String toString() {
+        return "AlertResult(status=" + this.getStatus() + ", message=" + this.getMessage() + ")";
+    }
+
+    public static class AlertResultBuilder {
+        private String status;
+        private String message;
+
+        AlertResultBuilder() {
+        }
+
+        public AlertResultBuilder status(String status) {
+            this.status = status;
+            return this;
+        }
+
+        public AlertResultBuilder message(String message) {
+            this.message = message;
+            return this;
+        }
+
+        public AlertResult build() {
+            return new AlertResult(status, message);
+        }
+
+        public String toString() {
+            return "AlertResult.AlertResultBuilder(status=" + this.status + ", message=" + this.message + ")";
+        }
+    }
+}
diff --git a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/ShowType.java
similarity index 60%
copy from dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
copy to dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/ShowType.java
index be781db..48f9877 100644
--- a/dolphinscheduler-registry/dolphinscheduler-registry-api/src/main/java/org/apache/dolphinscheduler/registry/api/Event.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-api/src/main/java/org/apache/dolphinscheduler/alert/api/ShowType.java
@@ -17,32 +17,33 @@
  * under the License.
  */
 
-package org.apache.dolphinscheduler.registry.api;
+package org.apache.dolphinscheduler.alert.api;
 
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
-import lombok.experimental.Accessors;
+public enum ShowType {
+    /**
+     * 0 TABLE;
+     * 1 TEXT;
+     * 2 attachment;
+     * 3 TABLE+attachment;
+     */
+    TABLE(0, "table"),
+    TEXT(1, "text"),
+    ATTACHMENT(2, "attachment"),
+    TABLEATTACHMENT(3, "table attachment");
 
-@Getter
-@Setter
-@Builder
-@ToString
-@NoArgsConstructor
-@AllArgsConstructor
-@Accessors(fluent = true)
-public class Event {
-    private String key;
-    private String path;
-    private String data;
-    private Type type;
+    private final int code;
+    private final String descp;
 
-    public enum Type {
-        ADD,
-        REMOVE,
-        UPDATE
+    ShowType(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
     }
 }
diff --git a/dolphinscheduler-registry/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/pom.xml
similarity index 59%
copy from dolphinscheduler-registry/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/pom.xml
index ff6796c..6dd1cc1 100644
--- a/dolphinscheduler-registry/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/pom.xml
@@ -15,32 +15,27 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>dolphinscheduler-registry</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>dolphinscheduler-registry-api</module>
-        <module>dolphinscheduler-registry-plugins</module>
-    </modules>
+    <artifactId>dolphinscheduler-alert-dingtalk</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>com.google.auto.service</groupId>
-            <artifactId>auto-service</artifactId>
-            <optional>true</optional>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
         </dependency>
+
         <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.22</version>
-            <scope>provided</scope>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
     </dependencies>
 </project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
similarity index 80%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
index 6b13f24..74c440f 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannel.java
@@ -17,21 +17,17 @@
 
 package org.apache.dolphinscheduler.plugin.alert.dingtalk;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
-/**
- * DingTalkAlertChannel
- */
-public class DingTalkAlertChannel implements AlertChannel {
+public final class DingTalkAlertChannel implements AlertChannel {
 
     @Override
     public AlertResult process(AlertInfo alertInfo) {
-
         AlertData alertData = alertInfo.getAlertData();
         Map<String, String> paramsMap = alertInfo.getAlertParams();
         if (null == paramsMap) {
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
similarity index 57%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
index 61518b6..27d95e7 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactory.java
@@ -22,67 +22,67 @@ import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_NO;
 import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_TRUE;
 import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_YES;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
 import org.apache.dolphinscheduler.spi.params.PasswordParam;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
 import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
 
 import java.util.Arrays;
 import java.util.List;
 
-/**
- * DingTalkAlertChannelFactory
- */
-public class DingTalkAlertChannelFactory implements AlertChannelFactory {
+import com.google.auto.service.AutoService;
+
+@AutoService(AlertChannelFactory.class)
+public final class DingTalkAlertChannelFactory implements AlertChannelFactory {
     @Override
-    public String getName() {
+    public String name() {
         return "DingTalk";
     }
 
     @Override
-    public List<PluginParams> getParams() {
+    public List<PluginParams> params() {
         InputParam webHookParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_WEB_HOOK, DingTalkParamsConstants.DING_TALK_WEB_HOOK)
-            .addValidate(Validate.newBuilder()
-                .setRequired(true)
-                .build())
-            .build();
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
         InputParam keywordParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_KEYWORD, DingTalkParamsConstants.DING_TALK_KEYWORD)
-            .addValidate(Validate.newBuilder()
-                .setRequired(true)
-                .build())
-            .build();
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
         RadioParam isEnableProxy =
-            RadioParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE)
-                    .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
-                    .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
-                .setValue(STRING_TRUE)
-                .addValidate(Validate.newBuilder()
-                    .setRequired(false)
-                    .build())
-                .build();
+            RadioParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, DingTalkParamsConstants.DING_TALK_PROXY_ENABLE)
+                      .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
+                      .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
+                      .setValue(STRING_TRUE)
+                      .addValidate(Validate.newBuilder()
+                                           .setRequired(false)
+                                           .build())
+                      .build();
         InputParam proxyParam =
             InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PROXY, DingTalkParamsConstants.DING_TALK_PROXY)
-                .addValidate(Validate.newBuilder()
-                    .setRequired(false).build())
-                .build();
+                      .addValidate(Validate.newBuilder()
+                                           .setRequired(false).build())
+                      .build();
 
         InputParam portParam = InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PORT, DingTalkParamsConstants.DING_TALK_PORT)
-            .addValidate(Validate.newBuilder()
-                .setRequired(false).build())
-            .build();
+                                         .addValidate(Validate.newBuilder()
+                                                              .setRequired(false).build())
+                                         .build();
 
         InputParam userParam =
             InputParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_USER, DingTalkParamsConstants.DING_TALK_USER)
-                .addValidate(Validate.newBuilder()
-                    .setRequired(false).build())
-                .build();
+                      .addValidate(Validate.newBuilder()
+                                           .setRequired(false).build())
+                      .build();
         PasswordParam passwordParam = PasswordParam.newBuilder(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD, DingTalkParamsConstants.DING_TALK_PASSWORD)
-            .setPlaceholder("if enable use authentication, you need input password")
-            .build();
+                                                   .setPlaceholder("if enable use authentication, you need input password")
+                                                   .build();
 
         return Arrays.asList(webHookParam, keywordParam, isEnableProxy, proxyParam, portParam, userParam, passwordParam);
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
similarity index 69%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
index e94da80..ec0003a 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkParamsConstants.java
@@ -17,29 +17,29 @@
 
 package org.apache.dolphinscheduler.plugin.alert.dingtalk;
 
-/**
- * DingTalkParamsConstants
- */
-public class DingTalkParamsConstants {
-
+public final class DingTalkParamsConstants {
+    static final String DING_TALK_PROXY_ENABLE = "$t('isEnableProxy')";
+    static final String NAME_DING_TALK_PROXY_ENABLE = "IsEnableProxy";
 
-    static final String DING_TALK_PROXY_ENABLE = "isEnableProxy";
-    static final String DING_TALK_WEB_HOOK = "webhook";
+    static final String DING_TALK_WEB_HOOK = "$t('webhook')";
     static final String NAME_DING_TALK_WEB_HOOK = "WebHook";
-    static final String DING_TALK_KEYWORD = "keyword";
+
+    static final String DING_TALK_KEYWORD = "$t('keyword')";
     static final String NAME_DING_TALK_KEYWORD = "Keyword";
-    static final String NAME_DING_TALK_PROXY_ENABLE = "IsEnableProxy";
-    static final String DING_TALK_PROXY = "proxy";
+
+    static final String DING_TALK_PROXY = "$t('proxy')";
     static final String NAME_DING_TALK_PROXY = "Proxy";
-    static final String DING_TALK_PORT = "port";
+
+    static final String DING_TALK_PORT = "$t('port')";
     static final String NAME_DING_TALK_PORT = "Port";
-    static final String DING_TALK_USER = "user";
+
+    static final String DING_TALK_USER = "$t('user')";
     static final String NAME_DING_TALK_USER = "User";
-    static final String DING_TALK_PASSWORD = "password";
+
+    static final String DING_TALK_PASSWORD = "$t('password')";
     static final String NAME_DING_TALK_PASSWORD = "Password";
 
     private DingTalkParamsConstants() {
-        throw new IllegalStateException("Utility class");
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
     }
-
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
similarity index 72%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
index 0d87e47..a97fb00 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/main/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSender.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.dingtalk;
 
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
 import org.apache.commons.codec.binary.StringUtils;
@@ -36,23 +36,17 @@ import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * Ding Talk Sender
- */
-public class DingTalkSender {
-    private static final Logger logger = LoggerFactory.getLogger(DingTalkSender.class);
-
-    private String url;
-
-    private String keyword;
-
-    private Boolean enableProxy;
+public final class DingTalkSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(DingTalkSender.class);
+    private final String url;
+    private final String keyword;
+    private final Boolean enableProxy;
 
     private String proxy;
 
@@ -72,12 +66,11 @@ public class DingTalkSender {
             user = config.get(DingTalkParamsConstants.DING_TALK_USER);
             password = config.get(DingTalkParamsConstants.NAME_DING_TALK_PASSWORD);
         }
-
     }
 
-    private static HttpPost constructHttpPost(String url, String msg, String charset) {
+    private static HttpPost constructHttpPost(String url, String msg) {
         HttpPost post = new HttpPost(url);
-        StringEntity entity = new StringEntity(msg, charset);
+        StringEntity entity = new StringEntity(msg, StandardCharsets.UTF_8);
         post.setEntity(entity);
         post.addHeader("Content-Type", "application/json; charset=utf-8");
         return post;
@@ -116,13 +109,13 @@ public class DingTalkSender {
 
         if (null == result) {
             alertResult.setMessage("send ding talk msg error");
-            logger.info("send ding talk msg error,ding talk server resp is null");
+            log.info("send ding talk msg error,ding talk server resp is null");
             return alertResult;
         }
         DingTalkSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, DingTalkSendMsgResponse.class);
         if (null == sendMsgResponse) {
             alertResult.setMessage("send ding talk msg fail");
-            logger.info("send ding talk msg error,resp error");
+            log.info("send ding talk msg error,resp error");
             return alertResult;
         }
         if (sendMsgResponse.errcode == 0) {
@@ -131,7 +124,7 @@ public class DingTalkSender {
             return alertResult;
         }
         alertResult.setMessage(String.format("alert send ding talk msg error : %s", sendMsgResponse.getErrmsg()));
-        logger.info("alert send ding talk msg error : {}", sendMsgResponse.getErrmsg());
+        log.info("alert send ding talk msg error : {}", sendMsgResponse.getErrmsg());
         return alertResult;
     }
 
@@ -141,7 +134,7 @@ public class DingTalkSender {
             String resp = sendMsg(title, content);
             return checkSendDingTalkSendMsgResult(resp);
         } catch (Exception e) {
-            logger.info("send ding talk alert msg  exception : {}", e.getMessage());
+            log.info("send ding talk alert msg  exception : {}", e.getMessage());
             alertResult = new AlertResult();
             alertResult.setStatus("false");
             alertResult.setMessage("send ding talk alert fail.");
@@ -152,7 +145,7 @@ public class DingTalkSender {
     private String sendMsg(String title, String content) throws IOException {
 
         String msgToJson = textToJsonString(title + content + "#" + keyword);
-        HttpPost httpPost = constructHttpPost(url, msgToJson, "UTF-8");
+        HttpPost httpPost = constructHttpPost(url, msgToJson);
 
         CloseableHttpClient httpClient;
         if (Boolean.TRUE.equals(enableProxy)) {
@@ -173,19 +166,22 @@ public class DingTalkSender {
             } finally {
                 response.close();
             }
-            logger.info("Ding Talk send title :{},content : {}, resp: {}", title, content, resp);
+            log.info("Ding Talk send title :{},content : {}, resp: {}", title, content, resp);
             return resp;
         } finally {
             httpClient.close();
         }
     }
 
-    public static class DingTalkSendMsgResponse {
+    static final class DingTalkSendMsgResponse {
         private Integer errcode;
         private String errmsg;
 
+        public DingTalkSendMsgResponse() {
+        }
+
         public Integer getErrcode() {
-            return errcode;
+            return this.errcode;
         }
 
         public void setErrcode(Integer errcode) {
@@ -193,12 +189,46 @@ public class DingTalkSender {
         }
 
         public String getErrmsg() {
-            return errmsg;
+            return this.errmsg;
         }
 
         public void setErrmsg(String errmsg) {
             this.errmsg = errmsg;
         }
-    }
 
+        public boolean equals(final Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (!(o instanceof DingTalkSendMsgResponse)) {
+                return false;
+            }
+            final DingTalkSendMsgResponse other = (DingTalkSendMsgResponse) o;
+            final Object this$errcode = this.getErrcode();
+            final Object other$errcode = other.getErrcode();
+            if (this$errcode == null ? other$errcode != null : !this$errcode.equals(other$errcode)) {
+                return false;
+            }
+            final Object this$errmsg = this.getErrmsg();
+            final Object other$errmsg = other.getErrmsg();
+            if (this$errmsg == null ? other$errmsg != null : !this$errmsg.equals(other$errmsg)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            final int PRIME = 59;
+            int result = 1;
+            final Object $errcode = this.getErrcode();
+            result = result * PRIME + ($errcode == null ? 43 : $errcode.hashCode());
+            final Object $errmsg = this.getErrmsg();
+            result = result * PRIME + ($errmsg == null ? 43 : $errmsg.hashCode());
+            return result;
+        }
+
+        public String toString() {
+            return "DingTalkSender.DingTalkSendMsgResponse(errcode=" + this.getErrcode() + ", errmsg=" + this.getErrmsg() + ")";
+        }
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
similarity index 91%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
index 7c25f1e..8b78042 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkAlertChannelFactoryTest.java
@@ -17,26 +17,20 @@
 
 package org.apache.dolphinscheduler.plugin.alert.dingtalk;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
 import java.util.List;
 
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 
-/**
- * DingTalkAlertChannelFactoryTest
- */
-@Ignore
 public class DingTalkAlertChannelFactoryTest {
-
     @Test
     public void testGetParams() {
         DingTalkAlertChannelFactory dingTalkAlertChannelFactory = new DingTalkAlertChannelFactory();
-        List<PluginParams> params = dingTalkAlertChannelFactory.getParams();
+        List<PluginParams> params = dingTalkAlertChannelFactory.params();
         JSONUtils.toJsonString(params);
         Assert.assertEquals(7, params.size());
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
similarity index 90%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
index bc17d41..d2267a4 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-dingtalk/src/test/java/org/apache/dolphinscheduler/plugin/alert/dingtalk/DingTalkSenderTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.dingtalk;
 
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -26,12 +26,9 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-/**
- * DingTalkSenderTest
- */
 public class DingTalkSenderTest {
 
-    private static Map<String, String> dingTalkConfig = new HashMap<>();
+    private static final Map<String, String> dingTalkConfig = new HashMap<>();
 
     @Before
     public void initDingTalkConfig() {
@@ -51,7 +48,7 @@ public class DingTalkSenderTest {
         dingTalkConfig.put(DingTalkParamsConstants.NAME_DING_TALK_PROXY_ENABLE, "true");
         dingTalkSender = new DingTalkSender(dingTalkConfig);
         AlertResult alertResult = dingTalkSender.sendDingTalkMsg("title", "content test");
-        Assert.assertEquals("false",alertResult.getStatus());
+        Assert.assertEquals("false", alertResult.getStatus());
     }
 
 }
diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-shell/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/pom.xml
similarity index 59%
copy from dolphinscheduler-task-plugin/dolphinscheduler-task-shell/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/pom.xml
index e6f5fd4..07f959f 100644
--- a/dolphinscheduler-task-plugin/dolphinscheduler-task-shell/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/pom.xml
@@ -15,36 +15,36 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler-task-plugin</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>dolphinscheduler-task-shell</artifactId>
-    <packaging>dolphinscheduler-plugin</packaging>
+    <artifactId>dolphinscheduler-alert-email</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-spi</artifactId>
-            <scope>provided</scope>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-task-api</artifactId>
-            <version>${project.version}</version>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
 
         <dependency>
             <groupId>org.apache.commons</groupId>
-            <artifactId>commons-collections4</artifactId>
+            <artifactId>commons-email</artifactId>
         </dependency>
     </dependencies>
-
-    <build>
-        <finalName>dolphinscheduler-task-shell-${project.version}</finalName>
-    </build>
 </project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java
similarity index 71%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java
index 3dbf0b8..c5cdc33 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannel.java
@@ -17,21 +17,17 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * email alert channel . use email to seed the alertInfo
- */
-public class EmailAlertChannel implements AlertChannel {
-    private static final Logger logger = LoggerFactory.getLogger(EmailAlertChannel.class);
+public final class EmailAlertChannel implements AlertChannel {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(EmailAlertChannel.class);
 
     @Override
     public AlertResult process(AlertInfo info) {
@@ -44,25 +40,24 @@ public class EmailAlertChannel implements AlertChannel {
         MailSender mailSender = new MailSender(paramsMap);
         AlertResult alertResult = mailSender.sendMails(alert.getTitle(), alert.getContent());
 
-        //send flag
-        boolean flag = false;
+        boolean flag;
 
         if (alertResult == null) {
             alertResult = new AlertResult();
             alertResult.setStatus("false");
             alertResult.setMessage("alert send error.");
-            logger.info("alert send error : {}", alertResult.getMessage());
+            log.info("alert send error : {}", alertResult.getMessage());
             return alertResult;
         }
 
         flag = Boolean.parseBoolean(String.valueOf(alertResult.getStatus()));
 
         if (flag) {
-            logger.info("alert send success");
+            log.info("alert send success");
             alertResult.setMessage("email send success.");
         } else {
             alertResult.setMessage("alert send error.");
-            logger.info("alert send error : {}", alertResult.getMessage());
+            log.info("alert send error : {}", alertResult.getMessage());
         }
 
         return alertResult;
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java
new file mode 100644
index 0000000..a2c5261
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactory.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.email;
+
+import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_FALSE;
+import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_NO;
+import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_TRUE;
+import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_YES;
+
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.ShowType;
+import org.apache.dolphinscheduler.spi.params.PasswordParam;
+import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.auto.service.AutoService;
+
+@AutoService(AlertChannelFactory.class)
+public final class EmailAlertChannelFactory implements AlertChannelFactory {
+    @Override
+    public String name() {
+        return "Email";
+    }
+
+    @Override
+    public List<PluginParams> params() {
+        List<PluginParams> paramsList = new ArrayList<>();
+        InputParam receivesParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS)
+                                             .setPlaceholder("please input receives")
+                                             .addValidate(Validate.newBuilder()
+                                                                  .setRequired(true)
+                                                                  .build())
+                                             .build();
+
+        InputParam receiveCcsParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERCCS)
+                                               .build();
+
+        InputParam mailSmtpHost = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_HOST, MailParamsConstants.MAIL_SMTP_HOST)
+                                            .addValidate(Validate.newBuilder().setRequired(true).build())
+                                            .build();
+
+        InputParam mailSmtpPort = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_PORT, MailParamsConstants.MAIL_SMTP_PORT)
+                                            .setValue("25")
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
+
+        InputParam mailSender = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SENDER, MailParamsConstants.MAIL_SENDER)
+                                          .addValidate(Validate.newBuilder().setRequired(true).build())
+                                          .build();
+
+        RadioParam enableSmtpAuth = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_AUTH, MailParamsConstants.MAIL_SMTP_AUTH)
+                                              .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
+                                              .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
+                                              .setValue(STRING_TRUE)
+                                              .addValidate(Validate.newBuilder().setRequired(true).build())
+                                              .build();
+
+        InputParam mailUser = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_USER, MailParamsConstants.MAIL_USER)
+                                        .setPlaceholder("if enable use authentication, you need input user")
+                                        .build();
+
+        PasswordParam mailPassword = PasswordParam.newBuilder(MailParamsConstants.NAME_MAIL_PASSWD, MailParamsConstants.MAIL_PASSWD)
+                                                  .setPlaceholder("if enable use authentication, you need input password")
+                                                  .build();
+
+        RadioParam enableTls = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE)
+                                         .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
+                                         .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
+                                         .setValue(STRING_FALSE)
+                                         .addValidate(Validate.newBuilder().setRequired(true).build())
+                                         .build();
+
+        RadioParam enableSsl = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, MailParamsConstants.MAIL_SMTP_SSL_ENABLE)
+                                         .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
+                                         .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
+                                         .setValue(STRING_FALSE)
+                                         .addValidate(Validate.newBuilder().setRequired(true).build())
+                                         .build();
+
+        InputParam sslTrust = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, MailParamsConstants.MAIL_SMTP_SSL_TRUST)
+                                        .setValue("*")
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .build();
+
+        RadioParam showType = RadioParam.newBuilder(AlertConstants.NAME_SHOW_TYPE, AlertConstants.SHOW_TYPE)
+                                        .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false))
+                                        .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false))
+                                        .addParamsOptions(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false))
+                                        .addParamsOptions(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false))
+                                        .setValue(ShowType.TABLE.getDescp())
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .build();
+
+        paramsList.add(receivesParam);
+        paramsList.add(receiveCcsParam);
+        paramsList.add(mailSmtpHost);
+        paramsList.add(mailSmtpPort);
+        paramsList.add(mailSender);
+        paramsList.add(enableSmtpAuth);
+        paramsList.add(mailUser);
+        paramsList.add(mailPassword);
+        paramsList.add(enableTls);
+        paramsList.add(enableSsl);
+        paramsList.add(sslTrust);
+        paramsList.add(showType);
+
+        return paramsList;
+    }
+
+    @Override
+    public AlertChannel create() {
+        return new EmailAlertChannel();
+    }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java
similarity index 52%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java
index 5eecaa0..4c6e1d3 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/EmailConstants.java
@@ -17,19 +17,11 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email;
 
-public class EmailConstants {
-
-    private EmailConstants() {
-        throw new IllegalStateException(EmailConstants.class.getName());
-    }
-
-
+public final class EmailConstants {
     public static final String XLS_FILE_PATH = "xls.file.path";
 
     public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol";
 
-    public static final String DEFAULT_SMTP_PORT = "25";
-
     public static final String TEXT_HTML_CHARSET_UTF_8 = "text/html;charset=utf-8";
 
     public static final int NUMBER_1000 = 1000;
@@ -42,32 +34,23 @@ public class EmailConstants {
 
     public static final String TR_END = "</tr>";
 
-    public static final String TITLE = "title";
-
-    public static final String CONTENT = "content";
-
     public static final String TH = "<th>";
 
     public static final String TH_END = "</th>";
 
-    public static final String MARKDOWN_QUOTE = ">";
-
-    public static final String MARKDOWN_ENTER = "\n";
-
-    public static final String HTML_HEADER_PREFIX = new StringBuilder("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>")
-            .append("<html>")
-            .append("<head>")
-            .append("<title>dolphinscheduler</title>")
-            .append("<meta name='Keywords' content=''>")
-            .append("<meta name='Description' content=''>")
-            .append("<style type=\"text/css\">")
-            .append("table {margin-top:0px;padding-top:0px;border:1px solid;font-size: 14px;color: #333333;border-width: 1px;border-color: #666666;border-collapse: collapse;}")
-            .append("table th {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #dedede;text-align: left;}")
-            .append("table td {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #ffffff;text-align: left;}")
-            .append("</style>")
-            .append("</head>")
-            .append("<body style=\"margin:0;padding:0\"><table border=\"1px\" cellpadding=\"5px\" cellspacing=\"-10px\"> ")
-            .toString();
+    public static final String HTML_HEADER_PREFIX = "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>"
+        + "<html>"
+        + "<head>"
+        + "<title>dolphinscheduler</title>"
+        + "<meta name='Keywords' content=''>"
+        + "<meta name='Description' content=''>"
+        + "<style type=\"text/css\">"
+        + "table {margin-top:0px;padding-top:0px;border:1px solid;font-size: 14px;color: #333333;border-width: 1px;border-color: #666666;border-collapse: collapse;}"
+        + "table th {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #dedede;text-align: left;}"
+        + "table td {border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #ffffff;text-align: left;}"
+        + "</style>"
+        + "</head>"
+        + "<body style=\"margin:0;padding:0\"><table border=\"1px\" cellpadding=\"5px\" cellspacing=\"-10px\"> ";
 
     public static final String TABLE_BODY_HTML_TAIL = "</table></body></html>";
 
@@ -76,4 +59,8 @@ public class EmailConstants {
     public static final String EXCEL_SUFFIX_XLSX = ".xlsx";
 
     public static final String SINGLE_SLASH = "/";
+
+    private EmailConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java
similarity index 92%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java
index 90069c6..1986f1c 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtils.java
@@ -36,21 +36,15 @@ import java.util.List;
 import java.util.Map;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * excel utils
- */
-public class ExcelUtils {
+public final class ExcelUtils {
+    private static final int XLSX_WINDOW_ROW = 10000;
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(ExcelUtils.class);
 
     private ExcelUtils() {
-        throw new IllegalStateException("Utility class");
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
     }
 
-    private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
-
-    private static final int XLSX_WINDOW_ROW = 10000;
-
     /**
      * generate excel file
      *
@@ -61,14 +55,14 @@ public class ExcelUtils {
     public static void genExcelFile(String content, String title, String xlsFilePath) {
         File file = new File(xlsFilePath);
         if (!file.exists() && !file.mkdirs()) {
-            logger.error("Create xlsx directory error, path:{}", xlsFilePath);
+            log.error("Create xlsx directory error, path:{}", xlsFilePath);
             throw new AlertEmailException("Create xlsx directory error");
         }
 
         List<LinkedHashMap> itemsList = JSONUtils.toList(content, LinkedHashMap.class);
 
         if (CollectionUtils.isEmpty(itemsList)) {
-            logger.error("itemsList is null");
+            log.error("itemsList is null");
             throw new AlertEmailException("itemsList is null");
         }
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java
similarity index 66%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java
index 9b49b47..7bd75b8 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailParamsConstants.java
@@ -17,49 +17,43 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email;
 
-/**
- * mail plugin params json use
- */
-public class MailParamsConstants {
-
-    private MailParamsConstants() {
-        throw new IllegalStateException("Utility class");
-    }
-
+public final class MailParamsConstants {
     public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERS = "$t('receivers')";
     public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receivers";
 
     public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "$t('receiverCcs')";
     public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs";
 
-    public static final String MAIL_PROTOCOL = "transport.protocol";
     public static final String NAME_MAIL_PROTOCOL = "mail.protocol";
 
-    public static final String MAIL_SMTP_HOST = "mail.smtp.host";
+    public static final String MAIL_SMTP_HOST = "$t('mailSmtpHost')";
     public static final String NAME_MAIL_SMTP_HOST = "serverHost";
 
-    public static final String MAIL_SMTP_PORT = "mail.smtp.port";
+    public static final String MAIL_SMTP_PORT = "$t('mailSmtpPort')";
     public static final String NAME_MAIL_SMTP_PORT = "serverPort";
 
-    public static final String MAIL_SENDER = "mail.sender";
+    public static final String MAIL_SENDER = "$t('mailSender')";
     public static final String NAME_MAIL_SENDER = "sender";
 
-    public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
+    public static final String MAIL_SMTP_AUTH = "$t('mailSmtpAuth')";
     public static final String NAME_MAIL_SMTP_AUTH = "enableSmtpAuth";
 
-    public static final String MAIL_USER = "mail.user";
-    public static final String NAME_MAIL_USER = "user";
+    public static final String MAIL_USER = "$t('mailUser')";
+    public static final String NAME_MAIL_USER = "User";
 
-    public static final String MAIL_PASSWD = "mail.passwd";
-    public static final String NAME_MAIL_PASSWD = "passwd";
+    public static final String MAIL_PASSWD = "$t('mailPasswd')";
+    public static final String NAME_MAIL_PASSWD = "Password";
 
-    public static final String MAIL_SMTP_STARTTLS_ENABLE = "mail.smtp.starttls.enable";
+    public static final String MAIL_SMTP_STARTTLS_ENABLE = "$t('mailSmtpStarttlsEnable')";
     public static final String NAME_MAIL_SMTP_STARTTLS_ENABLE = "starttlsEnable";
 
-    public static final String MAIL_SMTP_SSL_ENABLE = "mail.smtp.ssl.enable";
+    public static final String MAIL_SMTP_SSL_ENABLE = "$t('mailSmtpSslEnable')";
     public static final String NAME_MAIL_SMTP_SSL_ENABLE = "sslEnable";
 
-    public static final String MAIL_SMTP_SSL_TRUST = "mail.smtp.ssl.trust";
+    public static final String MAIL_SMTP_SSL_TRUST = "$t('mailSmtpSslTrust')";
     public static final String NAME_MAIL_SMTP_SSL_TRUST = "smtpSslTrust";
 
+    private MailParamsConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java
similarity index 79%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java
index 33701de..ba8acab 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/MailSender.java
@@ -17,76 +17,53 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email;
 
-import static java.util.Objects.requireNonNull;
-
+import com.sun.mail.smtp.SMTPProvider;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.mail.EmailException;
+import org.apache.commons.mail.HtmlEmail;
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.apache.dolphinscheduler.plugin.alert.email.exception.AlertEmailException;
 import org.apache.dolphinscheduler.plugin.alert.email.template.AlertTemplate;
 import org.apache.dolphinscheduler.plugin.alert.email.template.DefaultHTMLTemplate;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
 import org.apache.dolphinscheduler.spi.utils.StringUtils;
-
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.mail.EmailException;
-import org.apache.commons.mail.HtmlEmail;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import org.slf4j.Logger;
 
 import javax.activation.CommandMap;
 import javax.activation.MailcapCommandMap;
-import javax.mail.Authenticator;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.PasswordAuthentication;
-import javax.mail.Session;
-import javax.mail.Transport;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeBodyPart;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMultipart;
-import javax.mail.internet.MimeUtility;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import javax.mail.*;
+import javax.mail.internet.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
 
-import com.sun.mail.smtp.SMTPProvider;
+import static java.util.Objects.requireNonNull;
 
-/**
- * mail utils
- */
-public class MailSender {
-
-    public static final Logger logger = LoggerFactory.getLogger(MailSender.class);
-
-    private List<String> receivers;
-    private List<String> receiverCcs;
-    private String mailProtocol = "SMTP";
-    private String mailSmtpHost;
-    private String mailSmtpPort;
-    private String mailSenderEmail;
-    private String enableSmtpAuth;
-    private String mailUser;
-    private String mailPasswd;
-    private String mailUseStartTLS;
-    private String mailUseSSL;
+public final class MailSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(MailSender.class);
+
+    private final List<String> receivers;
+    private final List<String> receiverCcs;
+    private final String mailProtocol = "SMTP";
+    private final String mailSmtpHost;
+    private final String mailSmtpPort;
+    private final String mailSenderEmail;
+    private final String enableSmtpAuth;
+    private final String mailUser;
+    private final String mailPasswd;
+    private final String mailUseStartTLS;
+    private final String mailUseSSL;
+    private final String sslTrust;
+    private final String showType;
+    private final AlertTemplate alertTemplate;
+    private final String mustNotNull = " must not be null";
     private String xlsFilePath;
-    private String sslTrust;
-    private String showType;
-    private AlertTemplate alertTemplate;
-    private String mustNotNull = " must not be null";
 
     public MailSender(Map<String, String> config) {
-
         String receiversConfig = config.get(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS);
         if (receiversConfig == null || "".equals(receiversConfig)) {
-            throw new AlertEmailException(MailParamsConstants.PLUGIN_DEFAULT_EMAIL_RECEIVERS + mustNotNull);
+            throw new AlertEmailException(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS + mustNotNull);
         }
 
         receivers = Arrays.asList(receiversConfig.split(","));
@@ -95,37 +72,37 @@ public class MailSender {
 
         receiverCcs = new ArrayList<>();
         if (receiverCcsConfig != null && !"".equals(receiverCcsConfig)) {
-            receiverCcs = Arrays.asList(receiverCcsConfig.split(","));
+            receiverCcs.addAll(Arrays.asList(receiverCcsConfig.split(",")));
         }
 
         mailSmtpHost = config.get(MailParamsConstants.NAME_MAIL_SMTP_HOST);
-        requireNonNull(mailSmtpHost, MailParamsConstants.MAIL_SMTP_HOST + mustNotNull);
+        requireNonNull(mailSmtpHost, MailParamsConstants.NAME_MAIL_SMTP_HOST + mustNotNull);
 
         mailSmtpPort = config.get(MailParamsConstants.NAME_MAIL_SMTP_PORT);
-        requireNonNull(mailSmtpPort, MailParamsConstants.MAIL_SMTP_PORT + mustNotNull);
+        requireNonNull(mailSmtpPort, MailParamsConstants.NAME_MAIL_SMTP_PORT + mustNotNull);
 
         mailSenderEmail = config.get(MailParamsConstants.NAME_MAIL_SENDER);
-        requireNonNull(mailSenderEmail, MailParamsConstants.MAIL_SENDER + mustNotNull);
+        requireNonNull(mailSenderEmail, MailParamsConstants.NAME_MAIL_SENDER + mustNotNull);
 
         enableSmtpAuth = config.get(MailParamsConstants.NAME_MAIL_SMTP_AUTH);
 
         mailUser = config.get(MailParamsConstants.NAME_MAIL_USER);
-        requireNonNull(mailUser, MailParamsConstants.MAIL_USER + mustNotNull);
+        requireNonNull(mailUser, MailParamsConstants.NAME_MAIL_USER + mustNotNull);
 
         mailPasswd = config.get(MailParamsConstants.NAME_MAIL_PASSWD);
-        requireNonNull(mailPasswd, MailParamsConstants.MAIL_PASSWD + mustNotNull);
+        requireNonNull(mailPasswd, MailParamsConstants.NAME_MAIL_PASSWD + mustNotNull);
 
         mailUseStartTLS = config.get(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE);
-        requireNonNull(mailUseStartTLS, MailParamsConstants.MAIL_SMTP_STARTTLS_ENABLE + mustNotNull);
+        requireNonNull(mailUseStartTLS, MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE + mustNotNull);
 
         mailUseSSL = config.get(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE);
-        requireNonNull(mailUseSSL, MailParamsConstants.MAIL_SMTP_SSL_ENABLE + mustNotNull);
+        requireNonNull(mailUseSSL, MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE + mustNotNull);
 
         sslTrust = config.get(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST);
-        requireNonNull(sslTrust, MailParamsConstants.MAIL_SMTP_SSL_TRUST + mustNotNull);
+        requireNonNull(sslTrust, MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST + mustNotNull);
 
-        showType = config.get(AlertConstants.SHOW_TYPE);
-        requireNonNull(showType, AlertConstants.SHOW_TYPE + mustNotNull);
+        showType = config.get(AlertConstants.NAME_SHOW_TYPE);
+        requireNonNull(showType, AlertConstants.NAME_SHOW_TYPE + mustNotNull);
 
         xlsFilePath = config.get(EmailConstants.XLS_FILE_PATH);
         if (StringUtils.isBlank(xlsFilePath)) {
@@ -146,16 +123,6 @@ public class MailSender {
     }
 
     /**
-     * send mail to receivers
-     *
-     * @param title email title
-     * @param content email content
-     */
-    public AlertResult sendMailsToReceiverOnly(String title, String content) {
-        return sendMails(this.receivers, null, title, content);
-    }
-
-    /**
      * send mail
      *
      * @param receivers receivers
@@ -206,8 +173,8 @@ public class MailSender {
             try {
 
                 String partContent = (showType.equals(ShowType.ATTACHMENT.getDescp())
-                        ? "Please see the attachment " + title + EmailConstants.EXCEL_SUFFIX_XLSX
-                        : htmlTable(content, false));
+                    ? "Please see the attachment " + title + EmailConstants.EXCEL_SUFFIX_XLSX
+                    : htmlTable(content, false));
 
                 attachment(title, content, partContent);
 
@@ -396,12 +363,12 @@ public class MailSender {
     public void deleteFile(File file) {
         if (file.exists()) {
             if (file.delete()) {
-                logger.info("delete success: {}", file.getAbsolutePath());
+                log.info("delete success: {}", file.getAbsolutePath());
             } else {
-                logger.info("delete fail: {}", file.getAbsolutePath());
+                log.info("delete fail: {}", file.getAbsolutePath());
             }
         } else {
-            logger.info("file not exists: {}", file.getAbsolutePath());
+            log.info("file not exists: {}", file.getAbsolutePath());
         }
     }
 
@@ -409,7 +376,7 @@ public class MailSender {
      * handle exception
      */
     private void handleException(AlertResult alertResult, Exception e) {
-        logger.error("Send email to {} failed", receivers, e);
+        log.error("Send email to {} failed", receivers, e);
         alertResult.setMessage("Send email to {" + String.join(",", receivers) + "} failed," + e.toString());
     }
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/exception/AlertEmailException.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/exception/AlertEmailException.java
similarity index 83%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/exception/AlertEmailException.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/exception/AlertEmailException.java
index 466ccc0..5b64d8d 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/exception/AlertEmailException.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/exception/AlertEmailException.java
@@ -18,22 +18,10 @@
 package org.apache.dolphinscheduler.plugin.alert.email.exception;
 
 public class AlertEmailException extends RuntimeException {
-
-    /**
-     * Create Runtime exception
-     *
-     * @param errMsg - Error message
-     */
     public AlertEmailException(String errMsg) {
         super(errMsg);
     }
 
-    /**
-     * Create Runtime exception
-     *
-     * @param errMsg - Error message
-     * @param cause - cause
-     */
     public AlertEmailException(String errMsg, Throwable cause) {
         super(errMsg, cause);
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java
similarity index 86%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java
index dec993d..7f66e65 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/AlertTemplate.java
@@ -17,19 +17,16 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email.template;
 
-import org.apache.dolphinscheduler.spi.alert.ShowType;
+import org.apache.dolphinscheduler.alert.api.ShowType;
 
-/**
- * alert message template
- */
 public interface AlertTemplate {
 
     /**
      * get a message from a specified alert template
      *
-     * @param content  alert message content
+     * @param content alert message content
      * @param showType show type
-     * @param showAll  whether to show all
+     * @param showAll whether to show all
      * @return a message from a specified alert template
      */
     String getMessageFromTemplate(String content, ShowType showType, boolean showAll);
@@ -37,7 +34,7 @@ public interface AlertTemplate {
     /**
      * default showAll is true
      *
-     * @param content  alert message content
+     * @param content alert message content
      * @param showType show type
      * @return a message from a specified alert template
      */
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java
similarity index 95%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java
index 57187aa..433cfda 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/main/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplate.java
@@ -19,8 +19,8 @@ package org.apache.dolphinscheduler.plugin.alert.email.template;
 
 import static java.util.Objects.requireNonNull;
 
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.apache.dolphinscheduler.plugin.alert.email.EmailConstants;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 import org.apache.dolphinscheduler.spi.utils.StringUtils;
 
@@ -36,9 +36,6 @@ import org.slf4j.LoggerFactory;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 
-/**
- * the default html alert message template
- */
 public class DefaultHTMLTemplate implements AlertTemplate {
 
     public static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplate.class);
@@ -89,7 +86,7 @@ public class DefaultHTMLTemplate implements AlertTemplate {
 
                     Map.Entry<String, Object> entry = iterator.next();
                     t.append(EmailConstants.TH).append(entry.getKey()).append(EmailConstants.TH_END);
-                    cs.append(EmailConstants.TD).append(String.valueOf(entry.getValue())).append(EmailConstants.TD_END);
+                    cs.append(EmailConstants.TD).append(entry.getValue()).append(EmailConstants.TD_END);
 
                 }
                 t.append(EmailConstants.TR_END);
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java
similarity index 82%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java
index 37a11e4..5bb7c1d 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelFactoryTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 
 import java.util.List;
@@ -25,27 +25,14 @@ import java.util.List;
 import org.junit.Assert;
 import org.junit.Test;
 
-/**
- * EmailAlertChannelFactory Tester.
- *
- * @version 1.0
- * @since <pre>Aug 20, 2020</pre>
- */
 public class EmailAlertChannelFactoryTest {
-
-    /**
-     * Method: getParams()
-     */
     @Test
     public void testGetParams() {
         EmailAlertChannelFactory emailAlertChannelFactory = new EmailAlertChannelFactory();
-        List<PluginParams> params = emailAlertChannelFactory.getParams();
+        List<PluginParams> params = emailAlertChannelFactory.params();
         Assert.assertEquals(12, params.size());
     }
 
-    /**
-     * Method: create()
-     */
     @Test
     public void testCreate() {
         EmailAlertChannelFactory emailAlertChannelFactory = new EmailAlertChannelFactory();
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java
new file mode 100644
index 0000000..49f67b2
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/EmailAlertChannelTest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.email;
+
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+import org.apache.dolphinscheduler.alert.api.ShowType;
+import org.apache.dolphinscheduler.spi.params.PasswordParam;
+import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
+import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
+import org.apache.dolphinscheduler.spi.utils.JSONUtils;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EmailAlertChannelTest {
+    @Test
+    public void testProcess() {
+        EmailAlertChannel emailAlertChannel = new EmailAlertChannel();
+        AlertData alertData = new AlertData();
+        LinkedHashMap<String, Object> map1 = new LinkedHashMap<>();
+        map1.put("mysql service name", "mysql200");
+        map1.put("mysql address", "192.168.xx.xx");
+        map1.put("port", "3306");
+        map1.put("no index of number", "80");
+        map1.put("database client connections", "190");
+        List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
+        maps.add(0, map1);
+        String mapjson = JSONUtils.toJsonString(maps);
+
+        alertData.setId(10)
+                 .setContent(mapjson)
+                 .setLog("10")
+                 .setTitle("test");
+        AlertInfo alertInfo = new AlertInfo();
+        alertInfo.setAlertData(alertData);
+        Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(getEmailAlertParams());
+
+        alertInfo.setAlertParams(paramsMap);
+        AlertResult alertResult = emailAlertChannel.process(alertInfo);
+        Assert.assertNotNull(alertResult);
+        Assert.assertEquals("false", alertResult.getStatus());
+    }
+
+    public String getEmailAlertParams() {
+        List<PluginParams> paramsList = new ArrayList<>();
+        InputParam receivesParam = InputParam.newBuilder(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, "receivers")
+                                             .setValue("540957506@qq.com")
+                                             .addValidate(Validate.newBuilder().setRequired(true).build())
+                                             .build();
+
+        InputParam mailSmtpHost = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_HOST, "smtp.host")
+                                            .addValidate(Validate.newBuilder().setRequired(true).build())
+                                            .setValue("smtp.126.com")
+                                            .build();
+
+        InputParam mailSmtpPort = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_PORT, "smtp.port")
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .setValue("25")
+                                            .build();
+
+        InputParam mailSender = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SENDER, "sender")
+                                          .addValidate(Validate.newBuilder().setRequired(true).build())
+                                          .setValue("dolphinscheduler@126.com")
+                                          .build();
+
+        RadioParam enableSmtpAuth = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_AUTH, "smtp.auth")
+                                              .addParamsOptions(new ParamsOptions("YES", "true", false))
+                                              .addParamsOptions(new ParamsOptions("NO", "false", false))
+                                              .addValidate(Validate.newBuilder().setRequired(true).build())
+                                              .setValue("false")
+                                              .build();
+
+        InputParam mailUser = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_USER, "user")
+                                        .setPlaceholder("if enable use authentication, you need input user")
+                                        .setValue("dolphinscheduler@126.com")
+                                        .build();
+
+        PasswordParam mailPassword = PasswordParam.newBuilder(MailParamsConstants.NAME_MAIL_PASSWD, "passwd")
+                                                  .setPlaceholder("if enable use authentication, you need input password")
+                                                  .setValue("escheduler123")
+                                                  .build();
+
+        RadioParam enableTls = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, "starttls.enable")
+                                         .addParamsOptions(new ParamsOptions("YES", "true", false))
+                                         .addParamsOptions(new ParamsOptions("NO", "false", false))
+                                         .addValidate(Validate.newBuilder().setRequired(true).build())
+                                         .setValue("true")
+                                         .build();
+
+        RadioParam enableSsl = RadioParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_ENABLE, "smtp.ssl.enable")
+                                         .addParamsOptions(new ParamsOptions("YES", "true", false))
+                                         .addParamsOptions(new ParamsOptions("NO", "false", false))
+                                         .addValidate(Validate.newBuilder().setRequired(true).build())
+                                         .setValue("true")
+                                         .build();
+
+        InputParam sslTrust = InputParam.newBuilder(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, "smtp.ssl.trust")
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .setValue("smtp.126.com")
+                                        .build();
+
+        List<ParamsOptions> emailShowTypeList = new ArrayList<>();
+        emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false));
+        emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false));
+        emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false));
+        emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false));
+        RadioParam showType = RadioParam.newBuilder(AlertConstants.NAME_SHOW_TYPE, "showType")
+                                        .setOptions(emailShowTypeList)
+                                        .setValue(ShowType.TABLE.getDescp())
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .build();
+
+        paramsList.add(receivesParam);
+        paramsList.add(mailSmtpHost);
+        paramsList.add(mailSmtpPort);
+        paramsList.add(mailSender);
+        paramsList.add(enableSmtpAuth);
+        paramsList.add(mailUser);
+        paramsList.add(mailPassword);
+        paramsList.add(enableTls);
+        paramsList.add(enableSsl);
+        paramsList.add(sslTrust);
+        paramsList.add(showType);
+
+        return JSONUtils.toJsonString(paramsList);
+    }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java
similarity index 100%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/ExcelUtilsTest.java
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java
similarity index 80%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java
index 5b0b084..540bcde 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/MailUtilsTest.java
@@ -17,34 +17,24 @@
 
 package org.apache.dolphinscheduler.plugin.alert.email;
 
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.apache.dolphinscheduler.plugin.alert.email.template.AlertTemplate;
 import org.apache.dolphinscheduler.plugin.alert.email.template.DefaultHTMLTemplate;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- */
+import java.util.*;
+
 public class MailUtilsTest {
     private static final Logger logger = LoggerFactory.getLogger(MailUtilsTest.class);
-
+    static MailSender mailSender;
     private static Map<String, String> emailConfig = new HashMap<>();
-
     private static AlertTemplate alertTemplate;
 
-    static MailSender mailSender;
-
     @BeforeClass
     public static void initEmailConfig() {
         emailConfig.put(MailParamsConstants.NAME_MAIL_PROTOCOL, "smtp");
@@ -59,7 +49,7 @@ public class MailUtilsTest {
         emailConfig.put(MailParamsConstants.NAME_MAIL_SMTP_SSL_TRUST, "false");
         emailConfig.put(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, "347801120@qq.com");
         emailConfig.put(MailParamsConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, "347801120@qq.com");
-        emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp());
+        emailConfig.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TEXT.getDescp());
         alertTemplate = new DefaultHTMLTemplate();
         mailSender = new MailSender(emailConfig);
     }
@@ -68,19 +58,19 @@ public class MailUtilsTest {
     public void testSendMails() {
 
         String content = "[\"id:69\","
-                + "\"name:UserBehavior-0--1193959466\","
-                + "\"Job name: Start workflow\","
-                + "\"State: SUCCESS\","
-                + "\"Recovery:NO\","
-                + "\"Run time: 1\","
-                + "\"Start time: 2018-08-06 10:31:34.0\","
-                + "\"End time: 2018-08-06 10:31:49.0\","
-                + "\"Host: 192.168.xx.xx\","
-                + "\"Notify group :4\"]";
+            + "\"name:UserBehavior-0--1193959466\","
+            + "\"Job name: Start workflow\","
+            + "\"State: SUCCESS\","
+            + "\"Recovery:NO\","
+            + "\"Run time: 1\","
+            + "\"Start time: 2018-08-06 10:31:34.0\","
+            + "\"End time: 2018-08-06 10:31:49.0\","
+            + "\"Host: 192.168.xx.xx\","
+            + "\"Notify group :4\"]";
 
         mailSender.sendMails(
-                "Mysql Exception",
-                content);
+            "Mysql Exception",
+            content);
     }
 
     public String list2String() {
@@ -113,7 +103,7 @@ public class MailUtilsTest {
     public void testSendTableMail() {
         String title = "Mysql Exception";
         String content = list2String();
-        emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp());
+        emailConfig.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TABLE.getDescp());
         mailSender = new MailSender(emailConfig);
         mailSender.sendMails(title, content);
     }
@@ -121,7 +111,7 @@ public class MailUtilsTest {
     @Test
     public void testAttachmentFile() throws Exception {
         String content = list2String();
-        emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.ATTACHMENT.getDescp());
+        emailConfig.put(AlertConstants.NAME_SHOW_TYPE, ShowType.ATTACHMENT.getDescp());
         mailSender = new MailSender(emailConfig);
         mailSender.sendMails("gaojing", content);
     }
@@ -129,7 +119,7 @@ public class MailUtilsTest {
     @Test
     public void testTableAttachmentFile() throws Exception {
         String content = list2String();
-        emailConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLEATTACHMENT.getDescp());
+        emailConfig.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TABLEATTACHMENT.getDescp());
         mailSender = new MailSender(emailConfig);
         mailSender.sendMails("gaojing", content);
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java
similarity index 71%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java
index 3d94196..d53c95b 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-email/src/test/java/org/apache/dolphinscheduler/plugin/alert/email/template/DefaultHTMLTemplateTest.java
@@ -19,8 +19,8 @@ package org.apache.dolphinscheduler.plugin.alert.email.template;
 
 import static org.junit.Assert.assertEquals;
 
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.apache.dolphinscheduler.plugin.alert.email.EmailConstants;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
 import java.util.ArrayList;
@@ -31,19 +31,12 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * test class for DefaultHTMLTemplate
- */
 public class DefaultHTMLTemplateTest {
 
     private static final Logger logger = LoggerFactory.getLogger(DefaultHTMLTemplateTest.class);
 
-    /**
-     * only need test method GetMessageFromTemplate
-     */
     @Test
     public void testGetMessageFromTemplate() {
-
         DefaultHTMLTemplate template = new DefaultHTMLTemplate();
 
         String tableTypeMessage = template.getMessageFromTemplate(list2String(), ShowType.TABLE, true);
@@ -55,11 +48,7 @@ public class DefaultHTMLTemplateTest {
         assertEquals(textTypeMessage, generateMockTextTypeResultByHand());
     }
 
-    /**
-     * generate some simulation data
-     */
     private String list2String() {
-
         LinkedHashMap<String, Object> map1 = new LinkedHashMap<>();
         map1.put("mysql service name", "mysql200");
         map1.put("mysql address", "192.168.xx.xx");
@@ -84,22 +73,20 @@ public class DefaultHTMLTemplateTest {
     }
 
     private String generateMockTableTypeResultByHand() {
-
         return EmailConstants.HTML_HEADER_PREFIX
-                + "<thead>"
-                + "<tr><th>mysql service name</th><th>mysql address</th><th>database client connections</th><th>port</th><th>no index of number</th></tr>"
-                + "</thead>\n"
-                + "<tr><td>mysql200</td><td>192.168.xx.xx</td><td>190</td><td>3306</td><td>80</td></tr>"
-                + "<tr><td>mysql210</td><td>192.168.xx.xx</td><td>90</td><td>3306</td><td>10</td></tr>"
-                + EmailConstants.TABLE_BODY_HTML_TAIL;
+            + "<thead>"
+            + "<tr><th>mysql service name</th><th>mysql address</th><th>database client connections</th><th>port</th><th>no index of number</th></tr>"
+            + "</thead>\n"
+            + "<tr><td>mysql200</td><td>192.168.xx.xx</td><td>190</td><td>3306</td><td>80</td></tr>"
+            + "<tr><td>mysql210</td><td>192.168.xx.xx</td><td>90</td><td>3306</td><td>10</td></tr>"
+            + EmailConstants.TABLE_BODY_HTML_TAIL;
 
     }
 
     private String generateMockTextTypeResultByHand() {
-
         return EmailConstants.HTML_HEADER_PREFIX
-                + "<tr><td>{\"mysql service name\":\"mysql200\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"190\",\"port\":\"3306\",\"no index of number\":\"80\"}</td></tr>"
-                + "<tr><td>{\"mysql service name\":\"mysql210\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"90\",\"port\":\"3306\",\"no index of number\":\"10\"}</td></tr>"
-                + EmailConstants.TABLE_BODY_HTML_TAIL;
+            + "<tr><td>{\"mysql service name\":\"mysql200\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"190\",\"port\":\"3306\",\"no index of number\":\"80\"}</td></tr>"
+            + "<tr><td>{\"mysql service name\":\"mysql210\",\"mysql address\":\"192.168.xx.xx\",\"database client connections\":\"90\",\"port\":\"3306\",\"no index of number\":\"10\"}</td></tr>"
+            + EmailConstants.TABLE_BODY_HTML_TAIL;
     }
 }
diff --git a/dolphinscheduler-registry/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/pom.xml
similarity index 59%
copy from dolphinscheduler-registry/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/pom.xml
index ff6796c..aaaea2f 100644
--- a/dolphinscheduler-registry/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/pom.xml
@@ -15,32 +15,26 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>dolphinscheduler-registry</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>dolphinscheduler-registry-api</module>
-        <module>dolphinscheduler-registry-plugins</module>
-    </modules>
+    <artifactId>dolphinscheduler-alert-feishu</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>com.google.auto.service</groupId>
-            <artifactId>auto-service</artifactId>
-            <optional>true</optional>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.22</version>
-            <scope>provided</scope>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
     </dependencies>
 </project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannel.java
similarity index 81%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannel.java
index 3bbdaa9..509eebe 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannel.java
@@ -17,17 +17,16 @@
 
 package org.apache.dolphinscheduler.plugin.alert.feishu;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
-public class FeiShuAlertChannel implements AlertChannel {
+public final class FeiShuAlertChannel implements AlertChannel {
     @Override
     public AlertResult process(AlertInfo alertInfo) {
-
         AlertData alertData = alertInfo.getAlertData();
         Map<String, String> paramsMap = alertInfo.getAlertParams();
         if (null == paramsMap) {
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactory.java
similarity index 52%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactory.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactory.java
index 6eb3376..da78b9f 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactory.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactory.java
@@ -22,59 +22,62 @@ import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_NO;
 import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_TRUE;
 import static org.apache.dolphinscheduler.spi.utils.Constants.STRING_YES;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
 import org.apache.dolphinscheduler.spi.params.PasswordParam;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
 import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
 
 import java.util.Arrays;
 import java.util.List;
 
-public class FeiShuAlertChannelFactory implements AlertChannelFactory {
+import com.google.auto.service.AutoService;
+
+@AutoService(AlertChannelFactory.class)
+public final class FeiShuAlertChannelFactory implements AlertChannelFactory {
     @Override
-    public String getName() {
+    public String name() {
         return "Feishu";
     }
 
     @Override
-    public List<PluginParams> getParams() {
+    public List<PluginParams> params() {
         InputParam webHookParam = InputParam.newBuilder(FeiShuParamsConstants.NAME_WEB_HOOK, FeiShuParamsConstants.WEB_HOOK)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .build();
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
         RadioParam isEnableProxy =
-                RadioParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_PROXY_ENABLE, FeiShuParamsConstants.NAME_FEI_SHU_PROXY_ENABLE)
-                        .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
-                        .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
-                        .setValue(STRING_TRUE)
-                        .addValidate(Validate.newBuilder()
-                                .setRequired(false)
-                                .build())
-                        .build();
+            RadioParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_PROXY_ENABLE, FeiShuParamsConstants.FEI_SHU_PROXY_ENABLE)
+                      .addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
+                      .addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
+                      .setValue(STRING_TRUE)
+                      .addValidate(Validate.newBuilder()
+                                           .setRequired(false)
+                                           .build())
+                      .build();
         InputParam proxyParam =
-                InputParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_PROXY, FeiShuParamsConstants.FEI_SHU_PROXY)
-                        .addValidate(Validate.newBuilder()
-                                .setRequired(false).build())
-                        .build();
+            InputParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_PROXY, FeiShuParamsConstants.FEI_SHU_PROXY)
+                      .addValidate(Validate.newBuilder()
+                                           .setRequired(false).build())
+                      .build();
 
         InputParam portParam = InputParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_PORT, FeiShuParamsConstants.FEI_SHU_PORT)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(false).build())
-                .build();
+                                         .addValidate(Validate.newBuilder()
+                                                              .setRequired(false).build())
+                                         .build();
 
         InputParam userParam =
-                InputParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_USER, FeiShuParamsConstants.FEI_SHU_USER)
-                        .addValidate(Validate.newBuilder()
-                                .setRequired(false).build())
-                        .build();
+            InputParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_USER, FeiShuParamsConstants.FEI_SHU_USER)
+                      .addValidate(Validate.newBuilder()
+                                           .setRequired(false).build())
+                      .build();
         PasswordParam passwordParam = PasswordParam.newBuilder(FeiShuParamsConstants.NAME_FEI_SHU_PASSWORD, FeiShuParamsConstants.FEI_SHU_PASSWORD)
-                .setPlaceholder("if enable use authentication, you need input password")
-                .build();
+                                                   .setPlaceholder("if enable use authentication, you need input password")
+                                                   .build();
 
         return Arrays.asList(webHookParam, isEnableProxy, proxyParam, portParam, userParam, passwordParam);
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuParamsConstants.java
similarity index 52%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuParamsConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuParamsConstants.java
index 0b3c329..aa74390 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuParamsConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuParamsConstants.java
@@ -17,33 +17,29 @@
 
 package org.apache.dolphinscheduler.plugin.alert.feishu;
 
-public class FeiShuParamsConstants {
+public final class FeiShuParamsConstants {
+    public static final String FEI_SHU_PROXY_ENABLE = "$t('isEnableProxy')";
+    static final String WEB_HOOK = "$t('webhook')";
+    static final String NAME_WEB_HOOK = "WebHook";
+    static final String NAME_FEI_SHU_PROXY_ENABLE = "IsEnableProxy";
 
-    private FeiShuParamsConstants() {
-        throw new IllegalStateException("Utility class");
-    }
-
-    static final String WEB_HOOK = "webhook";
-
-    static final String NAME_WEB_HOOK = "webHook";
+    static final String FEI_SHU_PROXY = "$t('proxy')";
 
-    public static final String FEI_SHU_PROXY_ENABLE = "isEnableProxy";
+    static final String NAME_FEI_SHU_PROXY = "Proxy";
 
-    static final String NAME_FEI_SHU_PROXY_ENABLE = "isEnableProxy";
+    static final String FEI_SHU_PORT = "$t('port')";
 
-    static final String FEI_SHU_PROXY = "proxy";
+    static final String NAME_FEI_SHU_PORT = "Port";
 
-    static final String NAME_FEI_SHU_PROXY = "proxy";
+    static final String FEI_SHU_USER = "$t('user')";
 
-    static final String FEI_SHU_PORT = "port";
+    static final String NAME_FEI_SHU_USER = "User";
 
-    static final String NAME_FEI_SHU_PORT = "port";
+    static final String FEI_SHU_PASSWORD = "$t('password')";
 
-    static final String FEI_SHU_USER = "user";
+    static final String NAME_FEI_SHU_PASSWORD = "Password";
 
-    static final String NAME_FEI_SHU_USER = "user";
-
-    static final String FEI_SHU_PASSWORD = "password";
-
-    static final String NAME_FEI_SHU_PASSWORD = "password";
+    private FeiShuParamsConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSender.java
similarity index 66%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSender.java
index 8fdafe7..dd40c75 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSender.java
@@ -17,8 +17,8 @@
 
 package org.apache.dolphinscheduler.plugin.alert.feishu;
 
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
 import org.apache.commons.codec.binary.StringUtils;
@@ -31,23 +31,18 @@ import org.apache.http.util.EntityUtils;
 
 import java.io.IOException;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class FeiShuSender {
-
-    private static final Logger logger = LoggerFactory.getLogger(FeiShuSender.class);
-
-    private String url;
-
-    private Boolean enableProxy;
+public final class FeiShuSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(FeiShuSender.class);
+    private final String url;
+    private final Boolean enableProxy;
 
     private String proxy;
 
@@ -70,7 +65,6 @@ public class FeiShuSender {
     }
 
     private static String textToJsonString(AlertData alertData) {
-
         Map<String, Object> items = new HashMap<>(2);
         items.put("msg_type", "text");
         Map<String, String> textContent = new HashMap<>();
@@ -87,14 +81,14 @@ public class FeiShuSender {
 
         if (org.apache.dolphinscheduler.spi.utils.StringUtils.isBlank(result)) {
             alertResult.setMessage("send fei shu msg error");
-            logger.info("send fei shu msg error,fei shu server resp is null");
+            log.info("send fei shu msg error,fei shu server resp is null");
             return alertResult;
         }
         FeiShuSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, FeiShuSendMsgResponse.class);
 
         if (null == sendMsgResponse) {
             alertResult.setMessage("send fei shu msg fail");
-            logger.info("send fei shu msg error,resp error");
+            log.info("send fei shu msg error,resp error");
             return alertResult;
         }
         if (sendMsgResponse.statusCode == 0) {
@@ -103,7 +97,7 @@ public class FeiShuSender {
             return alertResult;
         }
         alertResult.setMessage(String.format("alert send fei shu msg error : %s", sendMsgResponse.getStatusMessage()));
-        logger.info("alert send fei shu msg error : {} ,Extra : {} ", sendMsgResponse.getStatusMessage(), sendMsgResponse.getExtra());
+        log.info("alert send fei shu msg error : {} ,Extra : {} ", sendMsgResponse.getStatusMessage(), sendMsgResponse.getExtra());
         return alertResult;
     }
 
@@ -118,9 +112,7 @@ public class FeiShuSender {
             StringBuilder contents = new StringBuilder(100);
             contents.append(String.format("`%s`%n", alertData.getTitle()));
             for (Map map : list) {
-                Iterator<Entry<String, Object>> entries = map.entrySet().iterator();
-                while (entries.hasNext()) {
-                    Entry<String, Object> entry = entries.next();
+                for (Entry<String, Object> entry : (Iterable<Entry<String, Object>>) map.entrySet()) {
                     String key = entry.getKey();
                     String value = entry.getValue().toString();
                     contents.append(key + ":" + value);
@@ -138,7 +130,7 @@ public class FeiShuSender {
             String resp = sendMsg(alertData);
             return checkSendFeiShuSendMsgResult(resp);
         } catch (Exception e) {
-            logger.info("send fei shu alert msg  exception : {}", e.getMessage());
+            log.info("send fei shu alert msg  exception : {}", e.getMessage());
             alertResult = new AlertResult();
             alertResult.setStatus("false");
             alertResult.setMessage("send fei shu alert fail.");
@@ -161,7 +153,7 @@ public class FeiShuSender {
 
             int statusCode = response.getStatusLine().getStatusCode();
             if (statusCode != HttpStatus.SC_OK) {
-                logger.error("send feishu message error, return http status code: {} ", statusCode);
+                log.error("send feishu message error, return http status code: {} ", statusCode);
             }
             String resp;
             try {
@@ -171,14 +163,14 @@ public class FeiShuSender {
             } finally {
                 response.close();
             }
-            logger.info("Fei Shu send title :{} ,content :{}, resp: {}", alertData.getTitle(), alertData.getContent(), resp);
+            log.info("Fei Shu send title :{} ,content :{}, resp: {}", alertData.getTitle(), alertData.getContent(), resp);
             return resp;
         } finally {
             httpClient.close();
         }
     }
 
-    public static class FeiShuSendMsgResponse {
+    static final class FeiShuSendMsgResponse {
         @JsonProperty("Extra")
         private String extra;
         @JsonProperty("StatusCode")
@@ -186,29 +178,76 @@ public class FeiShuSender {
         @JsonProperty("StatusMessage")
         private String statusMessage;
 
+        public FeiShuSendMsgResponse() {
+        }
+
         public String getExtra() {
-            return extra;
+            return this.extra;
         }
 
+        @JsonProperty("Extra")
         public void setExtra(String extra) {
             this.extra = extra;
         }
 
         public Integer getStatusCode() {
-            return statusCode;
+            return this.statusCode;
         }
 
+        @JsonProperty("StatusCode")
         public void setStatusCode(Integer statusCode) {
             this.statusCode = statusCode;
         }
 
         public String getStatusMessage() {
-            return statusMessage;
+            return this.statusMessage;
         }
 
+        @JsonProperty("StatusMessage")
         public void setStatusMessage(String statusMessage) {
             this.statusMessage = statusMessage;
         }
-    }
 
+        public boolean equals(final Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (!(o instanceof FeiShuSendMsgResponse)) {
+                return false;
+            }
+            final FeiShuSendMsgResponse other = (FeiShuSendMsgResponse) o;
+            final Object this$extra = this.getExtra();
+            final Object other$extra = other.getExtra();
+            if (this$extra == null ? other$extra != null : !this$extra.equals(other$extra)) {
+                return false;
+            }
+            final Object this$statusCode = this.getStatusCode();
+            final Object other$statusCode = other.getStatusCode();
+            if (this$statusCode == null ? other$statusCode != null : !this$statusCode.equals(other$statusCode)) {
+                return false;
+            }
+            final Object this$statusMessage = this.getStatusMessage();
+            final Object other$statusMessage = other.getStatusMessage();
+            if (this$statusMessage == null ? other$statusMessage != null : !this$statusMessage.equals(other$statusMessage)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            final int PRIME = 59;
+            int result = 1;
+            final Object $extra = this.getExtra();
+            result = result * PRIME + ($extra == null ? 43 : $extra.hashCode());
+            final Object $statusCode = this.getStatusCode();
+            result = result * PRIME + ($statusCode == null ? 43 : $statusCode.hashCode());
+            final Object $statusMessage = this.getStatusMessage();
+            result = result * PRIME + ($statusMessage == null ? 43 : $statusMessage.hashCode());
+            return result;
+        }
+
+        public String toString() {
+            return "FeiShuSender.FeiShuSendMsgResponse(extra=" + this.getExtra() + ", statusCode=" + this.getStatusCode() + ", statusMessage=" + this.getStatusMessage() + ")";
+        }
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java
similarity index 92%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java
index 3d14357..eca9b07 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/main/java/org/apache/dolphinscheduler/plugin/alert/feishu/HttpRequestUtil.java
@@ -28,7 +28,10 @@ import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 
-public class HttpRequestUtil {
+public final class HttpRequestUtil {
+    private HttpRequestUtil() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 
     public static CloseableHttpClient getHttpClient(boolean enableProxy, String proxy, Integer port, String user, String password) {
         if (enableProxy) {
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactoryTest.java
similarity index 92%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactoryTest.java
index d73355d..ce51e00 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuAlertChannelFactoryTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.feishu;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
@@ -31,7 +31,7 @@ public class FeiShuAlertChannelFactoryTest {
     @Test
     public void testGetParams() {
         FeiShuAlertChannelFactory feiShuAlertChannelFactory = new FeiShuAlertChannelFactory();
-        List<PluginParams> params = feiShuAlertChannelFactory.getParams();
+        List<PluginParams> params = feiShuAlertChannelFactory.params();
         JSONUtils.toJsonString(params);
         Assert.assertEquals(6, params.size());
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSenderTest.java
similarity index 74%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSenderTest.java
index 05110d4..8d5dfdb 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-feishu/src/test/java/org/apache/dolphinscheduler/plugin/alert/feishu/FeiShuSenderTest.java
@@ -17,8 +17,8 @@
 
 package org.apache.dolphinscheduler.plugin.alert.feishu;
 
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -50,23 +50,23 @@ public class FeiShuSenderTest {
     @Test
     public void testFormatContent() {
         String alertMsg = "[\n"
-                + "  {\n"
-                + "    \"owner\": \"dolphinscheduler\",\n"
-                + "    \"processEndTime\": \"2021-01-29 19:01:11\",\n"
-                + "    \"processHost\": \"10.81.129.4:5678\",\n"
-                + "    \"processId\": 2926,\n"
-                + "    \"processName\": \"3-20210129190038108\",\n"
-                + "    \"processStartTime\": \"2021-01-29 19:00:38\",\n"
-                + "    \"processState\": \"SUCCESS\",\n"
-                + "    \"processType\": \"START_PROCESS\",\n"
-                + "    \"projectId\": 2,\n"
-                + "    \"projectName\": \"testdelproject\",\n"
-                + "    \"recovery\": \"NO\",\n"
-                + "    \"retryTimes\": 0,\n"
-                + "    \"runTimes\": 1,\n"
-                + "    \"taskId\": 0\n"
-                + "  }\n"
-                + "]";
+            + "  {\n"
+            + "    \"owner\": \"dolphinscheduler\",\n"
+            + "    \"processEndTime\": \"2021-01-29 19:01:11\",\n"
+            + "    \"processHost\": \"10.81.129.4:5678\",\n"
+            + "    \"processId\": 2926,\n"
+            + "    \"processName\": \"3-20210129190038108\",\n"
+            + "    \"processStartTime\": \"2021-01-29 19:00:38\",\n"
+            + "    \"processState\": \"SUCCESS\",\n"
+            + "    \"processType\": \"START_PROCESS\",\n"
+            + "    \"projectId\": 2,\n"
+            + "    \"projectName\": \"testdelproject\",\n"
+            + "    \"recovery\": \"NO\",\n"
+            + "    \"retryTimes\": 0,\n"
+            + "    \"runTimes\": 1,\n"
+            + "    \"taskId\": 0\n"
+            + "  }\n"
+            + "]";
         AlertData alertData = new AlertData();
         alertData.setTitle("");
         alertData.setContent(alertMsg);
@@ -90,7 +90,7 @@ public class FeiShuSenderTest {
         AlertResult alertResult = feiShuSender.checkSendFeiShuSendMsgResult("");
         Assert.assertFalse(Boolean.valueOf(alertResult.getStatus()));
         AlertResult alertResult2 = feiShuSender.checkSendFeiShuSendMsgResult("123");
-        Assert.assertEquals("send fei shu msg fail",alertResult2.getMessage());
+        Assert.assertEquals("send fei shu msg fail", alertResult2.getMessage());
 
         String response = "{\"StatusCode\":\"0\",\"extra\":\"extra\",\"StatusMessage\":\"StatusMessage\"}";
         AlertResult alertResult3 = feiShuSender.checkSendFeiShuSendMsgResult(response);
diff --git a/dolphinscheduler-registry/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/pom.xml
similarity index 61%
copy from dolphinscheduler-registry/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/pom.xml
index ff6796c..c2e019d 100644
--- a/dolphinscheduler-registry/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/pom.xml
@@ -15,31 +15,32 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>dolphinscheduler-registry</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>dolphinscheduler-registry-api</module>
-        <module>dolphinscheduler-registry-plugins</module>
-    </modules>
+    <artifactId>dolphinscheduler-alert-http</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>com.google.auto.service</groupId>
-            <artifactId>auto-service</artifactId>
-            <optional>true</optional>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+
         <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.22</version>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
             <scope>provided</scope>
         </dependency>
     </dependencies>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java
similarity index 78%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java
index cb550b7..14b4167 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannel.java
@@ -17,20 +17,16 @@
 
 package org.apache.dolphinscheduler.plugin.alert.http;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
-/**
- * http alert channel,use sms message to seed the alertInfo
- */
-public class HttpAlertChannel implements AlertChannel {
+public final class HttpAlertChannel implements AlertChannel {
     @Override
     public AlertResult process(AlertInfo alertInfo) {
-
         AlertData alertData = alertInfo.getAlertData();
         Map<String, String> paramsMap = alertInfo.getAlertParams();
         if (null == paramsMap) {
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java
new file mode 100644
index 0000000..d5c628c
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactory.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.http;
+
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.google.auto.service.AutoService;
+
+@AutoService(AlertChannelFactory.class)
+public final class HttpAlertChannelFactory implements AlertChannelFactory {
+    @Override
+    public String name() {
+        return "Http";
+    }
+
+    @Override
+    public List<PluginParams> params() {
+
+        InputParam url = InputParam.newBuilder(HttpAlertConstants.NAME_URL, HttpAlertConstants.URL)
+                                   .addValidate(Validate.newBuilder()
+                                                        .setRequired(true)
+                                                        .build())
+                                   .build();
+
+        InputParam headerParams = InputParam.newBuilder(HttpAlertConstants.NAME_HEADER_PARAMS, HttpAlertConstants.HEADER_PARAMS)
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
+
+        InputParam bodyParams = InputParam.newBuilder(HttpAlertConstants.NAME_BODY_PARAMS, HttpAlertConstants.BODY_PARAMS)
+                                          .addValidate(Validate.newBuilder()
+                                                               .setRequired(true)
+                                                               .build())
+                                          .build();
+
+        InputParam contentField = InputParam.newBuilder(HttpAlertConstants.NAME_CONTENT_FIELD, HttpAlertConstants.CONTENT_FIELD)
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
+
+        InputParam requestType = InputParam.newBuilder(HttpAlertConstants.NAME_REQUEST_TYPE, HttpAlertConstants.REQUEST_TYPE)
+                                           .addValidate(Validate.newBuilder()
+                                                                .setRequired(true)
+                                                                .build())
+                                           .build();
+
+        return Arrays.asList(url, requestType, headerParams, bodyParams, contentField);
+    }
+
+    @Override
+    public AlertChannel create() {
+        return new HttpAlertChannel();
+    }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java
similarity index 53%
copy from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java
index 965860d..6bbf0bf 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertConstants.java
@@ -17,19 +17,28 @@
 
 package org.apache.dolphinscheduler.plugin.alert.http;
 
-public class HttpAlertConstants {
+public final class HttpAlertConstants {
+    public static final String URL = "$t('url')";
 
-    private HttpAlertConstants() {
-    }
+    public static final String NAME_URL = "url";
+
+    public static final String HEADER_PARAMS = "$t('headerParams')";
+
+    public static final String NAME_HEADER_PARAMS = "headerParams";
 
-    public static final String URL = "url";
+    public static final String BODY_PARAMS = "$t('bodyParams')";
 
-    public static final String HEADER_PARAMS = "headerParams";
+    public static final String NAME_BODY_PARAMS = "bodyParams";
 
-    public static final String BODY_PARAMS = "bodyParams";
+    public static final String CONTENT_FIELD = "$t('contentField')";
 
-    public static final String CONTENT_FIELD = "contentField";
+    public static final String NAME_CONTENT_FIELD = "contentField";
 
-    public static final String REQUEST_TYPE = "requestType";
+    public static final String REQUEST_TYPE = "$t('requestType')";
 
+    public static final String NAME_REQUEST_TYPE = "requestType";
+
+    private HttpAlertConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java
similarity index 84%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java
index 7b91904..bc789ed 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/main/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSender.java
@@ -17,10 +17,10 @@
 
 package org.apache.dolphinscheduler.plugin.alert.http;
 
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 import org.apache.dolphinscheduler.spi.utils.StringUtils;
-
 import org.apache.http.HttpEntity;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
@@ -30,56 +30,37 @@ import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-/**
- * http  send message
- */
-public class HttpSender {
-
-    public static final Logger logger = LoggerFactory.getLogger(HttpSender.class);
-
-    private String url;
-
-    private final String headerParams;
-
-    private final String bodyParams;
-
-    private final String contentField;
-
-    private final String requestType;
-
-    private HttpRequestBase httpRequest;
-
-
+public final class HttpSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(HttpSender.class);
     private static final String URL_SPLICE_CHAR = "?";
-
     /**
      * request type post
      */
     private static final String REQUEST_TYPE_POST = "POST";
-
     /**
      * request type get
      */
     private static final String REQUEST_TYPE_GET = "GET";
-
     private static final String DEFAULT_CHARSET = "utf-8";
+    private final String headerParams;
+    private final String bodyParams;
+    private final String contentField;
+    private final String requestType;
+    private String url;
+    private HttpRequestBase httpRequest;
 
     public HttpSender(Map<String, String> paramsMap) {
 
-        url = paramsMap.get(HttpAlertConstants.URL);
-        headerParams = paramsMap.get(HttpAlertConstants.HEADER_PARAMS);
-        bodyParams = paramsMap.get(HttpAlertConstants.BODY_PARAMS);
-        contentField = paramsMap.get(HttpAlertConstants.CONTENT_FIELD);
-        requestType = paramsMap.get(HttpAlertConstants.REQUEST_TYPE);
+        url = paramsMap.get(HttpAlertConstants.NAME_URL);
+        headerParams = paramsMap.get(HttpAlertConstants.NAME_HEADER_PARAMS);
+        bodyParams = paramsMap.get(HttpAlertConstants.NAME_BODY_PARAMS);
+        contentField = paramsMap.get(HttpAlertConstants.NAME_CONTENT_FIELD);
+        requestType = paramsMap.get(HttpAlertConstants.NAME_REQUEST_TYPE);
     }
 
     public AlertResult send(String msg) {
@@ -102,7 +83,7 @@ public class HttpSender {
             alertResult.setStatus("true");
             alertResult.setMessage(resp);
         } catch (Exception e) {
-            logger.error("send http alert msg  exception : {}", e.getMessage());
+            log.error("send http alert msg  exception : {}", e.getMessage());
             alertResult.setStatus("false");
             alertResult.setMessage("send http request  alert fail.");
         }
@@ -157,16 +138,15 @@ public class HttpSender {
     /**
      * set body params
      */
-    private void setMsgInRequestBody(String msg)  {
+    private void setMsgInRequestBody(String msg) {
         ObjectNode objectNode = JSONUtils.parseObject(bodyParams);
         //set msg content field
         objectNode.put(contentField, msg);
         try {
             StringEntity entity = new StringEntity(bodyParams, DEFAULT_CHARSET);
-            ((HttpPost)httpRequest).setEntity(entity);
+            ((HttpPost) httpRequest).setEntity(entity);
         } catch (Exception e) {
-            logger.error("send http alert msg  exception : {}", e.getMessage());
+            log.error("send http alert msg  exception : {}", e.getMessage());
         }
     }
-
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java
similarity index 93%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java
index 25181eb..089f78f 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelFactoryTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.http;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 
 import java.util.List;
@@ -26,9 +26,6 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-/**
- * HttpAlertChannelFactory UT
- */
 public class HttpAlertChannelFactoryTest {
 
     private HttpAlertChannelFactory httpAlertChannelFactory;
@@ -41,7 +38,7 @@ public class HttpAlertChannelFactoryTest {
     @Test
     public void getParamsTest() {
 
-        List<PluginParams> pluginParamsList = httpAlertChannelFactory.getParams();
+        List<PluginParams> pluginParamsList = httpAlertChannelFactory.params();
         Assert.assertEquals(5, pluginParamsList.size());
     }
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java
similarity index 70%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java
index 2d29407..ca63902 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpAlertChannelTest.java
@@ -17,13 +17,13 @@
 
 package org.apache.dolphinscheduler.plugin.alert.http;
 
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
 import java.util.ArrayList;
@@ -33,9 +33,6 @@ import java.util.Map;
 import org.junit.Assert;
 import org.junit.Test;
 
-/**
- * HttpAlertChannel UT
- */
 public class HttpAlertChannelTest {
 
     @Test
@@ -71,29 +68,29 @@ public class HttpAlertChannelTest {
 
         List<PluginParams> paramsList = new ArrayList<>();
         InputParam urlParam = InputParam.newBuilder("url", "url")
-                .setValue("http://www.baidu.com")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
+                                        .setValue("http://www.baidu.com")
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .build();
 
         InputParam headerParams = InputParam.newBuilder("headerParams", "headerParams")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("{\"Content-Type\":\"application/json\"}")
-                .build();
+                                            .addValidate(Validate.newBuilder().setRequired(true).build())
+                                            .setValue("{\"Content-Type\":\"application/json\"}")
+                                            .build();
 
         InputParam bodyParams = InputParam.newBuilder("bodyParams", "bodyParams")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("{\"number\":\"13457654323\"}")
-                .build();
+                                          .addValidate(Validate.newBuilder().setRequired(true).build())
+                                          .setValue("{\"number\":\"13457654323\"}")
+                                          .build();
 
         InputParam content = InputParam.newBuilder("contentField", "contentField")
-                .setValue("content")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
+                                       .setValue("content")
+                                       .addValidate(Validate.newBuilder().setRequired(true).build())
+                                       .build();
 
         InputParam requestType = InputParam.newBuilder("requestType", "requestType")
-                .setValue("POST")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
+                                           .setValue("POST")
+                                           .addValidate(Validate.newBuilder().setRequired(true).build())
+                                           .build();
 
         paramsList.add(urlParam);
         paramsList.add(headerParams);
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java
similarity index 73%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java
index d59c4d4..637c615 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-http/src/test/java/org/apache/dolphinscheduler/plugin/alert/http/HttpSenderTest.java
@@ -17,28 +17,23 @@
 
 package org.apache.dolphinscheduler.plugin.alert.http;
 
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+import org.junit.Assert;
+import org.junit.Test;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * HttpSender UT
- */
 public class HttpSenderTest {
 
     @Test
     public void sendTest() {
-
         Map<String, String> paramsMap = new HashMap<>();
-        paramsMap.put(HttpAlertConstants.URL, "http://www.baidu.com");
-        paramsMap.put(HttpAlertConstants.REQUEST_TYPE, "POST");
-        paramsMap.put(HttpAlertConstants.HEADER_PARAMS, "{\"Content-Type\":\"application/json\"}");
-        paramsMap.put(HttpAlertConstants.BODY_PARAMS, "{\"number\":\"13457654323\"}");
-        paramsMap.put(HttpAlertConstants.CONTENT_FIELD, "content");
+        paramsMap.put(HttpAlertConstants.NAME_URL, "http://www.baidu.com");
+        paramsMap.put(HttpAlertConstants.NAME_REQUEST_TYPE, "POST");
+        paramsMap.put(HttpAlertConstants.NAME_HEADER_PARAMS, "{\"Content-Type\":\"application/json\"}");
+        paramsMap.put(HttpAlertConstants.NAME_BODY_PARAMS, "{\"number\":\"13457654323\"}");
+        paramsMap.put(HttpAlertConstants.NAME_CONTENT_FIELD, "content");
         HttpSender httpSender = new HttpSender(paramsMap);
         AlertResult alertResult = httpSender.send("Fault tolerance warning");
         Assert.assertEquals("true", alertResult.getStatus());
diff --git a/dolphinscheduler-registry/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/pom.xml
similarity index 57%
copy from dolphinscheduler-registry/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/pom.xml
index ff6796c..7f8443e 100644
--- a/dolphinscheduler-registry/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/pom.xml
@@ -15,32 +15,22 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>dolphinscheduler-registry</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>dolphinscheduler-registry-api</module>
-        <module>dolphinscheduler-registry-plugins</module>
-    </modules>
+    <artifactId>dolphinscheduler-alert-script</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>com.google.auto.service</groupId>
-            <artifactId>auto-service</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.22</version>
-            <scope>provided</scope>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
     </dependencies>
 </project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java
similarity index 88%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java
index b881672..51e567b 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/OSUtils.java
@@ -17,13 +17,9 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-/**
- * OSUtils
- */
-public class OSUtils {
-
+public final class OSUtils {
     private OSUtils() {
-        throw new UnsupportedOperationException("Construct OSUtils");
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
     }
 
     static Boolean isWindows() {
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java
similarity index 84%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java
index d63a350..7008267 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtils.java
@@ -20,17 +20,12 @@ package org.apache.dolphinscheduler.plugin.alert.script;
 import java.io.IOException;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * ProcessUtils
- */
-public class ProcessUtils {
-
-    private static final Logger logger = LoggerFactory.getLogger(ProcessUtils.class);
+public final class ProcessUtils {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(ProcessUtils.class);
 
     private ProcessUtils() {
-        throw new IllegalStateException("Utility class");
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
     }
 
     /**
@@ -53,7 +48,7 @@ public class ProcessUtils {
             errorStreamGobbler.start();
             return process.waitFor();
         } catch (IOException | InterruptedException e) {
-            logger.error("execute alert script error {}", e.getMessage());
+            log.error("execute alert script error {}", e.getMessage());
             Thread.currentThread().interrupt();
         }
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java
similarity index 77%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java
index af0c276..bd52955 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannel.java
@@ -17,18 +17,14 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
-/**
- * ScriptAlertChannel
- */
-public class ScriptAlertChannel implements AlertChannel {
-
+public final class ScriptAlertChannel implements AlertChannel {
     @Override
     public AlertResult process(AlertInfo alertinfo) {
         AlertData alertData = alertinfo.getAlertData();
@@ -36,6 +32,6 @@ public class ScriptAlertChannel implements AlertChannel {
         if (null == paramsMap) {
             return new AlertResult("false", "script params is null");
         }
-        return new ScriptSender(paramsMap).sendScriptAlert(alertData.getTitle(),alertData.getContent());
+        return new ScriptSender(paramsMap).sendScriptAlert(alertData.getTitle(), alertData.getContent());
     }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java
similarity index 52%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java
index 67cfc39..aacde95 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactory.java
@@ -17,49 +17,49 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
 import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
 
 import java.util.Arrays;
 import java.util.List;
 
-/**
- * ScriptAlertChannelFactory
- */
-public class ScriptAlertChannelFactory implements AlertChannelFactory {
+import com.google.auto.service.AutoService;
 
+@AutoService(AlertChannelFactory.class)
+public final class ScriptAlertChannelFactory implements AlertChannelFactory {
     @Override
-    public String getName() {
+    public String name() {
         return "Script";
     }
 
     @Override
-    public List<PluginParams> getParams() {
+    public List<PluginParams> params() {
 
         InputParam scriptUserParam = InputParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_USER_PARAMS, ScriptParamsConstants.SCRIPT_USER_PARAMS)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(false)
-                        .build())
-                .setPlaceholder("please enter your custom parameters, which will be passed to you when calling your script")
-                .build();
+                                               .addValidate(Validate.newBuilder()
+                                                                    .setRequired(false)
+                                                                    .build())
+                                               .setPlaceholder("please enter your custom parameters, which will be passed to you when calling your script")
+                                               .build();
         // need check file type and file exist
         InputParam scriptPathParam = InputParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_PATH, ScriptParamsConstants.SCRIPT_PATH)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .setPlaceholder("please upload the file to the disk directory of the alert server, and ensure that the path is absolute and has the corresponding access rights")
-                .build();
+                                               .addValidate(Validate.newBuilder()
+                                                                    .setRequired(true)
+                                                                    .build())
+                                               .setPlaceholder("please upload the file to the disk directory of the alert server,"
+                                                   + " and ensure that the path is absolute and has the corresponding access rights")
+                                               .build();
 
         RadioParam scriptTypeParams = RadioParam.newBuilder(ScriptParamsConstants.NAME_SCRIPT_TYPE, ScriptParamsConstants.SCRIPT_TYPE)
-                .addParamsOptions(new ParamsOptions(ScriptType.SHELL.getDescp(), ScriptType.SHELL.getDescp(), false))
-                .setValue(ScriptType.SHELL.getDescp())
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
+                                                .addParamsOptions(new ParamsOptions(ScriptType.SHELL.getDescp(), ScriptType.SHELL.getDescp(), false))
+                                                .setValue(ScriptType.SHELL.getDescp())
+                                                .addValidate(Validate.newBuilder().setRequired(true).build())
+                                                .build();
 
         return Arrays.asList(scriptUserParam, scriptPathParam, scriptTypeParams);
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java
similarity index 76%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java
index 5b096d5..e680903 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptParamsConstants.java
@@ -17,24 +17,20 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-/**
- * ScriptParamsConstants
- */
-public class ScriptParamsConstants {
-
-    private ScriptParamsConstants() {
-        throw new IllegalStateException("Utility class");
-    }
-
-    static final String SCRIPT_TYPE = "type";
+public final class ScriptParamsConstants {
+    static final String SCRIPT_TYPE = "$t('scriptType')";
 
     static final String NAME_SCRIPT_TYPE = "type";
 
-    static final String SCRIPT_PATH = "path";
+    static final String SCRIPT_PATH = "$t('scriptPath')";
 
     static final String NAME_SCRIPT_PATH = "path";
 
-    static final String SCRIPT_USER_PARAMS = "user.params";
+    static final String SCRIPT_USER_PARAMS = "$t('userParams')";
 
     static final String NAME_SCRIPT_USER_PARAMS = "userParams";
+
+    private ScriptParamsConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java
similarity index 86%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java
index 8e33b79..a4dbe1e 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSender.java
@@ -17,31 +17,20 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * ScriptSender
- */
-public class ScriptSender {
-
-    private static final Logger logger = LoggerFactory.getLogger(ScriptSender.class);
-
-    private String scriptPath;
-
-    private String scriptType;
-
-    private String userParams;
 
+public final class ScriptSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(ScriptSender.class);
     private static final String ALERT_TITLE_OPTION = " -t ";
-
     private static final String ALERT_CONTENT_OPTION = " -c ";
-
     private static final String ALERT_USER_PARAMS_OPTION = " -p ";
+    private final String scriptPath;
+    private final String scriptType;
+    private final String userParams;
 
     ScriptSender(Map<String, String> config) {
         scriptPath = config.get(ScriptParamsConstants.NAME_SCRIPT_PATH);
@@ -73,7 +62,7 @@ public class ScriptSender {
             return alertResult;
         }
         alertResult.setMessage("send script alert msg error,exitCode is " + exitCode);
-        logger.info("send script alert msg error,exitCode is {}", exitCode);
+        log.info("send script alert msg error,exitCode is {}", exitCode);
         return alertResult;
     }
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java
similarity index 94%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java
index ff3b809..cbb3e11 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptType.java
@@ -17,26 +17,17 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * ScriptType
- */
 public enum ScriptType {
-
-
     SHELL(0, "SHELL"),
     ;
 
+    private final int code;
+    private final String descp;
     ScriptType(int code, String descp) {
         this.code = code;
         this.descp = descp;
     }
 
-    private final int code;
-    private final String descp;
-
     public int getCode() {
         return code;
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java
similarity index 81%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java
index 41aabfe..6b1d19a 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/main/java/org/apache/dolphinscheduler/plugin/alert/script/StreamGobbler.java
@@ -23,16 +23,11 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-/**
- * StreamGobbler
- */
-public class StreamGobbler extends Thread {
-
-    private static final Logger logger = LoggerFactory.getLogger(StreamGobbler.class);
+public final class StreamGobbler extends Thread {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(StreamGobbler.class);
 
-    private InputStream inputStream;
+    private final InputStream inputStream;
 
     StreamGobbler(InputStream inputStream) {
         this.inputStream = inputStream;
@@ -51,16 +46,16 @@ public class StreamGobbler extends Thread {
                 output.append(System.getProperty("line.separator"));
             }
             if (output.length() > 0) {
-                logger.info("out put msg is{}", output);
+                log.info("out put msg is{}", output);
             }
         } catch (IOException e) {
-            logger.error("I/O error occurs {}", e.getMessage());
+            log.error("I/O error occurs {}", e.getMessage());
         } finally {
             try {
                 inputBufferReader.close();
                 inputStreamReader.close();
             } catch (IOException e) {
-                logger.error("I/O error occurs {}", e.getMessage());
+                log.error("I/O error occurs {}", e.getMessage());
             }
         }
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java
similarity index 93%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java
index 1d847a0..7ee473e 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ProcessUtilsTest.java
@@ -26,7 +26,7 @@ public class ProcessUtilsTest {
 
     private static final String rootPath = System.getProperty("user.dir");
 
-    private static final String shellFilPath = rootPath + "/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/test.sh";
+    private static final String shellFilPath = rootPath + "/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/script/shell/test.sh";
 
     private String[] cmd = {"/bin/sh", "-c", shellFilPath + " -t 1"};
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java
similarity index 91%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java
index 8cedc2c..ca45cf7 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptAlertChannelFactoryTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 
 import java.util.List;
@@ -33,7 +33,7 @@ public class ScriptAlertChannelFactoryTest {
     @Test
     public void testGetParams() {
         ScriptAlertChannelFactory scriptAlertChannelFactory = new ScriptAlertChannelFactory();
-        List<PluginParams> params = scriptAlertChannelFactory.getParams();
+        List<PluginParams> params = scriptAlertChannelFactory.params();
         Assert.assertEquals(3, params.size());
     }
 
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java
similarity index 97%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java
index e022b9e..445d073 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/java/org/apache/dolphinscheduler/plugin/alert/script/ScriptSenderTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.script;
 
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -31,11 +31,9 @@ import org.junit.Test;
  */
 public class ScriptSenderTest {
 
-    private static Map<String, String> scriptConfig = new HashMap<>();
-
     private static final String rootPath = System.getProperty("user.dir");
-
     private static final String shellFilPath = rootPath + "/src/test/script/shell/scriptExample.sh";
+    private static Map<String, String> scriptConfig = new HashMap<>();
 
     @Before
     public void initScriptConfig() {
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/scriptExample.sh b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/script/shell/scriptExample.sh
similarity index 100%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/scriptExample.sh
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/script/shell/scriptExample.sh
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/test.sh b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/script/shell/test.sh
similarity index 100%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-script/src/test/script/shell/test.sh
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-script/src/test/script/shell/test.sh
diff --git a/dolphinscheduler-registry/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/pom.xml
similarity index 59%
copy from dolphinscheduler-registry/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/pom.xml
index ff6796c..f24073e 100644
--- a/dolphinscheduler-registry/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/pom.xml
@@ -15,32 +15,27 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>dolphinscheduler-registry</artifactId>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>dolphinscheduler-registry-api</module>
-        <module>dolphinscheduler-registry-plugins</module>
-    </modules>
+    <artifactId>dolphinscheduler-alert-slack</artifactId>
+    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>com.google.auto.service</groupId>
-            <artifactId>auto-service</artifactId>
-            <optional>true</optional>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
         </dependency>
+
         <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>1.18.22</version>
-            <scope>provided</scope>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
     </dependencies>
 </project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
similarity index 82%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
index 6399d8b..b63fed0 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannel.java
@@ -17,18 +17,14 @@
 
 package org.apache.dolphinscheduler.plugin.alert.slack;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
-/**
- * SlackAlertChannel
- */
-public class SlackAlertChannel implements AlertChannel {
-
+public final class SlackAlertChannel implements AlertChannel {
     @Override
     public AlertResult process(AlertInfo alertInfo) {
         AlertData alertData = alertInfo.getAlertData();
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
similarity index 61%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
index d569764..9819ed4 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactory.java
@@ -17,42 +17,41 @@
 
 package org.apache.dolphinscheduler.plugin.alert.slack;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
 
 import java.util.LinkedList;
 import java.util.List;
 
-/**
- * Slack alert factory, see {@link AlertChannelFactory}
- */
-public class SlackAlertChannelFactory implements AlertChannelFactory {
+import com.google.auto.service.AutoService;
 
+@AutoService(AlertChannelFactory.class)
+public final class SlackAlertChannelFactory implements AlertChannelFactory {
     @Override
-    public String getName() {
+    public String name() {
         return "Slack";
     }
 
     @Override
-    public List<PluginParams> getParams() {
+    public List<PluginParams> params() {
         List<PluginParams> paramsList = new LinkedList<>();
 
         InputParam webHookParam = InputParam.newBuilder(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME, SlackParamsConstants.SLACK_WEB_HOOK_URL)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .setPlaceholder("Input WebHook Url")
-                .build();
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .setPlaceholder("Input WebHook Url")
+                                            .build();
 
         InputParam botName = InputParam.newBuilder(SlackParamsConstants.SLACK_BOT_NAME, SlackParamsConstants.SLACK_BOT)
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .build())
-                .setPlaceholder("Input the bot username")
-                .build();
+                                       .addValidate(Validate.newBuilder()
+                                                            .setRequired(true)
+                                                            .build())
+                                       .setPlaceholder("Input the bot username")
+                                       .build();
 
         paramsList.add(webHookParam);
         paramsList.add(botName);
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
similarity index 81%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
index fd191c5..928eba6 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackParamsConstants.java
@@ -17,18 +17,17 @@
 
 package org.apache.dolphinscheduler.plugin.alert.slack;
 
-public class SlackParamsConstants {
-
-    private SlackParamsConstants() {
-
-    }
-
-    public static final String SLACK_WEB_HOOK_URL = "WebHook";
+public final class SlackParamsConstants {
+    public static final String SLACK_WEB_HOOK_URL = "$t('webhook')";
     public static final String SLACK_WEN_HOOK_URL_NAME = "webHook";
-    public static final String SLACK_BOT = "Username";
+    public static final String SLACK_BOT = "$t('Username')";
     public static final String SLACK_BOT_NAME = "username";
     public static final String TEXT = "text";
     public static final String ATTACHMENT = "attachments";
 
     public static final Integer MAX_SHOW_NUMBER = 100;
+
+    private SlackParamsConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
similarity index 88%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
index 21a8286..579fbaa 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/main/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSender.java
@@ -39,17 +39,14 @@ import java.util.Objects;
 import java.util.stream.Collectors;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 
-public class SlackSender {
+public final class SlackSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(SlackSender.class);
 
-    private static final Logger logger = LoggerFactory.getLogger(SlackSender.class);
-
-    private String webHookUrl;
-
-    private String botName;
+    private final String webHookUrl;
+    private final String botName;
 
     public SlackSender(Map<String, String> slackAlertParam) {
         webHookUrl = slackAlertParam.get(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME);
@@ -86,7 +83,7 @@ public class SlackSender {
             HttpEntity entity = response.getEntity();
             return EntityUtils.toString(entity, "UTF-8");
         } catch (Exception e) {
-            logger.error("Send message to slack error.", e);
+            log.error("Send message to slack error.", e);
             return "System Exception";
         }
     }
@@ -122,17 +119,17 @@ public class SlackSender {
         final int elementLen = maxLen;
         StringBuilder stringBuilder = new StringBuilder(200);
         stringBuilder.append(headers.stream()
-                .map(header -> generateString(header, elementLen, " "))
-                .collect(Collectors.joining("|")));
+                                    .map(header -> generateString(header, elementLen, " "))
+                                    .collect(Collectors.joining("|")));
         stringBuilder.append("\n");
         for (List<String> element : elements) {
             stringBuilder.append(element.stream()
-                    .map(lement -> generateString("", elementLen, "-"))
-                    .collect(Collectors.joining("|")));
+                                        .map(lement -> generateString("", elementLen, "-"))
+                                        .collect(Collectors.joining("|")));
             stringBuilder.append("\n");
             stringBuilder.append(element.stream()
-                    .map(e -> generateString(e, elementLen, " "))
-                    .collect(Collectors.joining("|")));
+                                        .map(e -> generateString(e, elementLen, " "))
+                                        .collect(Collectors.joining("|")));
             stringBuilder.append("\n");
         }
         return String.format("```%s```", stringBuilder);
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java
similarity index 87%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java
index e294365..21ba907 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackAlertChannelFactoryTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.slack;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 
 import java.util.List;
@@ -31,12 +31,12 @@ public class SlackAlertChannelFactoryTest {
 
     @Test
     public void testTestGetName() {
-        Assert.assertEquals("Slack", slackAlertChannelFactory.getName());
+        Assert.assertEquals("Slack", slackAlertChannelFactory.name());
     }
 
     @Test
     public void testGetParams() {
-        List<PluginParams> params = slackAlertChannelFactory.getParams();
+        List<PluginParams> params = slackAlertChannelFactory.params();
         Assert.assertEquals(2, params.size());
     }
 
@@ -45,4 +45,4 @@ public class SlackAlertChannelFactoryTest {
         AlertChannel alertChannel = slackAlertChannelFactory.create();
         Assert.assertTrue(alertChannel instanceof SlackAlertChannel);
     }
-}
\ No newline at end of file
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java
similarity index 95%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java
index a488026..c675aca 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-slack/src/test/java/org/apache/dolphinscheduler/plugin/alert/slack/SlackSenderTest.java
@@ -29,11 +29,11 @@ public class SlackSenderTest {
     public void testSendMessage() {
         Map<String, String> alertparam = new HashMap<>();
         alertparam.put(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME,
-                "https://hooks.slack.com/services/123456");
+            "https://hooks.slack.com/services/123456");
         alertparam.put(SlackParamsConstants.SLACK_BOT_NAME, "Dolphinscheduler");
 
         SlackSender slackSender = new SlackSender(alertparam);
         String response = slackSender.sendMessage("test title", "test content");
         Assert.assertNotEquals("ok", response);
     }
-}
\ No newline at end of file
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/pom.xml
similarity index 61%
copy from dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/pom.xml
index 99a0918..7258476 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-http/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/pom.xml
@@ -15,18 +15,19 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler-alert-plugin</artifactId>
+        <artifactId>dolphinscheduler-alert-plugins</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
+    <artifactId>dolphinscheduler-alert-wechat</artifactId>
+    <packaging>jar</packaging>
 
-    <artifactId>dolphinscheduler-alert-http</artifactId>
-    <packaging>dolphinscheduler-plugin</packaging>
     <dependencies>
-
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
@@ -47,30 +48,5 @@
             <artifactId>jackson-databind</artifactId>
             <scope>provided</scope>
         </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <type>jar</type>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
-
-    <build>
-        <finalName>dolphinscheduler-alert-http-${project.version}</finalName>
-    </build>
-
 </project>
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
similarity index 80%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
index 36cce09..94b43ea 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannel.java
@@ -17,18 +17,14 @@
 
 package org.apache.dolphinscheduler.plugin.alert.wechat;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 
 import java.util.Map;
 
-/**
- * WeChatAlertChannel
- */
-public class WeChatAlertChannel implements AlertChannel {
-
+public final class WeChatAlertChannel implements AlertChannel {
     @Override
     public AlertResult process(AlertInfo info) {
         AlertData alertData = info.getAlertData();
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java
new file mode 100644
index 0000000..299ffdd
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.plugin.alert.wechat;
+
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.ShowType;
+import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+import org.apache.dolphinscheduler.spi.params.base.Validate;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.google.auto.service.AutoService;
+
+@AutoService(AlertChannelFactory.class)
+public final class WeChatAlertChannelFactory implements AlertChannelFactory {
+    @Override
+    public String name() {
+        return "WeChat";
+    }
+
+    @Override
+    public List<PluginParams> params() {
+        InputParam corpIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_CORP_ID)
+                                           .setPlaceholder("please input corp id ")
+                                           .addValidate(Validate.newBuilder()
+                                                                .setRequired(true)
+                                                                .build())
+                                           .build();
+
+        InputParam secretParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_SECRET)
+                                           .setPlaceholder("please input secret ")
+                                           .addValidate(Validate.newBuilder()
+                                                                .setRequired(true)
+                                                                .build())
+                                           .build();
+
+        InputParam usersParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USERS)
+                                          .setPlaceholder("please input users ")
+                                          .addValidate(Validate.newBuilder()
+                                                               .setRequired(true)
+                                                               .build())
+                                          .build();
+
+        InputParam userSendMsgParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USER_SEND_MSG)
+                                                .setPlaceholder("please input corp id ")
+                                                .addValidate(Validate.newBuilder()
+                                                                     .setRequired(true)
+                                                                     .build())
+                                                .build();
+
+        InputParam agentIdParam = InputParam.newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID, WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_AGENT_ID)
+                                            .setPlaceholder("please input agent id ")
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .build())
+                                            .build();
+
+        RadioParam showType = RadioParam.newBuilder(AlertConstants.NAME_SHOW_TYPE, AlertConstants.SHOW_TYPE)
+                                        .addParamsOptions(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false))
+                                        .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false))
+                                        .setValue(ShowType.TABLE.getDescp())
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .build();
+
+        return Arrays.asList(corpIdParam, secretParam, usersParam, userSendMsgParam, agentIdParam, showType);
+    }
+
+    @Override
+    public AlertChannel create() {
+        return new WeChatAlertChannel();
+    }
+}
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java
similarity index 89%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java
index 9aec21b..141542f 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertConstants.java
@@ -17,15 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.wechat;
 
-/**
- * WeChatAlertConstants
- */
-public class WeChatAlertConstants {
-
-    private WeChatAlertConstants() {
-        throw new IllegalStateException(WeChatAlertConstants.class.getName());
-    }
-
+public final class WeChatAlertConstants {
     static final String MARKDOWN_QUOTE = ">";
 
     static final String MARKDOWN_ENTER = "\n";
@@ -35,4 +27,8 @@ public class WeChatAlertConstants {
     static final String WE_CHAT_PUSH_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}";
 
     static final String WE_CHAT_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={secret}";
+
+    private WeChatAlertConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
similarity index 69%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
index c254b27..e4c6381 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertParamsConstants.java
@@ -17,43 +17,21 @@
 
 package org.apache.dolphinscheduler.plugin.alert.wechat;
 
-/**
- * WeChatAlertParamsConstants
- */
-public class WeChatAlertParamsConstants {
-
-    private WeChatAlertParamsConstants() {
-        throw new IllegalStateException(WeChatAlertParamsConstants.class.getName());
-    }
-
-    static final String ENTERPRISE_WE_CHAT_CORP_ID = "corp.id";
-
+public final class WeChatAlertParamsConstants {
+    static final String ENTERPRISE_WE_CHAT_CORP_ID = "$t('corpId')";
     static final String NAME_ENTERPRISE_WE_CHAT_CORP_ID = "corpId";
-
-
-    static final String ENTERPRISE_WE_CHAT_SECRET = "secret";
-
+    static final String ENTERPRISE_WE_CHAT_SECRET = "$t('secret')";
     static final String NAME_ENTERPRISE_WE_CHAT_SECRET = "secret";
-
-    static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "team.send.msg";
-
+    static final String ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "$t('teamSendMsg')";
     static final String NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG = "teamSendMsg";
-
-
-    static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = "user.send.msg";
-
+    static final String ENTERPRISE_WE_CHAT_USER_SEND_MSG = "$t('userSendMsg')";
     static final String NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG = "userSendMsg";
-
-
-    static final String ENTERPRISE_WE_CHAT_AGENT_ID = "agent.id";
-
+    static final String ENTERPRISE_WE_CHAT_AGENT_ID = "$t('agentId')";
     static final String NAME_ENTERPRISE_WE_CHAT_AGENT_ID = "agentId";
-
-
-    static final String ENTERPRISE_WE_CHAT_USERS = "users";
-
-
+    static final String ENTERPRISE_WE_CHAT_USERS = "$t('users')";
     static final String NAME_ENTERPRISE_WE_CHAT_USERS = "users";
 
-
+    private WeChatAlertParamsConstants() {
+        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
similarity index 78%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
index 6944da6..1febc8b 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/main/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSender.java
@@ -17,15 +17,11 @@
 
 package org.apache.dolphinscheduler.plugin.alert.wechat;
 
-import static java.util.Objects.requireNonNull;
-
-import org.apache.dolphinscheduler.plugin.alert.wechat.exception.WeChatAlertException;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 import org.apache.dolphinscheduler.spi.utils.StringUtils;
-
 import org.apache.http.HttpEntity;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
@@ -34,41 +30,16 @@ import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
 
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * WeChatSender
- */
-public class WeChatSender {
-
-    private static Logger logger = LoggerFactory.getLogger(WeChatSender.class);
-
-    private String weChatAgentId;
-
-    private String weChatUsers;
-
-    private String weChatUserSendMsg;
-
-    private String weChatTokenUrlReplace;
-
-    private String weChatToken;
-
-    private String showType;
 
+import static java.util.Objects.requireNonNull;
 
+public final class WeChatSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(WeChatSender.class);
     private static final String MUST_NOT_NULL = " must not null";
     private static final String ALERT_STATUS = "false";
     private static final String AGENT_ID_REG_EXP = "{agentId}";
@@ -77,6 +48,12 @@ public class WeChatSender {
     private static final String CORP_ID_REGEX = "{corpId}";
     private static final String SECRET_REGEX = "{secret}";
     private static final String TOKEN_REGEX = "{token}";
+    private final String weChatAgentId;
+    private final String weChatUsers;
+    private final String weChatUserSendMsg;
+    private final String weChatTokenUrlReplace;
+    private final String weChatToken;
+    private final String showType;
 
     WeChatSender(Map<String, String> config) {
         weChatAgentId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID);
@@ -85,58 +62,14 @@ public class WeChatSender {
         String weChatSecret = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET);
         String weChatTokenUrl = WeChatAlertConstants.WE_CHAT_TOKEN_URL;
         weChatUserSendMsg = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG);
-        showType = config.get(AlertConstants.SHOW_TYPE);
-        requireNonNull(showType, AlertConstants.SHOW_TYPE + MUST_NOT_NULL);
+        showType = config.get(AlertConstants.NAME_SHOW_TYPE);
+        requireNonNull(showType, AlertConstants.NAME_SHOW_TYPE + MUST_NOT_NULL);
         weChatTokenUrlReplace = weChatTokenUrl
             .replace(CORP_ID_REGEX, weChatCorpId)
             .replace(SECRET_REGEX, weChatSecret);
         weChatToken = getToken();
     }
 
-    /**
-     * make user multi user message
-     *
-     * @param toUser the toUser
-     * @param agentId the agentId
-     * @param msg the msg
-     * @return Enterprise WeChat send message
-     */
-    private String makeUserSendMsg(Collection<String> toUser, String agentId, String msg) {
-        String listUser = mkString(toUser);
-        return weChatUserSendMsg.replace(USER_REG_EXP, listUser)
-            .replace(AGENT_ID_REG_EXP, agentId)
-            .replace(MSG_REG_EXP, msg);
-    }
-
-    /**
-     * send Enterprise WeChat
-     *
-     * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""}
-     */
-    public AlertResult sendEnterpriseWeChat(String title, String content) {
-        AlertResult alertResult;
-        List<String> userList = Arrays.asList(weChatUsers.split(","));
-        String data = markdownByAlert(title, content);
-        String msg = makeUserSendMsg(userList, weChatAgentId, data);
-        if (null == weChatToken) {
-            alertResult = new AlertResult();
-            alertResult.setMessage("send we chat alert fail,get weChat token error");
-            alertResult.setStatus(ALERT_STATUS);
-            return alertResult;
-        }
-        String enterpriseWeChatPushUrlReplace = WeChatAlertConstants.WE_CHAT_PUSH_URL.replace(TOKEN_REGEX, weChatToken);
-
-        try {
-            return checkWeChatSendMsgResult(post(enterpriseWeChatPushUrlReplace, msg));
-        } catch (Exception e) {
-            logger.info("send we chat alert msg  exception : {}", e.getMessage());
-            alertResult = new AlertResult();
-            alertResult.setMessage("send we chat alert fail");
-            alertResult.setStatus(ALERT_STATUS);
-        }
-        return alertResult;
-    }
-
     private static String post(String url, String data) throws IOException {
         try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
             HttpPost httpPost = new HttpPost(url);
@@ -150,7 +83,7 @@ public class WeChatSender {
             } finally {
                 response.close();
             }
-            logger.info("Enterprise WeChat send [{}], param:{}, resp:{}",
+            log.info("Enterprise WeChat send [{}], param:{}, resp:{}",
                 url, data, resp);
             return resp;
         }
@@ -166,8 +99,8 @@ public class WeChatSender {
     private static String markdownTable(String title, String content) {
         List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
         if (null == mapItemsList || mapItemsList.isEmpty()) {
-            logger.error("itemsList is null");
-            throw new WeChatAlertException("itemsList is null");
+            log.error("itemsList is null");
+            throw new RuntimeException("itemsList is null");
         }
         StringBuilder contents = new StringBuilder(200);
         for (LinkedHashMap mapItems : mapItemsList) {
@@ -199,7 +132,7 @@ public class WeChatSender {
         if (StringUtils.isNotEmpty(content)) {
             List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
             if (null == mapItemsList || mapItemsList.isEmpty()) {
-                logger.error("itemsList is null");
+                log.error("itemsList is null");
                 throw new RuntimeException("itemsList is null");
             }
 
@@ -220,31 +153,6 @@ public class WeChatSender {
         return null;
     }
 
-    /**
-     * Determine the mardown style based on the show type of the alert
-     *
-     * @return the markdown alert table/text
-     */
-    private String markdownByAlert(String title, String content) {
-        String result = "";
-        if (showType.equals(ShowType.TABLE.getDescp())) {
-            result = markdownTable(title, content);
-        } else if (showType.equals(ShowType.TEXT.getDescp())) {
-            result = markdownText(title, content);
-        }
-        return result;
-
-    }
-
-    private String getToken() {
-        try {
-            return get(weChatTokenUrlReplace);
-        } catch (IOException e) {
-            logger.info("we chat alert get token error{}", e.getMessage());
-        }
-        return null;
-    }
-
     private static String get(String url) throws IOException {
         String resp;
 
@@ -266,7 +174,6 @@ public class WeChatSender {
     }
 
     private static String mkString(Iterable<String> list) {
-
         if (null == list || StringUtils.isEmpty("|")) {
             return null;
         }
@@ -284,40 +191,19 @@ public class WeChatSender {
         return sb.toString();
     }
 
-    public static class WeChatSendMsgResponse {
-        private Integer errcode;
-        private String errmsg;
-
-        public Integer getErrcode() {
-            return errcode;
-        }
-
-        public void setErrcode(Integer errcode) {
-            this.errcode = errcode;
-        }
-
-        public String getErrmsg() {
-            return errmsg;
-        }
-
-        public void setErrmsg(String errmsg) {
-            this.errmsg = errmsg;
-        }
-    }
-
     private static AlertResult checkWeChatSendMsgResult(String result) {
         AlertResult alertResult = new AlertResult();
         alertResult.setStatus(ALERT_STATUS);
 
         if (null == result) {
             alertResult.setMessage("we chat send fail");
-            logger.info("send we chat msg error,resp is null");
+            log.info("send we chat msg error,resp is null");
             return alertResult;
         }
         WeChatSendMsgResponse sendMsgResponse = JSONUtils.parseObject(result, WeChatSendMsgResponse.class);
         if (null == sendMsgResponse) {
             alertResult.setMessage("we chat send fail");
-            logger.info("send we chat msg error,resp error");
+            log.info("send we chat msg error,resp error");
             return alertResult;
         }
         if (sendMsgResponse.errcode == 0) {
@@ -329,4 +215,132 @@ public class WeChatSender {
         alertResult.setMessage(sendMsgResponse.getErrmsg());
         return alertResult;
     }
+
+    /**
+     * make user multi user message
+     *
+     * @param toUser the toUser
+     * @param agentId the agentId
+     * @param msg the msg
+     * @return Enterprise WeChat send message
+     */
+    private String makeUserSendMsg(Collection<String> toUser, String agentId, String msg) {
+        String listUser = mkString(toUser);
+        return weChatUserSendMsg.replace(USER_REG_EXP, listUser)
+                                .replace(AGENT_ID_REG_EXP, agentId)
+                                .replace(MSG_REG_EXP, msg);
+    }
+
+    /**
+     * send Enterprise WeChat
+     *
+     * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""}
+     */
+    public AlertResult sendEnterpriseWeChat(String title, String content) {
+        AlertResult alertResult;
+        List<String> userList = Arrays.asList(weChatUsers.split(","));
+        String data = markdownByAlert(title, content);
+        String msg = makeUserSendMsg(userList, weChatAgentId, data);
+        if (null == weChatToken) {
+            alertResult = new AlertResult();
+            alertResult.setMessage("send we chat alert fail,get weChat token error");
+            alertResult.setStatus(ALERT_STATUS);
+            return alertResult;
+        }
+        String enterpriseWeChatPushUrlReplace = WeChatAlertConstants.WE_CHAT_PUSH_URL.replace(TOKEN_REGEX, weChatToken);
+
+        try {
+            return checkWeChatSendMsgResult(post(enterpriseWeChatPushUrlReplace, msg));
+        } catch (Exception e) {
+            log.info("send we chat alert msg  exception : {}", e.getMessage());
+            alertResult = new AlertResult();
+            alertResult.setMessage("send we chat alert fail");
+            alertResult.setStatus(ALERT_STATUS);
+        }
+        return alertResult;
+    }
+
+    /**
+     * Determine the mardown style based on the show type of the alert
+     *
+     * @return the markdown alert table/text
+     */
+    private String markdownByAlert(String title, String content) {
+        String result = "";
+        if (showType.equals(ShowType.TABLE.getDescp())) {
+            result = markdownTable(title, content);
+        } else if (showType.equals(ShowType.TEXT.getDescp())) {
+            result = markdownText(title, content);
+        }
+        return result;
+
+    }
+
+    private String getToken() {
+        try {
+            return get(weChatTokenUrlReplace);
+        } catch (IOException e) {
+            log.info("we chat alert get token error{}", e.getMessage());
+        }
+        return null;
+    }
+
+    static final class WeChatSendMsgResponse {
+        private Integer errcode;
+        private String errmsg;
+
+        public WeChatSendMsgResponse() {
+        }
+
+        public Integer getErrcode() {
+            return this.errcode;
+        }
+
+        public void setErrcode(Integer errcode) {
+            this.errcode = errcode;
+        }
+
+        public String getErrmsg() {
+            return this.errmsg;
+        }
+
+        public void setErrmsg(String errmsg) {
+            this.errmsg = errmsg;
+        }
+
+        public boolean equals(final Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (!(o instanceof WeChatSendMsgResponse)) {
+                return false;
+            }
+            final WeChatSendMsgResponse other = (WeChatSendMsgResponse) o;
+            final Object this$errcode = this.getErrcode();
+            final Object other$errcode = other.getErrcode();
+            if (this$errcode == null ? other$errcode != null : !this$errcode.equals(other$errcode)) {
+                return false;
+            }
+            final Object this$errmsg = this.getErrmsg();
+            final Object other$errmsg = other.getErrmsg();
+            if (this$errmsg == null ? other$errmsg != null : !this$errmsg.equals(other$errmsg)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int hashCode() {
+            final int PRIME = 59;
+            int result = 1;
+            final Object $errcode = this.getErrcode();
+            result = result * PRIME + ($errcode == null ? 43 : $errcode.hashCode());
+            final Object $errmsg = this.getErrmsg();
+            result = result * PRIME + ($errmsg == null ? 43 : $errmsg.hashCode());
+            return result;
+        }
+
+        public String toString() {
+            return "WeChatSender.WeChatSendMsgResponse(errcode=" + this.getErrcode() + ", errmsg=" + this.getErrmsg() + ")";
+        }
+    }
 }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
similarity index 92%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
index cc62d5a..04ecc36 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatAlertChannelFactoryTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.dolphinscheduler.plugin.alert.wechat;
 
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.utils.JSONUtils;
 
@@ -34,7 +34,7 @@ public class WeChatAlertChannelFactoryTest {
     @Test
     public void testGetParams() {
         WeChatAlertChannelFactory weChatAlertChannelFactory = new WeChatAlertChannelFactory();
-        List<PluginParams> params = weChatAlertChannelFactory.getParams();
+        List<PluginParams> params = weChatAlertChannelFactory.params();
         JSONUtils.toJsonString(params);
         Assert.assertEquals(6, params.size());
     }
diff --git a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
similarity index 72%
rename from dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
index 61010eb..f4934bf 100644
--- a/dolphinscheduler-alert-plugin/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-wechat/src/test/java/org/apache/dolphinscheduler/plugin/alert/wechat/WeChatSenderTest.java
@@ -17,17 +17,16 @@
 
 package org.apache.dolphinscheduler.plugin.alert.wechat;
 
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-
-import java.util.HashMap;
-import java.util.Map;
-
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * WeChatSenderTest
  */
@@ -36,24 +35,24 @@ public class WeChatSenderTest {
     private static Map<String, String> weChatConfig = new HashMap<>();
 
     private String content = "[{\"id\":\"69\","
-            +
-            "\"name\":\"UserBehavior-0--1193959466\","
-            +
-            "\"Job name\":\"Start workflow\","
-            +
-            "\"State\":\"SUCCESS\","
-            +
-            "\"Recovery\":\"NO\","
-            +
-            "\"Run time\":\"1\","
-            +
-            "\"Start time\": \"2018-08-06 10:31:34.0\","
-            +
-            "\"End time\": \"2018-08-06 10:31:49.0\","
-            +
-            "\"Host\": \"192.168.xx.xx\","
-            +
-            "\"Notify group\" :\"4\"}]";
+        +
+        "\"name\":\"UserBehavior-0--1193959466\","
+        +
+        "\"Job name\":\"Start workflow\","
+        +
+        "\"State\":\"SUCCESS\","
+        +
+        "\"Recovery\":\"NO\","
+        +
+        "\"Run time\":\"1\","
+        +
+        "\"Start time\": \"2018-08-06 10:31:34.0\","
+        +
+        "\"End time\": \"2018-08-06 10:31:49.0\","
+        +
+        "\"Host\": \"192.168.xx.xx\","
+        +
+        "\"Notify group\" :\"4\"}]";
 
     @Before
     public void initDingTalkConfig() {
@@ -62,12 +61,12 @@ public class WeChatSenderTest {
         weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID, "NAME_ENTERPRISE_WE_CHAT_CORP_ID");
         weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET, "NAME_ENTERPRISE_WE_CHAT_SECRET");
         weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USER_SEND_MSG, "{\"touser\":\"{toUser}\",\"agentid\":{agentId}"
-                +
-                ",\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"{msg}\"}}"
+            +
+            ",\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"{msg}\"}}"
         );
         weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS, "Kris");
         weChatConfig.put(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_TEAM_SEND_MSG, "msg");
-        weChatConfig.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp());
+        weChatConfig.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TABLE.getDescp());
     }
 
     @Test
@@ -80,7 +79,7 @@ public class WeChatSenderTest {
 
     @Test
     public void testSendWeChatTextMsg() {
-        weChatConfig.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp());
+        weChatConfig.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TEXT.getDescp());
         WeChatSender weChatSender = new WeChatSender(weChatConfig);
         AlertResult alertResult = weChatSender.sendEnterpriseWeChat("test", content);
         Assert.assertEquals("false", alertResult.getStatus());
diff --git a/dolphinscheduler-alert-plugin/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
similarity index 76%
rename from dolphinscheduler-alert-plugin/pom.xml
rename to dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
index 0c980aa..1499cd2 100644
--- a/dolphinscheduler-alert-plugin/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-plugins/pom.xml
@@ -15,16 +15,16 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert</artifactId>
         <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-
-    <groupId>org.apache.dolphinscheduler</groupId>
-    <artifactId>dolphinscheduler-alert-plugin</artifactId>
+    <artifactId>dolphinscheduler-alert-plugins</artifactId>
     <packaging>pom</packaging>
 
     <modules>
@@ -38,11 +38,9 @@
     </modules>
 
     <dependencies>
-        <!-- dolphinscheduler -->
         <dependency>
             <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-spi</artifactId>
-            <scope>provided</scope>
+            <artifactId>dolphinscheduler-alert-api</artifactId>
         </dependency>
     </dependencies>
 
diff --git a/dolphinscheduler-alert/pom.xml b/dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml
similarity index 59%
copy from dolphinscheduler-alert/pom.xml
copy to dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml
index 3bcccb1..2de2fc9 100644
--- a/dolphinscheduler-alert/pom.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/pom.xml
@@ -16,42 +16,56 @@
   ~ limitations under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.dolphinscheduler</groupId>
-        <artifactId>dolphinscheduler</artifactId>
+        <artifactId>dolphinscheduler-alert</artifactId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
-    <artifactId>dolphinscheduler-alert</artifactId>
+    <artifactId>dolphinscheduler-alert-server</artifactId>
     <name>${project.artifactId}</name>
     <packaging>jar</packaging>
 
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
     <dependencies>
         <!-- dolphinscheduler -->
         <dependency>
             <groupId>org.apache.dolphinscheduler</groupId>
             <artifactId>dolphinscheduler-remote</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-dao</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>log4j-api</artifactId>
-                    <groupId>org.apache.logging.log4j</groupId>
-                </exclusion>
-            </exclusions>
+            <artifactId>dolphinscheduler-alert-dingtalk</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-email</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-feishu</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-script</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-slack</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-alert-wechat</artifactId>
         </dependency>
 
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-dao</artifactId>
         </dependency>
 
         <dependency>
@@ -65,11 +79,6 @@
         </dependency>
 
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <exclusions>
@@ -91,35 +100,31 @@
         </dependency>
 
         <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-module-junit4</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <scope>test</scope>
         </dependency>
 
         <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-api-mockito2</artifactId>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.mockito</groupId>
-                    <artifactId>mockito-core</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>*.yaml</exclude>
+                        <exclude>*.yml</exclude>
+                        <exclude>*.xml</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertPluginManager.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertPluginManager.java
new file mode 100644
index 0000000..ca882ca
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertPluginManager.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.alert;
+
+import static java.lang.String.format;
+
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
+import org.apache.dolphinscheduler.common.enums.PluginType;
+import org.apache.dolphinscheduler.dao.PluginDao;
+import org.apache.dolphinscheduler.dao.entity.PluginDefine;
+import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
+import org.apache.dolphinscheduler.spi.params.base.PluginParams;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.springframework.stereotype.Component;
+
+@Component
+public final class AlertPluginManager {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(AlertPluginManager.class);
+
+    private final PluginDao pluginDao;
+
+    private final Map<Integer, AlertChannel> channelKeyedById = new HashMap<>();
+
+    public AlertPluginManager(PluginDao pluginDao) {
+        this.pluginDao = pluginDao;
+    }
+
+    @PostConstruct
+    public void installPlugin() {
+        final Set<String> names = new HashSet<>();
+
+        ServiceLoader.load(AlertChannelFactory.class).forEach(factory -> {
+            final String name = factory.name();
+
+            log.info("Registering alert plugin: {}", name);
+
+            if (!names.add(name)) {
+                throw new IllegalStateException(format("Duplicate alert plugins named '%s'", name));
+            }
+
+            final AlertChannel alertChannel = factory.create();
+
+            log.info("Registered alert plugin: {}", name);
+
+            final List<PluginParams> params = factory.params();
+            final String paramsJson = PluginParamsTransfer.transferParamsToJson(params);
+
+            final PluginDefine pluginDefine = new PluginDefine(name, PluginType.ALERT.getDesc(), paramsJson);
+            final int id = pluginDao.addOrUpdatePluginDefine(pluginDefine);
+
+            channelKeyedById.put(id, alertChannel);
+        });
+    }
+
+    public Optional<AlertChannel> getAlertChannel(int id) {
+        return Optional.ofNullable(channelKeyedById.get(id));
+    }
+
+    public int size() {
+        return channelKeyedById.size();
+    }
+}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessor.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertRequestProcessor.java
similarity index 56%
rename from dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessor.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertRequestProcessor.java
index 9421a97..0db7f70 100644
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessor.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertRequestProcessor.java
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.dolphinscheduler.alert.processor;
+package org.apache.dolphinscheduler.alert;
+
+import static com.google.common.base.Preconditions.checkArgument;
 
-import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
-import org.apache.dolphinscheduler.alert.runner.AlertSender;
-import org.apache.dolphinscheduler.dao.AlertDao;
 import org.apache.dolphinscheduler.remote.command.Command;
 import org.apache.dolphinscheduler.remote.command.CommandType;
 import org.apache.dolphinscheduler.remote.command.alert.AlertSendRequestCommand;
@@ -28,35 +27,33 @@ import org.apache.dolphinscheduler.remote.processor.NettyRequestProcessor;
 import org.apache.dolphinscheduler.remote.utils.JsonSerializer;
 
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
+import org.springframework.stereotype.Component;
 
 import io.netty.channel.Channel;
 
-public class AlertRequestProcessor implements NettyRequestProcessor {
+@Component
+public final class AlertRequestProcessor implements NettyRequestProcessor {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(AlertRequestProcessor.class);
 
-    private final Logger logger = LoggerFactory.getLogger(AlertRequestProcessor.class);
-    private final AlertDao alertDao;
-    private final AlertPluginManager alertPluginManager;
+    private final AlertSender alertSender;
 
-    public AlertRequestProcessor(AlertDao alertDao, AlertPluginManager alertPluginManager) {
-        this.alertDao = alertDao;
-        this.alertPluginManager = alertPluginManager;
+    public AlertRequestProcessor(AlertSender alertSender) {
+        this.alertSender = alertSender;
     }
 
     @Override
     public void process(Channel channel, Command command) {
-        Preconditions.checkArgument(CommandType.ALERT_SEND_REQUEST == command.getType(),
-                String.format("invalid command type : %s", command.getType()));
+        checkArgument(CommandType.ALERT_SEND_REQUEST == command.getType(), "invalid command type: %s", command.getType());
 
         AlertSendRequestCommand alertSendRequestCommand = JsonSerializer.deserialize(
-                command.getBody(), AlertSendRequestCommand.class);
-        logger.info("received command : {}", alertSendRequestCommand);
+            command.getBody(), AlertSendRequestCommand.class);
 
-        AlertSender alertSender = new AlertSender(alertDao, alertPluginManager);
-        AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(alertSendRequestCommand.getGroupId(), alertSendRequestCommand.getTitle(), alertSendRequestCommand.getContent());
-        channel.writeAndFlush(alertSendResponseCommand.convert2Command(command.getOpaque()));
+        log.info("Received command : {}", alertSendRequestCommand);
 
+        AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(
+            alertSendRequestCommand.getGroupId(),
+            alertSendRequestCommand.getTitle(),
+            alertSendRequestCommand.getContent());
+        channel.writeAndFlush(alertSendResponseCommand.convert2Command(command.getOpaque()));
     }
 }
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertSender.java
similarity index 70%
rename from dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertSender.java
index 726dcef..ebc57e8 100644
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/runner/AlertSender.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertSender.java
@@ -15,10 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.dolphinscheduler.alert.runner;
+package org.apache.dolphinscheduler.alert;
 
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertData;
+import org.apache.dolphinscheduler.alert.api.AlertInfo;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 import org.apache.dolphinscheduler.common.enums.AlertStatus;
 import org.apache.dolphinscheduler.common.utils.JSONUtils;
 import org.apache.dolphinscheduler.dao.AlertDao;
@@ -26,64 +28,50 @@ import org.apache.dolphinscheduler.dao.entity.Alert;
 import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
 import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand;
 import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseResult;
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertData;
-import org.apache.dolphinscheduler.spi.alert.AlertInfo;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import org.apache.commons.collections.CollectionUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
-public class AlertSender {
+import org.slf4j.Logger;
+import org.springframework.stereotype.Component;
 
-    private static final Logger logger = LoggerFactory.getLogger(AlertSender.class);
+@Component
+public final class AlertSender {
+    private static final Logger log = org.slf4j.LoggerFactory.getLogger(AlertSender.class);
 
-    private List<Alert> alertList;
-    private AlertDao alertDao;
+    private final AlertDao alertDao;
     private final AlertPluginManager alertPluginManager;
 
-    public AlertSender(AlertPluginManager alertPluginManager) {
-        this.alertPluginManager = alertPluginManager;
-    }
-
     public AlertSender(AlertDao alertDao, AlertPluginManager alertPluginManager) {
-        super();
         this.alertDao = alertDao;
         this.alertPluginManager = alertPluginManager;
     }
 
-    public AlertSender(List<Alert> alertList, AlertDao alertDao, AlertPluginManager alertPluginManager) {
-        super();
-        this.alertList = alertList;
-        this.alertDao = alertDao;
-        this.alertPluginManager = alertPluginManager;
-    }
-
-    public void run() {
-        for (Alert alert : alertList) {
+    public void send(List<Alert> alerts) {
+        for (Alert alert : alerts) {
             //get alert group from alert
             int alertGroupId = alert.getAlertGroupId();
             List<AlertPluginInstance> alertInstanceList = alertDao.listInstanceByAlertGroupId(alertGroupId);
             if (CollectionUtils.isEmpty(alertInstanceList)) {
-                logger.error("send alert msg fail,no bind plugin instance.");
+                log.error("send alert msg fail,no bind plugin instance.");
                 alertDao.updateAlert(AlertStatus.EXECUTION_FAILURE, "no bind plugin instance", alert.getId());
                 continue;
             }
             AlertData alertData = new AlertData();
             alertData.setId(alert.getId())
-                    .setContent(alert.getContent())
-                    .setLog(alert.getLog())
-                    .setTitle(alert.getTitle());
+                     .setContent(alert.getContent())
+                     .setLog(alert.getLog())
+                     .setTitle(alert.getTitle());
 
             for (AlertPluginInstance instance : alertInstanceList) {
 
                 AlertResult alertResult = this.alertResultHandler(instance, alertData);
                 AlertStatus alertStatus = Boolean.parseBoolean(String.valueOf(alertResult.getStatus())) ? AlertStatus.EXECUTION_SUCCESS : AlertStatus.EXECUTION_FAILURE;
                 alertDao.updateAlert(alertStatus, alertResult.getMessage(), alert.getId());
-
             }
         }
 
@@ -98,30 +86,28 @@ public class AlertSender {
      * @return AlertSendResponseCommand
      */
     public AlertSendResponseCommand syncHandler(int alertGroupId, String title, String content) {
-
         List<AlertPluginInstance> alertInstanceList = alertDao.listInstanceByAlertGroupId(alertGroupId);
         AlertData alertData = new AlertData();
         alertData.setContent(content)
-                .setTitle(title);
+                 .setTitle(title);
 
         boolean sendResponseStatus = true;
         List<AlertSendResponseResult> sendResponseResults = new ArrayList<>();
 
         if (CollectionUtils.isEmpty(alertInstanceList)) {
-            sendResponseStatus = false;
             AlertSendResponseResult alertSendResponseResult = new AlertSendResponseResult();
             String message = String.format("Alert GroupId %s send error : not found alert instance", alertGroupId);
-            alertSendResponseResult.setStatus(sendResponseStatus);
+            alertSendResponseResult.setStatus(false);
             alertSendResponseResult.setMessage(message);
             sendResponseResults.add(alertSendResponseResult);
-            logger.error("Alert GroupId {} send error : not found alert instance", alertGroupId);
-            return new AlertSendResponseCommand(sendResponseStatus, sendResponseResults);
+            log.error("Alert GroupId {} send error : not found alert instance", alertGroupId);
+            return new AlertSendResponseCommand(false, sendResponseResults);
         }
 
         for (AlertPluginInstance instance : alertInstanceList) {
             AlertResult alertResult = this.alertResultHandler(instance, alertData);
             AlertSendResponseResult alertSendResponseResult = new AlertSendResponseResult(
-                    Boolean.parseBoolean(String.valueOf(alertResult.getStatus())), alertResult.getMessage());
+                Boolean.parseBoolean(String.valueOf(alertResult.getStatus())), alertResult.getMessage());
             sendResponseStatus = sendResponseStatus && alertSendResponseResult.getStatus();
             sendResponseResults.add(alertSendResponseResult);
         }
@@ -137,15 +123,14 @@ public class AlertSender {
      * @return AlertResult
      */
     private AlertResult alertResultHandler(AlertPluginInstance instance, AlertData alertData) {
-        String pluginName = alertPluginManager.getPluginNameById(instance.getPluginDefineId());
-        AlertChannel alertChannel = alertPluginManager.getAlertChannelMap().get(pluginName);
+        Optional<AlertChannel> alertChannel = alertPluginManager.getAlertChannel(instance.getPluginDefineId());
         AlertResult alertResultExtend = new AlertResult();
         String pluginInstanceName = instance.getInstanceName();
-        if (alertChannel == null) {
+        if (!alertChannel.isPresent()) {
             String message = String.format("Alert Plugin %s send error : return value is null", pluginInstanceName);
             alertResultExtend.setStatus(String.valueOf(false));
             alertResultExtend.setMessage(message);
-            logger.error("Alert Plugin {} send error : not found plugin {}", pluginInstanceName, pluginName);
+            log.error("Alert Plugin {} send error : not found plugin {}", pluginInstanceName, instance.getPluginDefineId());
             return alertResultExtend;
         }
 
@@ -155,29 +140,27 @@ public class AlertSender {
         alertInfo.setAlertParams(paramsMap);
         AlertResult alertResult;
         try {
-            alertResult = alertChannel.process(alertInfo);
+            alertResult = alertChannel.get().process(alertInfo);
         } catch (Exception e) {
             alertResult = new AlertResult("false", e.getMessage());
-            logger.error("send alert error alert data id :{},", alertData.getId(), e);
+            log.error("send alert error alert data id :{},", alertData.getId(), e);
         }
 
-
         if (alertResult == null) {
             String message = String.format("Alert Plugin %s send error : return alertResult value is null", pluginInstanceName);
             alertResultExtend.setStatus(String.valueOf(false));
             alertResultExtend.setMessage(message);
-            logger.info("Alert Plugin {} send error : return alertResult value is null", pluginInstanceName);
+            log.info("Alert Plugin {} send error : return alertResult value is null", pluginInstanceName);
         } else if (!Boolean.parseBoolean(String.valueOf(alertResult.getStatus()))) {
             alertResultExtend.setStatus(String.valueOf(false));
             alertResultExtend.setMessage(alertResult.getMessage());
-            logger.info("Alert Plugin {} send error : {}", pluginInstanceName, alertResult.getMessage());
+            log.info("Alert Plugin {} send error : {}", pluginInstanceName, alertResult.getMessage());
         } else {
             String message = String.format("Alert Plugin %s send success", pluginInstanceName);
             alertResultExtend.setStatus(String.valueOf(true));
             alertResultExtend.setMessage(message);
-            logger.info("Alert Plugin {} send success", pluginInstanceName);
+            log.info("Alert Plugin {} send success", pluginInstanceName);
         }
         return alertResultExtend;
     }
-
 }
diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java
new file mode 100644
index 0000000..b3dfa62
--- /dev/null
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.alert;
+
+import static org.apache.dolphinscheduler.common.Constants.ALERT_RPC_PORT;
+
+import org.apache.dolphinscheduler.common.thread.Stopper;
+import org.apache.dolphinscheduler.dao.AlertDao;
+import org.apache.dolphinscheduler.dao.PluginDao;
+import org.apache.dolphinscheduler.dao.entity.Alert;
+import org.apache.dolphinscheduler.remote.NettyRemotingServer;
+import org.apache.dolphinscheduler.remote.command.CommandType;
+import org.apache.dolphinscheduler.remote.config.NettyServerConfig;
+
+import java.io.Closeable;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+
+@EnableAutoConfiguration
+@ComponentScan(value = {
+    "org.apache.dolphinscheduler.alert",
+    "org.apache.dolphinscheduler.dao"
+})
+public class AlertServer implements Closeable {
+    private static final Logger log = LoggerFactory.getLogger(AlertServer.class);
+
+    private final PluginDao pluginDao;
+    private final AlertDao alertDao;
+    private final AlertPluginManager alertPluginManager;
+    private final AlertSender alertSender;
+    private final AlertRequestProcessor alertRequestProcessor;
+
+    private NettyRemotingServer server;
+
+    public AlertServer(PluginDao pluginDao, AlertDao alertDao, AlertPluginManager alertPluginManager, AlertSender alertSender, AlertRequestProcessor alertRequestProcessor) {
+        this.pluginDao = pluginDao;
+        this.alertDao = alertDao;
+        this.alertPluginManager = alertPluginManager;
+        this.alertSender = alertSender;
+        this.alertRequestProcessor = alertRequestProcessor;
+    }
+
+    public static void main(String[] args) {
+        SpringApplication.run(AlertServer.class, args);
+    }
+
+    @PostConstruct
+    public void start() {
+        log.info("Starting Alert server");
+
+        checkTable();
+        startServer();
+
+        if (alertPluginManager.size() == 0) {
+            log.warn("No alert plugin, alert sender will exit.");
+            return;
+        }
+
+        Executors.newScheduledThreadPool(1)
+                 .scheduleAtFixedRate(new Sender(), 5, 5, TimeUnit.SECONDS);
+    }
+
+    @Override
+    @PreDestroy
+    public void close() {
+        server.close();
+    }
+
+    private void checkTable() {
+        if (!pluginDao.checkPluginDefineTableExist()) {
+            log.error("Plugin Define Table t_ds_plugin_define Not Exist . Please Create it First !");
+            System.exit(1);
+        }
+    }
+
+    private void startServer() {
+        NettyServerConfig serverConfig = new NettyServerConfig();
+        serverConfig.setListenPort(ALERT_RPC_PORT);
+
+        server = new NettyRemotingServer(serverConfig);
+        server.registerProcessor(CommandType.ALERT_SEND_REQUEST, alertRequestProcessor);
+        server.start();
+    }
+
+    final class Sender implements Runnable {
+        @Override
+        public void run() {
+            if (!Stopper.isRunning()) {
+                return;
+            }
+
+            try {
+                final List<Alert> alerts = alertDao.listPendingAlerts();
+                alertSender.send(alerts);
+            } catch (Exception e) {
+                log.error("Failed to send alert", e);
+            }
+        }
+    }
+}
diff --git a/dolphinscheduler-alert/src/main/resources/logback-alert.xml b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/logback-alert.xml
similarity index 95%
rename from dolphinscheduler-alert/src/main/resources/logback-alert.xml
rename to dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/logback-alert.xml
index 1718947..48b3c35 100644
--- a/dolphinscheduler-alert/src/main/resources/logback-alert.xml
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/logback-alert.xml
@@ -17,7 +17,7 @@
   -->
 
 <!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
-<configuration scan="true" scanPeriod="120 seconds"> <!--debug="true" -->
+<configuration scan="true" scanPeriod="120 seconds">
 
     <property name="log.base" value="logs"/>
     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
@@ -49,4 +49,4 @@
         <appender-ref ref="ALERTLOGFILE"/>
     </root>
 
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java
similarity index 57%
rename from dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java
index 5c31225..b1f8e54 100644
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/plugin/EmailAlertPluginTest.java
@@ -17,54 +17,62 @@
 
 package org.apache.dolphinscheduler.alert.plugin;
 
+import org.apache.dolphinscheduler.alert.AlertPluginManager;
+import org.apache.dolphinscheduler.alert.AlertSender;
 import org.apache.dolphinscheduler.alert.AlertServer;
-import org.apache.dolphinscheduler.alert.runner.AlertSender;
-import org.apache.dolphinscheduler.alert.utils.Constants;
+import org.apache.dolphinscheduler.alert.api.AlertConstants;
+import org.apache.dolphinscheduler.alert.api.ShowType;
 import org.apache.dolphinscheduler.common.enums.AlertStatus;
+import org.apache.dolphinscheduler.common.enums.ProfileType;
 import org.apache.dolphinscheduler.common.utils.JSONUtils;
-import org.apache.dolphinscheduler.common.utils.PropertyUtils;
 import org.apache.dolphinscheduler.dao.AlertDao;
-import org.apache.dolphinscheduler.dao.DaoFactory;
 import org.apache.dolphinscheduler.dao.PluginDao;
 import org.apache.dolphinscheduler.dao.entity.Alert;
 import org.apache.dolphinscheduler.dao.entity.AlertGroup;
 import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
 import org.apache.dolphinscheduler.dao.entity.PluginDefine;
-import org.apache.dolphinscheduler.spi.alert.AlertConstants;
-import org.apache.dolphinscheduler.spi.alert.ShowType;
-import org.apache.dolphinscheduler.spi.params.input.InputParam;
 import org.apache.dolphinscheduler.spi.params.PasswordParam;
 import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
-import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
 import org.apache.dolphinscheduler.spi.params.base.DataType;
 import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
 import org.apache.dolphinscheduler.spi.params.base.PluginParams;
 import org.apache.dolphinscheduler.spi.params.base.Validate;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginLoader;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginManagerConfig;
-import org.apache.dolphinscheduler.spi.utils.StringUtils;
+import org.apache.dolphinscheduler.spi.params.input.InputParam;
+import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
 
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.LinkedHashMap;
 import java.util.List;
 
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * test load and use alert plugin
- */
+@ActiveProfiles(ProfileType.H2)
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = AlertServer.class)
 public class EmailAlertPluginTest {
-
-    private AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
-    private PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class);
+    @Autowired
+    private AlertDao alertDao;
+    @Autowired
+    private PluginDao pluginDao;
+    @Autowired
+    private AlertPluginManager manager;
+    @Autowired
+    private AlertSender alertSender;
+
+    @BeforeClass
+    public static void setUpClass() {
+        System.setProperty("spring.profiles.active", "h2");
+    }
 
     @Test
     public void testRunSend() {
-
         //create alert group
         AlertGroup alertGroup = new AlertGroup();
         alertGroup.setDescription("test alert group 1");
@@ -78,7 +86,7 @@ public class EmailAlertPluginTest {
         map1.put("mysql service name", "mysql200");
         map1.put("mysql address", "192.168.xx.xx");
         map1.put("port", "3306");
-        map1.put(AlertConstants.SHOW_TYPE, ShowType.TEXT.getDescp());
+        map1.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TEXT.getDescp());
         map1.put("no index of number", "80");
         map1.put("database client connections", "190");
 
@@ -87,7 +95,7 @@ public class EmailAlertPluginTest {
         map2.put("mysql address", "192.168.xx.xx");
         map2.put("port", "3306");
         map2.put("no index of number", "10");
-        map1.put(AlertConstants.SHOW_TYPE, ShowType.TABLE.getDescp());
+        map1.put(AlertConstants.NAME_SHOW_TYPE, ShowType.TABLE.getDescp());
         map2.put("database client connections", "90");
 
         List<LinkedHashMap<String, Object>> maps = new ArrayList<>();
@@ -102,42 +110,20 @@ public class EmailAlertPluginTest {
         List<Alert> alertList = new ArrayList<>();
         alertList.add(alert1);
 
-        //load email alert plugin
-        AlertPluginManager alertPluginManager = new AlertPluginManager();
-        DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
-        String path = DolphinPluginLoader.class.getClassLoader().getResource("").getPath();
-        alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml");
-        if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR))) {
-            alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim());
-        }
-
-        if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY))) {
-            alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY).trim());
-        }
-
-        DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
-        try {
-            alertPluginLoader.loadPlugins();
-        } catch (Exception e) {
-            throw new RuntimeException("load Alert Plugin Failed !", e);
-        }
-
         //create email alert plugin instance
         AlertPluginInstance alertPluginInstance = new AlertPluginInstance();
         alertPluginInstance.setCreateTime(new Date());
         alertPluginInstance.setInstanceName("test email alert");
 
-        List<PluginDefine> pluginDefineList = pluginDao.getPluginDefineMapper().queryByNameAndType("Email", "alert");
-        if (pluginDefineList == null || pluginDefineList.size() == 0) {
+        PluginDefine pluginDefine = pluginDao.getPluginDefineMapper().queryByNameAndType("Email", "alert");
+        if (pluginDefine == null) {
             throw new RuntimeException("no alert plugin be load");
         }
-        PluginDefine pluginDefine = pluginDefineList.get(0);
         alertPluginInstance.setPluginDefineId(pluginDefine.getId());
         alertPluginInstance.setPluginInstanceParams(getEmailAlertParams());
         alertDao.getAlertPluginInstanceMapper().insert(alertPluginInstance);
 
-        AlertSender alertSender = new AlertSender(alertList, alertDao, alertPluginManager);
-        alertSender.run();
+        alertSender.send(alertList);
 
         Alert alertResult = alertDao.getAlertMapper().selectById(alert1.getId());
         Assert.assertNotNull(alertResult);
@@ -153,74 +139,74 @@ public class EmailAlertPluginTest {
 
         List<PluginParams> paramsList = new ArrayList<>();
         InputParam receivesParam = InputParam.newBuilder("receivers", "receivers")
-                .setValue("540957506@qq.com")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
+                                             .setValue("540957506@qq.com")
+                                             .addValidate(Validate.newBuilder().setRequired(true).build())
+                                             .build();
 
         InputParam mailSmtpHost = InputParam.newBuilder("mailServerHost", "mail.smtp.host")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("smtp.exmail.qq.com")
-                .build();
+                                            .addValidate(Validate.newBuilder().setRequired(true).build())
+                                            .setValue("smtp.exmail.qq.com")
+                                            .build();
 
         InputParam mailSmtpPort = InputParam.newBuilder("mailServerPort", "mail.smtp.port")
-                .addValidate(Validate.newBuilder()
-                        .setRequired(true)
-                        .setType(DataType.NUMBER.getDataType())
-                        .build())
-                .setValue(25)
-                .build();
+                                            .addValidate(Validate.newBuilder()
+                                                                 .setRequired(true)
+                                                                 .setType(DataType.NUMBER.getDataType())
+                                                                 .build())
+                                            .setValue(25)
+                                            .build();
 
         InputParam mailSender = InputParam.newBuilder("mailSender", "mail.sender")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("easyscheduler@analysys.com.cn")
-                .build();
+                                          .addValidate(Validate.newBuilder().setRequired(true).build())
+                                          .setValue("easyscheduler@analysys.com.cn")
+                                          .build();
 
         RadioParam enableSmtpAuth = RadioParam.newBuilder("enableSmtpAuth", "mail.smtp.auth")
-                .addParamsOptions(new ParamsOptions("YES", true, false))
-                .addParamsOptions(new ParamsOptions("NO", false, false))
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue(true)
-                .build();
+                                              .addParamsOptions(new ParamsOptions("YES", true, false))
+                                              .addParamsOptions(new ParamsOptions("NO", false, false))
+                                              .addValidate(Validate.newBuilder().setRequired(true).build())
+                                              .setValue(true)
+                                              .build();
 
         InputParam mailUser = InputParam.newBuilder("mailUser", "mail.user")
-                .setPlaceholder("if enable use authentication, you need input user")
-                .setValue("easyscheduler@analysys.com.cn")
-                .build();
+                                        .setPlaceholder("if enable use authentication, you need input user")
+                                        .setValue("easyscheduler@analysys.com.cn")
+                                        .build();
 
         PasswordParam mailPassword = PasswordParam.newBuilder("mailPasswd", "mail.passwd")
-                .setPlaceholder("if enable use authentication, you need input password")
-                .setValue("xxxxxxx")
-                .build();
+                                                  .setPlaceholder("if enable use authentication, you need input password")
+                                                  .setValue("xxxxxxx")
+                                                  .build();
 
         RadioParam enableTls = RadioParam.newBuilder("starttlsEnable", "mail.smtp.starttls.enable")
-                .addParamsOptions(new ParamsOptions("YES", true, false))
-                .addParamsOptions(new ParamsOptions("NO", false, false))
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue(true)
-                .build();
+                                         .addParamsOptions(new ParamsOptions("YES", true, false))
+                                         .addParamsOptions(new ParamsOptions("NO", false, false))
+                                         .addValidate(Validate.newBuilder().setRequired(true).build())
+                                         .setValue(true)
+                                         .build();
 
         RadioParam enableSsl = RadioParam.newBuilder("sslEnable", "mail.smtp.ssl.enable")
-                .addParamsOptions(new ParamsOptions("YES", true, false))
-                .addParamsOptions(new ParamsOptions("NO", false, false))
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue(false)
-                .build();
+                                         .addParamsOptions(new ParamsOptions("YES", true, false))
+                                         .addParamsOptions(new ParamsOptions("NO", false, false))
+                                         .addValidate(Validate.newBuilder().setRequired(true).build())
+                                         .setValue(false)
+                                         .build();
 
         InputParam sslTrust = InputParam.newBuilder("mailSmtpSslTrust", "mail.smtp.ssl.trust")
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .setValue("smtp.exmail.qq.com")
-                .build();
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .setValue("smtp.exmail.qq.com")
+                                        .build();
 
         List<ParamsOptions> emailShowTypeList = new ArrayList<>();
         emailShowTypeList.add(new ParamsOptions(ShowType.TABLE.getDescp(), ShowType.TABLE.getDescp(), false));
         emailShowTypeList.add(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false));
         emailShowTypeList.add(new ParamsOptions(ShowType.ATTACHMENT.getDescp(), ShowType.ATTACHMENT.getDescp(), false));
         emailShowTypeList.add(new ParamsOptions(ShowType.TABLEATTACHMENT.getDescp(), ShowType.TABLEATTACHMENT.getDescp(), false));
-        RadioParam showType = RadioParam.newBuilder(AlertConstants.SHOW_TYPE, "showType")
-                .setOptions(emailShowTypeList)
-                .setValue(ShowType.TABLE.getDescp())
-                .addValidate(Validate.newBuilder().setRequired(true).build())
-                .build();
+        RadioParam showType = RadioParam.newBuilder(AlertConstants.NAME_SHOW_TYPE, "showType")
+                                        .setOptions(emailShowTypeList)
+                                        .setValue(ShowType.TABLE.getDescp())
+                                        .addValidate(Validate.newBuilder().setRequired(true).build())
+                                        .build();
 
         paramsList.add(receivesParam);
         paramsList.add(mailSmtpHost);
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java
similarity index 77%
rename from dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java
index 052d2f3..20e6768 100644
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/processor/AlertRequestProcessorTest.java
@@ -17,7 +17,10 @@
 
 package org.apache.dolphinscheduler.alert.processor;
 
-import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
+import static org.mockito.Mockito.mock;
+
+import org.apache.dolphinscheduler.alert.AlertRequestProcessor;
+import org.apache.dolphinscheduler.alert.AlertSender;
 import org.apache.dolphinscheduler.dao.AlertDao;
 import org.apache.dolphinscheduler.remote.command.Command;
 import org.apache.dolphinscheduler.remote.command.CommandType;
@@ -26,30 +29,21 @@ import org.apache.dolphinscheduler.remote.command.alert.AlertSendRequestCommand;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.powermock.api.mockito.PowerMockito;
 
 import io.netty.channel.Channel;
 
-/**
- * alert request processor test
- */
 public class AlertRequestProcessorTest {
-
-    private AlertDao alertDao;
-    private AlertPluginManager alertPluginManager;
-
     private AlertRequestProcessor alertRequestProcessor;
 
     @Before
     public void before() {
-        alertDao = PowerMockito.mock(AlertDao.class);
-        alertPluginManager = PowerMockito.mock(AlertPluginManager.class);
-        alertRequestProcessor = new AlertRequestProcessor(alertDao, alertPluginManager);
+        final AlertDao alertDao = mock(AlertDao.class);
+        alertRequestProcessor = new AlertRequestProcessor(new AlertSender(alertDao, null));
     }
 
     @Test
     public void testProcess() {
-        Channel channel = PowerMockito.mock(Channel.class);
+        Channel channel = mock(Channel.class);
         AlertSendRequestCommand alertSendRequestCommand = new AlertSendRequestCommand(1, "title", "content");
         Command reqCommand = alertSendRequestCommand.convert2Command();
         Assert.assertEquals(CommandType.ALERT_SEND_REQUEST, reqCommand.getType());
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java
similarity index 60%
rename from dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java
rename to dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java
index 3b84bdb..160afeb 100644
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java
+++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/AlertSenderTest.java
@@ -17,34 +17,32 @@
 
 package org.apache.dolphinscheduler.alert.runner;
 
-import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.dolphinscheduler.alert.AlertPluginManager;
+import org.apache.dolphinscheduler.alert.AlertSender;
+import org.apache.dolphinscheduler.alert.api.AlertChannel;
+import org.apache.dolphinscheduler.alert.api.AlertResult;
 import org.apache.dolphinscheduler.dao.AlertDao;
 import org.apache.dolphinscheduler.dao.PluginDao;
 import org.apache.dolphinscheduler.dao.entity.Alert;
 import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
 import org.apache.dolphinscheduler.dao.entity.PluginDefine;
 import org.apache.dolphinscheduler.remote.command.alert.AlertSendResponseCommand;
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertResult;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Optional;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * alert sender test
- */
 public class AlertSenderTest {
-
     private static final Logger logger = LoggerFactory.getLogger(AlertSenderTest.class);
 
     private AlertDao alertDao;
@@ -55,10 +53,9 @@ public class AlertSenderTest {
 
     @Before
     public void before() {
-        alertDao = PowerMockito.mock(AlertDao.class);
-        pluginDao = PowerMockito.mock(PluginDao.class);
-        alertPluginManager = PowerMockito.mock(AlertPluginManager.class);
-
+        alertDao = mock(AlertDao.class);
+        pluginDao = mock(PluginDao.class);
+        alertPluginManager = mock(AlertPluginManager.class);
     }
 
     @Test
@@ -70,12 +67,12 @@ public class AlertSenderTest {
         alertSender = new AlertSender(alertDao, alertPluginManager);
 
         //1.alert instance does not exist
-        PowerMockito.when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(null);
+        when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(null);
 
         AlertSendResponseCommand alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
         Assert.assertFalse(alertSendResponseCommand.getResStatus());
         alertSendResponseCommand.getResResults().forEach(result ->
-                logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
+            logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
 
         //2.alert plugin does not exist
         int pluginDefineId = 1;
@@ -83,59 +80,52 @@ public class AlertSenderTest {
         String pluginInstanceName = "alert-instance-mail";
         List<AlertPluginInstance> alertInstanceList = new ArrayList<>();
         AlertPluginInstance alertPluginInstance = new AlertPluginInstance(
-                pluginDefineId, pluginInstanceParams, pluginInstanceName);
+            pluginDefineId, pluginInstanceParams, pluginInstanceName);
         alertInstanceList.add(alertPluginInstance);
-        PowerMockito.when(alertDao.listInstanceByAlertGroupId(1)).thenReturn(alertInstanceList);
+        when(alertDao.listInstanceByAlertGroupId(1)).thenReturn(alertInstanceList);
 
         String pluginName = "alert-plugin-mail";
         PluginDefine pluginDefine = new PluginDefine(pluginName, "1", null);
-        PowerMockito.when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
+        when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
 
         alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
         Assert.assertFalse(alertSendResponseCommand.getResStatus());
         alertSendResponseCommand.getResResults().forEach(result ->
-                logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
+            logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
 
         //3.alert result value is null
-        AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class);
-        PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(null);
-        Map<String, AlertChannel> alertChannelMap = new ConcurrentHashMap<>();
-        alertChannelMap.put(pluginName, alertChannelMock);
-        PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
-        PowerMockito.when(alertPluginManager.getPluginNameById(Mockito.anyInt())).thenReturn("alert-plugin-mail");
+        AlertChannel alertChannelMock = mock(AlertChannel.class);
+        when(alertChannelMock.process(Mockito.any())).thenReturn(null);
+        when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock));
 
         alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
         Assert.assertFalse(alertSendResponseCommand.getResStatus());
         alertSendResponseCommand.getResResults().forEach(result ->
-                logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
+            logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
 
         //4.abnormal information inside the alert plug-in code
         AlertResult alertResult = new AlertResult();
         alertResult.setStatus(String.valueOf(false));
         alertResult.setMessage("Abnormal information inside the alert plug-in code");
-        PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
-        alertChannelMap = new ConcurrentHashMap<>();
-        alertChannelMap.put(pluginName, alertChannelMock);
-        PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
+        when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
+        when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock));
 
         alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
         Assert.assertFalse(alertSendResponseCommand.getResStatus());
         alertSendResponseCommand.getResResults().forEach(result ->
-                logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
+            logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
 
         //5.alert plugin send success
         alertResult = new AlertResult();
         alertResult.setStatus(String.valueOf(true));
         alertResult.setMessage(String.format("Alert Plugin %s send success", pluginInstanceName));
-        PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
-        alertChannelMap = new ConcurrentHashMap<>();
-        alertChannelMap.put(pluginName, alertChannelMock);
-        PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
+        when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
+        when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock));
 
         alertSendResponseCommand = alertSender.syncHandler(alertGroupId, title, content);
         Assert.assertTrue(alertSendResponseCommand.getResStatus());
         alertSendResponseCommand.getResResults().forEach(result ->
-                logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
+            logger.info("alert send response result, status:{}, message:{}", result.getStatus(), result.getMessage()));
 
     }
 
@@ -151,33 +141,28 @@ public class AlertSenderTest {
         alert.setContent(content);
         alertList.add(alert);
 
-        alertSender = new AlertSender(alertList, alertDao, alertPluginManager);
+        alertSender = new AlertSender(alertDao, alertPluginManager);
 
         int pluginDefineId = 1;
         String pluginInstanceParams = "alert-instance-mail-params";
         String pluginInstanceName = "alert-instance-mail";
         List<AlertPluginInstance> alertInstanceList = new ArrayList<>();
         AlertPluginInstance alertPluginInstance = new AlertPluginInstance(
-                pluginDefineId, pluginInstanceParams, pluginInstanceName);
+            pluginDefineId, pluginInstanceParams, pluginInstanceName);
         alertInstanceList.add(alertPluginInstance);
-        PowerMockito.when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(alertInstanceList);
+        when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(alertInstanceList);
 
         String pluginName = "alert-plugin-mail";
         PluginDefine pluginDefine = new PluginDefine(pluginName, "1", null);
-        PowerMockito.when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
-        PowerMockito.when(alertPluginManager.getPluginNameById(1)).thenReturn("alert-instance-mail");
+        when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
 
         AlertResult alertResult = new AlertResult();
         alertResult.setStatus(String.valueOf(true));
         alertResult.setMessage(String.format("Alert Plugin %s send success", pluginInstanceName));
-        AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class);
-        PowerMockito.when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
-        ConcurrentHashMap alertChannelMap = new ConcurrentHashMap<>();
-        alertChannelMap.put(pluginName, alertChannelMock);
-        PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
+        AlertChannel alertChannelMock = mock(AlertChannel.class);
+        when(alertChannelMock.process(Mockito.any())).thenReturn(alertResult);
+        when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock));
         Assert.assertTrue(Boolean.parseBoolean(alertResult.getStatus()));
-        alertSender.run();
-
+        alertSender.send(alertList);
     }
-
 }
diff --git a/dolphinscheduler-alert/pom.xml b/dolphinscheduler-alert/pom.xml
index 3bcccb1..3460560 100644
--- a/dolphinscheduler-alert/pom.xml
+++ b/dolphinscheduler-alert/pom.xml
@@ -1,125 +1,50 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
+  ~ Licensed to Apache Software Foundation (ASF) under one or more contributor
+  ~ license agreements. See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright
+  ~ ownership. Apache Software Foundation (ASF) licenses this file to you under
+  ~ the Apache License, Version 2.0 (the "License"); you may
+  ~ not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
   ~
   ~     http://www.apache.org/licenses/LICENSE-2.0
   ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <groupId>org.apache.dolphinscheduler</groupId>
         <artifactId>dolphinscheduler</artifactId>
+        <groupId>org.apache.dolphinscheduler</groupId>
         <version>2.0.1-SNAPSHOT</version>
     </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>pom</packaging>
     <artifactId>dolphinscheduler-alert</artifactId>
-    <name>${project.artifactId}</name>
-    <packaging>jar</packaging>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
-    <dependencies>
-        <!-- dolphinscheduler -->
-        <dependency>
-            <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-remote</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.dolphinscheduler</groupId>
-            <artifactId>dolphinscheduler-dao</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>log4j-api</artifactId>
-                    <groupId>org.apache.logging.log4j</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
 
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
+    <modules>
+        <module>dolphinscheduler-alert-api</module>
+        <module>dolphinscheduler-alert-plugins</module>
+        <module>dolphinscheduler-alert-server</module>
+    </modules>
 
+    <dependencies>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
-
         <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>jsr305</artifactId>
-                    <groupId>com.google.code.findbugs</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-        </dependency>
-
-        <!--excel poi-->
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-module-junit4</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-api-mockito2</artifactId>
-            <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.mockito</groupId>
-                    <artifactId>mockito-core</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
-
 </project>
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java
deleted file mode 100644
index b0a8c03..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert;
-
-import static org.apache.dolphinscheduler.alert.utils.Constants.ALERT_PROPERTIES_PATH;
-import static org.apache.dolphinscheduler.common.Constants.ALERT_RPC_PORT;
-
-import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
-import org.apache.dolphinscheduler.alert.processor.AlertRequestProcessor;
-import org.apache.dolphinscheduler.alert.runner.AlertSender;
-import org.apache.dolphinscheduler.alert.utils.Constants;
-import org.apache.dolphinscheduler.common.thread.Stopper;
-import org.apache.dolphinscheduler.common.utils.PropertyUtils;
-import org.apache.dolphinscheduler.dao.AlertDao;
-import org.apache.dolphinscheduler.dao.DaoFactory;
-import org.apache.dolphinscheduler.dao.PluginDao;
-import org.apache.dolphinscheduler.dao.entity.Alert;
-import org.apache.dolphinscheduler.remote.NettyRemotingServer;
-import org.apache.dolphinscheduler.remote.command.CommandType;
-import org.apache.dolphinscheduler.remote.config.NettyServerConfig;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginLoader;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginManagerConfig;
-import org.apache.dolphinscheduler.spi.utils.StringUtils;
-
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-
-public class AlertServer {
-
-    private static final Logger logger = LoggerFactory.getLogger(AlertServer.class);
-
-    private final PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class);
-
-    private final AlertDao alertDao = DaoFactory.getDaoInstance(AlertDao.class);
-
-    private AlertPluginManager alertPluginManager;
-
-    public static final String ALERT_PLUGIN_BINDING = "alert.plugin.binding";
-
-    public static final String ALERT_PLUGIN_DIR = "alert.plugin.dir";
-
-    public static final String MAVEN_LOCAL_REPOSITORY = "maven.local.repository";
-
-    private NettyRemotingServer server;
-
-    private static class AlertServerHolder {
-        private static final AlertServer INSTANCE = new AlertServer();
-    }
-
-    public static AlertServer getInstance() {
-        return AlertServerHolder.INSTANCE;
-    }
-
-    private AlertServer() {
-
-    }
-
-    private void checkTable() {
-        if (!pluginDao.checkPluginDefineTableExist()) {
-            logger.error("Plugin Define Table t_ds_plugin_define Not Exist . Please Create it First !");
-            System.exit(1);
-        }
-    }
-
-    private void initPlugin() {
-        DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
-        alertPluginManagerConfig.setPlugins(PropertyUtils.getString(ALERT_PLUGIN_BINDING));
-        if (StringUtils.isNotBlank(PropertyUtils.getString(ALERT_PLUGIN_DIR))) {
-            alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim());
-        }
-
-        if (StringUtils.isNotBlank(PropertyUtils.getString(MAVEN_LOCAL_REPOSITORY))) {
-            alertPluginManagerConfig.setMavenLocalRepository(PropertyUtils.getString(MAVEN_LOCAL_REPOSITORY).trim());
-        }
-
-        alertPluginManager = new AlertPluginManager();
-        DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
-        try {
-            alertPluginLoader.loadPlugins();
-        } catch (Exception e) {
-            throw new RuntimeException("Load Alert Plugin Failed !", e);
-        }
-    }
-
-    private void initRemoteServer() {
-        NettyServerConfig serverConfig = new NettyServerConfig();
-        serverConfig.setListenPort(ALERT_RPC_PORT);
-        this.server = new NettyRemotingServer(serverConfig);
-        this.server.registerProcessor(CommandType.ALERT_SEND_REQUEST, new AlertRequestProcessor(alertDao, alertPluginManager));
-        this.server.start();
-    }
-
-    private void runSender() {
-        new Thread(new Sender()).start();
-    }
-
-    public void start() {
-        PropertyUtils.loadPropertyFile(ALERT_PROPERTIES_PATH);
-        checkTable();
-        initPlugin();
-        initRemoteServer();
-        logger.info("alert server ready start ");
-        runSender();
-    }
-
-    public void stop() {
-        this.server.close();
-        logger.info("alert server shut down");
-    }
-
-    final class Sender implements Runnable {
-        @Override
-        public void run() {
-            while (Stopper.isRunning()) {
-                try {
-                    Thread.sleep(Constants.ALERT_SCAN_INTERVAL);
-                } catch (InterruptedException e) {
-                    logger.error(e.getMessage(), e);
-                    Thread.currentThread().interrupt();
-                }
-                if (alertPluginManager == null || alertPluginManager.getAlertChannelMap().size() == 0) {
-                    logger.warn("No Alert Plugin . Cannot send alert info. ");
-                } else {
-                    List<Alert> alerts = alertDao.listWaitExecutionAlert();
-                    new AlertSender(alerts, alertDao, alertPluginManager).run();
-                }
-            }
-        }
-    }
-
-    public static void main(String[] args) {
-        AlertServer alertServer = AlertServer.getInstance();
-        alertServer.start();
-        Runtime.getRuntime().addShutdownHook(new Thread(alertServer::stop));
-    }
-
-}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java
deleted file mode 100644
index 02f4b0f..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert.plugin;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import org.apache.dolphinscheduler.common.enums.PluginType;
-import org.apache.dolphinscheduler.spi.plugin.AbstractDolphinPluginManager;
-import org.apache.dolphinscheduler.dao.DaoFactory;
-import org.apache.dolphinscheduler.dao.PluginDao;
-import org.apache.dolphinscheduler.dao.entity.PluginDefine;
-import org.apache.dolphinscheduler.spi.DolphinSchedulerPlugin;
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-import org.apache.dolphinscheduler.spi.alert.AlertChannelFactory;
-import org.apache.dolphinscheduler.spi.classloader.ThreadContextClassLoader;
-import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
-import org.apache.dolphinscheduler.spi.params.base.PluginParams;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * load the configured alert plugin and manager them
- */
-public class AlertPluginManager extends AbstractDolphinPluginManager {
-    private static final Logger logger = LoggerFactory.getLogger(AlertPluginManager.class);
-
-    private final Map<String, AlertChannelFactory> alertChannelFactoryMap = new ConcurrentHashMap<>();
-    private final Map<String, AlertChannel> alertChannelMap = new ConcurrentHashMap<>();
-
-    /**
-     * k->pluginDefineId v->pluginDefineName
-     */
-    private final Map<Integer, String> pluginDefineMap = new HashMap<>();
-
-    private final PluginDao pluginDao = DaoFactory.getDaoInstance(PluginDao.class);
-
-    private void addAlertChannelFactory(AlertChannelFactory alertChannelFactory) {
-        requireNonNull(alertChannelFactory, "alertChannelFactory is null");
-
-        if (alertChannelFactoryMap.putIfAbsent(alertChannelFactory.getName(), alertChannelFactory) != null) {
-            throw new IllegalArgumentException(format("Alert Plugin '%s' is already registered", alertChannelFactory.getName()));
-        }
-
-        try {
-            loadAlertChannel(alertChannelFactory.getName());
-        } catch (Exception e) {
-            throw new IllegalArgumentException(format("Alert Plugin '%s' is can not load .", alertChannelFactory.getName()));
-        }
-    }
-
-    private void loadAlertChannel(String name) {
-        requireNonNull(name, "name is null");
-
-        AlertChannelFactory alertChannelFactory = alertChannelFactoryMap.get(name);
-        checkState(alertChannelFactory != null, "Alert Plugin %s is not registered", name);
-
-        try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(alertChannelFactory.getClass().getClassLoader())) {
-            AlertChannel alertChannel = alertChannelFactory.create();
-            this.alertChannelMap.put(name, alertChannel);
-        }
-
-        logger.info("-- Loaded Alert Plugin {} --", name);
-    }
-
-    Map<String, AlertChannelFactory> getAlertChannelFactoryMap() {
-        return alertChannelFactoryMap;
-    }
-
-    public Map<String, AlertChannel> getAlertChannelMap() {
-        return alertChannelMap;
-    }
-
-    public String getPluginNameById(int id) {
-        return pluginDefineMap.get(id);
-    }
-
-    @Override
-    public void installPlugin(DolphinSchedulerPlugin dolphinSchedulerPlugin) {
-        for (AlertChannelFactory alertChannelFactory : dolphinSchedulerPlugin.getAlertChannelFactorys()) {
-            logger.info("Registering Alert Plugin '{}'", alertChannelFactory.getName());
-            this.addAlertChannelFactory(alertChannelFactory);
-            List<PluginParams> params = alertChannelFactory.getParams();
-            String nameEn = alertChannelFactory.getName();
-            String paramsJson = PluginParamsTransfer.transferParamsToJson(params);
-
-            PluginDefine pluginDefine = new PluginDefine(nameEn, PluginType.ALERT.getDesc(), paramsJson);
-            int id = pluginDao.addOrUpdatePluginDefine(pluginDefine);
-            pluginDefineMap.put(id, pluginDefine.getPluginName());
-        }
-    }
-}
diff --git a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java b/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java
deleted file mode 100644
index 077f7ac..0000000
--- a/dolphinscheduler-alert/src/main/java/org/apache/dolphinscheduler/alert/utils/Constants.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert.utils;
-
-/**
- * constants
- */
-public class Constants {
-    private Constants() {
-        throw new IllegalStateException("Constants class");
-    }
-
-    /**
-     * alert properties path
-     */
-    public static final String ALERT_PROPERTIES_PATH = "/alert.properties";
-
-    /** default alert plugin dir **/
-    public static final String ALERT_PLUGIN_PATH = "lib/plugin/alert";
-
-    public static final int ALERT_SCAN_INTERVAL = 5000;
-
-}
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/AlertServerTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/AlertServerTest.java
deleted file mode 100644
index 38fb6b0..0000000
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/AlertServerTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert;
-
-import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginLoader;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginManagerConfig;
-import org.apache.dolphinscheduler.alert.runner.AlertSender;
-import org.apache.dolphinscheduler.alert.utils.Constants;
-import org.apache.dolphinscheduler.dao.AlertDao;
-import org.apache.dolphinscheduler.dao.DaoFactory;
-import org.apache.dolphinscheduler.dao.PluginDao;
-import org.apache.dolphinscheduler.remote.NettyRemotingServer;
-import org.apache.dolphinscheduler.spi.alert.AlertChannel;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({AlertServer.class, DaoFactory.class})
-public class AlertServerTest {
-
-    @Before
-    public void before() {
-
-    }
-
-    @Test
-    public void testMain() throws Exception {
-        AlertDao alertDao = PowerMockito.mock(AlertDao.class);
-        PowerMockito.mockStatic(DaoFactory.class);
-        PowerMockito.when(DaoFactory.getDaoInstance(AlertDao.class)).thenReturn(alertDao);
-
-        PluginDao pluginDao = PowerMockito.mock(PluginDao.class);
-        PowerMockito.when(DaoFactory.getDaoInstance(PluginDao.class)).thenReturn(pluginDao);
-        PowerMockito.when(pluginDao.checkPluginDefineTableExist()).thenReturn(true);
-
-        AlertChannel alertChannelMock = PowerMockito.mock(AlertChannel.class);
-
-        AlertPluginManager alertPluginManager = PowerMockito.mock(AlertPluginManager.class);
-        PowerMockito.whenNew(AlertPluginManager.class).withNoArguments().thenReturn(alertPluginManager);
-        ConcurrentHashMap alertChannelMap = new ConcurrentHashMap<>();
-        alertChannelMap.put("pluginName", alertChannelMock);
-        PowerMockito.when(alertPluginManager.getPluginNameById(Mockito.anyInt())).thenReturn("pluginName");
-        PowerMockito.when(alertPluginManager.getAlertChannelMap()).thenReturn(alertChannelMap);
-
-        DolphinPluginManagerConfig alertPluginManagerConfig = PowerMockito.mock(DolphinPluginManagerConfig.class);
-        PowerMockito.whenNew(DolphinPluginManagerConfig.class).withNoArguments().thenReturn(alertPluginManagerConfig);
-
-        NettyRemotingServer nettyRemotingServer = PowerMockito.mock(NettyRemotingServer.class);
-        PowerMockito.whenNew(NettyRemotingServer.class).withAnyArguments().thenReturn(nettyRemotingServer);
-        AlertSender alertSender = PowerMockito.mock(AlertSender.class);
-        PowerMockito.whenNew(AlertSender.class).withAnyArguments().thenReturn(alertSender);
-
-        DolphinPluginLoader dolphinPluginLoader = PowerMockito.mock(DolphinPluginLoader.class);
-        PowerMockito.whenNew(DolphinPluginLoader.class).withAnyArguments().thenReturn(dolphinPluginLoader);
-
-        AlertServer alertServer = AlertServer.getInstance();
-        Assert.assertNotNull(alertServer);
-
-        new Thread(() -> alertServer.start()).start();
-
-        Thread.sleep(5 * Constants.ALERT_SCAN_INTERVAL);
-
-        alertServer.stop();
-    }
-
-}
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManagerTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManagerTest.java
deleted file mode 100644
index c451807..0000000
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManagerTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert.plugin;
-
-import org.apache.dolphinscheduler.alert.AlertServer;
-import org.apache.dolphinscheduler.alert.utils.Constants;
-import org.apache.dolphinscheduler.common.utils.PropertyUtils;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginLoader;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginManagerConfig;
-import org.apache.dolphinscheduler.spi.utils.StringUtils;
-
-import java.util.Objects;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * AlertPluginManager Tester.
- */
-public class AlertPluginManagerTest {
-
-    private static final Logger logger = LoggerFactory.getLogger(AlertPluginManagerTest.class);
-
-    @Test
-    public void testLoadPlugins() {
-        logger.info("begin test AlertPluginManagerTest");
-        AlertPluginManager alertPluginManager = new AlertPluginManager();
-        DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
-        String path = Objects.requireNonNull(DolphinPluginLoader.class.getClassLoader().getResource("")).getPath();
-        alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml");
-        if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR))) {
-            alertPluginManagerConfig.setInstalledPluginsDir(PropertyUtils.getString(AlertServer.ALERT_PLUGIN_DIR, Constants.ALERT_PLUGIN_PATH).trim());
-        }
-
-        if (StringUtils.isNotBlank(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY))) {
-            alertPluginManagerConfig.setMavenLocalRepository(Objects.requireNonNull(PropertyUtils.getString(AlertServer.MAVEN_LOCAL_REPOSITORY)).trim());
-        }
-
-        DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
-        try {
-            //alertPluginLoader.loadPlugins();
-        } catch (Exception e) {
-            throw new RuntimeException("load Alert Plugin Failed !", e);
-        }
-
-        Assert.assertNull(alertPluginManager.getAlertChannelFactoryMap().get("Email"));
-    }
-}
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoaderTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoaderTest.java
deleted file mode 100644
index aceb6a1..0000000
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/plugin/DolphinPluginLoaderTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert.plugin;
-
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginLoader;
-import org.apache.dolphinscheduler.spi.plugin.DolphinPluginManagerConfig;
-
-import java.util.Objects;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * DolphinPluginLoader Tester.
- */
-@Ignore("load jar fail,don't care plugin,should mock plugin")
-public class DolphinPluginLoaderTest {
-
-    /**
-     * Method: loadPlugins()
-     */
-    @Test
-    public void testLoadPlugins() {
-        AlertPluginManager alertPluginManager = new AlertPluginManager();
-        DolphinPluginManagerConfig alertPluginManagerConfig = new DolphinPluginManagerConfig();
-        String path = Objects.requireNonNull(DolphinPluginLoader.class.getClassLoader().getResource("")).getPath();
-        alertPluginManagerConfig.setPlugins(path + "../../../dolphinscheduler-alert-plugin/dolphinscheduler-alert-email/pom.xml");
-        DolphinPluginLoader alertPluginLoader = new DolphinPluginLoader(alertPluginManagerConfig, ImmutableList.of(alertPluginManager));
-        try {
-            alertPluginLoader.loadPlugins();
-        } catch (Exception e) {
-            throw new RuntimeException("load Alert Plugin Failed !", e);
-        }
-
-        Assert.assertNotNull(alertPluginManager.getAlertChannelFactoryMap().get("Email"));
-    }
-}
diff --git a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java b/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java
deleted file mode 100644
index d72c09a..0000000
--- a/dolphinscheduler-alert/src/test/java/org/apache/dolphinscheduler/alert/utils/PropertyUtilsTest.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.alert.utils;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.dolphinscheduler.common.enums.NodeType;
-import org.apache.dolphinscheduler.common.utils.PropertyUtils;
-
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Test PropertyUtils
- * and the resource path is src/test/resources/alert.properties.
- */
-public class PropertyUtilsTest {
-
-    private static final Logger logger = LoggerFactory.getLogger(PropertyUtilsTest.class);
-
-    /**
-     * Test getString
-     */
-    @Test
-    public void testGetString() {
-
-        //Expected "EMAIL"
-        String result = PropertyUtils.getString("alert.type");
-        logger.info(result);
-        assertEquals("EMAIL", result);
-
-        //Expected "xxx.xxx.test"
-        result = PropertyUtils.getString("mail.server.host");
-        assertEquals("xxx.xxx.test", result);
-
-        //If key is undefine in alert.properties, then return null
-        result = PropertyUtils.getString("abc");
-        assertNull(result);
-
-        //If key is null, then return null
-        result = PropertyUtils.getString(null);
-        assertNull(result);
-    }
-
-
-    /**
-     * Test getBoolean
-     */
-    @Test
-    public void testGetBoolean() {
-
-        //Expected true
-        Boolean result = PropertyUtils.getBoolean("mail.smtp.starttls.enable");
-        assertTrue(result);
-
-        //Expected false
-        result = PropertyUtils.getBoolean("mail.smtp.ssl.enable");
-        assertFalse(result);
-
-        //If key is undefine in alert.properties, then return null
-        result = PropertyUtils.getBoolean("abc");
-        assertFalse(result);
-
-        //If key is null, then return false
-        result = PropertyUtils.getBoolean(null);
-        assertFalse(result);
-    }
-
-    /**
-     * Test getLong
-     */
-    @Test
-    public void testGetLong() {
-
-        //Expected 25
-        long result = PropertyUtils.getLong("mail.server.port");
-        assertSame(25L, result);
-
-        //If key is null, then return -1
-        result = PropertyUtils.getLong(null);
-        assertSame(-1L, result);
-
-        //If key is undefine in alert.properties, then return -1
-        result = PropertyUtils.getLong("abc");
-        assertSame(-1L, result);
-
-        //If key is undefine in alert.properties, and there is a defaultval, then return defaultval
-        result = PropertyUtils.getLong("abc", 200);
-        assertEquals(200L, result);
-
-        //If the value can not parse to long ,it will log the error and return -1L
-        result = PropertyUtils.getLong("test.server.testnumber");
-        assertSame(-1L, result);
-    }
-
-    /**
-     * Test getDouble
-     */
-    @Test
-    public void testGetDouble() {
-
-        //Expected 3.0
-        double result = PropertyUtils.getDouble("test.server.factor", 3.0);
-        assertEquals(3.0, result, 0);
-
-        //If key is null, then return -1.0
-        result = PropertyUtils.getDouble(null, -1.0);
-        assertEquals(-1.0, result, 0);
-
-        //If key is undefine in alert.properties, then return -1
-        result = PropertyUtils.getDouble("abc", -1.0);
-        assertEquals(-1.0, result, 0);
-
-        //If key is undefine in alert.properties, and there is a defaultval, then return defaultval
-        result = PropertyUtils.getDouble("abc", 5.0);
-        assertEquals(5.0, result, 0);
-
-        //If the value can not parse to double ,it will log the error and return -1.0
-        result = PropertyUtils.getDouble("test.server.testnumber", -1.0);
-        assertEquals(-1.0, result, 0);
-    }
-
-    /**
-     * Test getArray
-     */
-    @Test
-    public void testGetArray() {
-
-        //Expected length 3
-        String[] result = PropertyUtils.getArray("test.server.list", ",");
-        assertEquals(result.length, 3);
-
-        //Equal array values
-        assertEquals("xxx.xxx.test1", result[0]);
-        assertEquals("xxx.xxx.test2", result[1]);
-        assertEquals("xxx.xxx.test3", result[2]);
-
-        //If key is null, then return -1
-        result = PropertyUtils.getArray(null, ",");
-        assertNull(result);
-
-        //If key is undefine in alert.properties, then return null
-        result = PropertyUtils.getArray("abc", ",");
-        assertNull(result);
-
-        //If splitStr is null, then return null
-        result = PropertyUtils.getArray("test.server.list", null);
-        assertNull(result);
-    }
-
-    /**
-     * test getInt
-     */
-    @Test
-    public void testGetInt() {
-
-        //Expected 25
-        int result = PropertyUtils.getInt("mail.server.port");
-        assertSame(25, result);
-
-        //If key is null, then return -1
-        result = PropertyUtils.getInt(null);
-        assertSame(-1, result);
-
-        //If key is undefine in alert.properties, then return -1
-        result = PropertyUtils.getInt("abc");
-        assertSame(-1, result);
-
-        //If key is undefine in alert.properties, and there is a defaultval, then return defaultval
-        result = PropertyUtils.getInt("abc", 300);
-        assertEquals(300, result);
-
-        //If the value can not parse to int ,it will log the error and return -1
-        result = PropertyUtils.getInt("test.server.testnumber");
-        assertSame(-1, result);
-    }
-
-    /**
-     * Test getEnum
-     */
-    @Test
-    public void testGetEnum() {
-
-        //Expected MASTER
-        NodeType nodeType = PropertyUtils.getEnum("test.server.enum1", NodeType.class, NodeType.WORKER);
-        assertEquals(NodeType.MASTER, nodeType);
-
-        //Expected DEAD_SERVER
-        nodeType = PropertyUtils.getEnum("test.server.enum2", NodeType.class, NodeType.WORKER);
-        assertEquals(NodeType.DEAD_SERVER, nodeType);
-
-        //If key is null, then return defaultval
-        nodeType = PropertyUtils.getEnum(null, NodeType.class, NodeType.WORKER);
-        assertEquals(NodeType.WORKER, nodeType);
-
-        //If the value doesn't define in enum ,it will log the error and return -1
-        nodeType = PropertyUtils.getEnum("test.server.enum3", NodeType.class, NodeType.WORKER);
-        assertEquals(NodeType.WORKER, nodeType);
-    }
-
-}
diff --git a/dolphinscheduler-api/pom.xml b/dolphinscheduler-api/pom.xml
index 3cdaf24..3e002de 100644
--- a/dolphinscheduler-api/pom.xml
+++ b/dolphinscheduler-api/pom.xml
@@ -34,6 +34,12 @@
             <artifactId>dolphinscheduler-service</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.dolphinscheduler</groupId>
+            <artifactId>dolphinscheduler-datasource-all</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
         <!--springboot-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -223,12 +229,6 @@
         </dependency>
 
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
             <groupId>org.powermock</groupId>
             <artifactId>powermock-module-junit4</artifactId>
             <scope>test</scope>
@@ -238,20 +238,35 @@
             <groupId>org.powermock</groupId>
             <artifactId>powermock-api-mockito2</artifactId>
             <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <version>${curator.test}</version>
             <exclusions>
                 <exclusion>
-                    <groupId>org.mockito</groupId>
-                    <artifactId>mockito-core</artifactId>
+                    <groupId>org.javassist</groupId>
+                    <artifactId>javassist</artifactId>
                 </exclusion>
             </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
             <scope>test</scope>
         </dependency>
-
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>*.yaml</exclude>
+                        <exclude>*.yml</exclude>
+                        <exclude>*.xml</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/ApiApplicationServer.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/ApiApplicationServer.java
index 6afb9d5..9d04857 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/ApiApplicationServer.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/ApiApplicationServer.java
@@ -17,21 +17,25 @@
 
 package org.apache.dolphinscheduler.api;
 
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.web.servlet.ServletComponentScan;
 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.FilterType;
 
-@SpringBootApplication
+@EnableAutoConfiguration
 @ServletComponentScan
-@ComponentScan(value = "org.apache.dolphinscheduler",
-        excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.apache.dolphinscheduler.server.*"))
+@ComponentScan(value = "org.apache.dolphinscheduler", excludeFilters = {
+    @ComponentScan.Filter(type = FilterType.REGEX, pattern = {
+        "org.apache.dolphinscheduler.server.*",
+        "org.apache.dolphinscheduler.alert.*"
+    })
+})
 public class ApiApplicationServer extends SpringBootServletInitializer {
 
     public static void main(String[] args) {
-        SpringApplication.run(ApiApplicationServer.class, args);
+        new SpringApplicationBuilder(ApiApplicationServer.class).profiles("api").run(args);
     }
 
 }
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java
index 34ce49a..a449a87 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataSourceController.java
@@ -34,13 +34,13 @@ import org.apache.dolphinscheduler.api.exceptions.ApiException;
 import org.apache.dolphinscheduler.api.service.DataSourceService;
 import org.apache.dolphinscheduler.api.utils.Result;
 import org.apache.dolphinscheduler.common.Constants;
-import org.apache.dolphinscheduler.common.datasource.BaseDataSourceParamDTO;
-import org.apache.dolphinscheduler.common.datasource.ConnectionParam;
-import org.apache.dolphinscheduler.common.datasource.DatasourceUtil;
-import org.apache.dolphinscheduler.common.enums.DbType;
 import org.apache.dolphinscheduler.common.utils.CommonUtils;
 import org.apache.dolphinscheduler.common.utils.ParameterUtils;
 import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.BaseDataSourceParamDTO;
+import org.apache.dolphinscheduler.plugin.datasource.api.utils.DatasourceUtil;
+import org.apache.dolphinscheduler.spi.datasource.ConnectionParam;
+import org.apache.dolphinscheduler.spi.enums.DbType;
 
 import java.util.Map;
 
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java
index dc1637e..d240847 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DataSourceService.java
@@ -18,10 +18,10 @@
 package org.apache.dolphinscheduler.api.service;
 
 import org.apache.dolphinscheduler.api.utils.Result;
-import org.apache.dolphinscheduler.common.datasource.BaseDataSourceParamDTO;
-import org.apache.dolphinscheduler.common.datasource.ConnectionParam;
-import org.apache.dolphinscheduler.common.enums.DbType;
 import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.BaseDataSourceParamDTO;
+import org.apache.dolphinscheduler.spi.datasource.ConnectionParam;
+import org.apache.dolphinscheduler.spi.enums.DbType;
 
 import java.util.Map;
 
diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataSourceServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataSourceServiceImpl.java
index bd29aa8..aa640b1 100644
--- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataSourceServiceImpl.java
+++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DataSourceServiceImpl.java
@@ -22,16 +22,17 @@ import org.apache.dolphinscheduler.api.service.DataSourceService;
 import org.apache.dolphinscheduler.api.utils.PageInfo;
 import org.apache.dolphinscheduler.api.utils.Result;
 import org.apache.dolphinscheduler.common.Constants;
-import org.apache.dolphinscheduler.common.datasource.BaseConnectionParam;
-import org.apache.dolphinscheduler.common.datasource.BaseDataSourceParamDTO;
-import org.apache.dolphinscheduler.common.datasource.ConnectionParam;
-import org.apache.dolphinscheduler.common.datasource.DatasourceUtil;
-import org.apache.dolphinscheduler.common.enums.DbType;
 import org.apache.dolphinscheduler.common.utils.JSONUtils;
 import org.apache.dolphinscheduler.dao.entity.DataSource;
 import org.apache.dolphinscheduler.dao.entity.User;
 import org.apache.dolphinscheduler.dao.mapper.DataSourceMapper;
 import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.BaseDataSourceParamDTO;
+import org.apache.dolphinscheduler.plugin.datasource.api.plugin.DataSourceClientProvider;
+import org.apache.dolphinscheduler.plugin.datasource.api.utils.DatasourceUtil;
+import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam;
+import org.apache.dolphinscheduler.spi.datasource.ConnectionParam;
+import org.apache.dolphinscheduler.spi.enums.DbType;
 
 import org.apache.commons.lang.StringUtils;
 
@@ -316,7 +317,7 @@ public class DataSourceServiceImpl extends BaseServiceImpl implements DataSource
     @Override
     public Result<Object> checkConnection(DbType type, ConnectionParam connectionParam) {
         Result<Object> result = new Result<>();
-        try (Connection connection = DatasourceUtil.getConnection(type, connectionParam)) {
+        try (Connection connection = DataSourceClientProvider.getInstance().getConnection(type, connectionParam)) {
             if (connection == null) {
                 putMsg(result, Status.CONNECTION_TEST_FAILURE);
                 return result;
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/HttpClientTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/HttpClientTest.java
deleted file mode 100644
index 6753d93..0000000
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/HttpClientTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dolphinscheduler.api;
-
-import org.apache.http.NameValuePair;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.util.EntityUtils;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-public class HttpClientTest {
-
-    private static final Logger logger = LoggerFactory.getLogger(HttpClientTest.class);
-
-    @Test
-    public  void doPOSTParam()throws Exception{
-        // create HttpClient
-        CloseableHttpClient httpclient = HttpClients.createDefault();
-
-        // create http post request
-        HttpPost httpPost = new HttpPost("http://localhost:12345/dolphinscheduler/projects/create");
-        httpPost.setHeader("token", "123");
-        // set parameters
-        List<NameValuePair> parameters = new ArrayList<NameValuePair>();
-        parameters.add(new BasicNameValuePair("projectName", "qzw"));
-        parameters.add(new BasicNameValuePair("desc", "qzw"));
-
-        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
-        httpPost.setEntity(formEntity);
-
-
-        CloseableHttpResponse response = null;
-        try {
-            // execute
-            response = httpclient.execute(httpPost);
-            // response status code 200
-            if (response.getStatusLine().getStatusCode() == 200) {
-                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
-                logger.info(content);
-            }
-        } finally {
-            if (response != null) {
-                response.close();
-            }
-            httpclient.close();
-        }
-    }
-
-    /**
-     * do get param path variables chinese
-     * @throws Exception
-     */
-    @Test
-    public  void doGETParamPathVariableAndChinese()throws Exception{
-        // create HttpClient
-        CloseableHttpClient httpclient = HttpClients.createDefault();
-
-        List<NameValuePair> parameters = new ArrayList<NameValuePair>();
-       // parameters.add(new BasicNameValuePair("pageSize", "10"));
-
-        // define the parameters of the request
-        URI uri = new URIBuilder("http://localhost:12345/dolphinscheduler/projects/%E5%85%A8%E9%83%A8%E6%B5%81%E7%A8%8B%E6%B5%8B%E8%AF%95/process/list")
-                .build();
-
-        // create http GET request
-        HttpGet httpGet = new HttpGet(uri);
-        httpGet.setHeader("token","10f5625a2a1cbf9aa710653796c5d764");
-        //response object
-        CloseableHttpResponse response = null;
-        try {
-            // execute http get request
-            response = httpclient.execute(httpGet);
-            // response status code 200
-            if (response.getStatusLine().getStatusCode() == 200) {
-                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
-                logger.info("start--------------->");
-                logger.info(content);
-                logger.info("end----------------->");
-            }
-        } finally {
-            if (response != null) {
-                response.close();
-            }
-            httpclient.close();
-        }
-    }
-
-    /**
-     *
-     * do get param
-     * @throws Exception
-     */
-    @Test
-    public  void doGETParam()throws Exception{
-        // create HttpClient
-        CloseableHttpClient httpclient = HttpClients.createDefault();
-
-        List<NameValuePair> parameters = new ArrayList<NameValuePair>();
-        parameters.add(new BasicNameValuePair("startDate", "2018-04-22 19:30:08"));
-        parameters.add(new BasicNameValuePair("endDate", "2028-04-22 19:30:08"));
-        parameters.add(new BasicNameValuePair("projectId", "0"));
-
-        // define the parameters of the request
-        URI uri = new URIBuilder("http://localhost:12345/dolphinscheduler/projects/analysis/queue-count")
-                 .setParameters(parameters)
-                .build();
-
-        // create http GET request
-        HttpGet httpGet = new HttpGet(uri);
-        httpGet.setHeader("token","2aef24c052c212fab9eec78848c2258b");
-        //response object
-        CloseableHttpResponse response = null;
-        try {
-            // execute http get request
-            response = httpclient.execute(httpGet);
-            // response status code 200
-            if (response.getStatusLine().getStatusCode() == 200) {
-                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
-                logger.info("start--------------->");
-                logger.info(content);
-                logger.info("end----------------->");
-            }
-        } finally {
-            if (response != null) {
-                response.close();
-            }
-            httpclient.close();
-        }
-    }
-
-}
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AbstractControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AbstractControllerTest.java
index dcc9da3..867f342 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AbstractControllerTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AbstractControllerTest.java
@@ -20,22 +20,30 @@ package org.apache.dolphinscheduler.api.controller;
 import org.apache.dolphinscheduler.api.ApiApplicationServer;
 import org.apache.dolphinscheduler.api.enums.Status;
 import org.apache.dolphinscheduler.api.service.SessionService;
+import org.apache.dolphinscheduler.api.service.UsersService;
 import org.apache.dolphinscheduler.common.Constants;
-import org.apache.dolphinscheduler.common.enums.UserType;
+import org.apache.dolphinscheduler.common.enums.ProfileType;
 import org.apache.dolphinscheduler.dao.entity.User;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.curator.test.TestingServer;
 
 import java.text.MessageFormat;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.annotation.PostConstruct;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@@ -44,8 +52,10 @@ import org.springframework.web.context.WebApplicationContext;
 /**
  * abstract controller test
  */
+@ActiveProfiles(value = {ProfileType.H2})
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = ApiApplicationServer.class)
+@Ignore
 public class AbstractControllerTest {
 
     public static final String SESSION_ID = "sessionId";
@@ -58,6 +68,9 @@ public class AbstractControllerTest {
     @Autowired
     private SessionService sessionService;
 
+    @Autowired
+    private UsersService usersService;
+
     protected User user;
 
     protected String sessionId;
@@ -66,7 +79,8 @@ public class AbstractControllerTest {
     public void setUp() {
         mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
 
-        createSession();
+        user = usersService.queryUser(1);
+        createSession(user);
     }
 
     @After
@@ -74,11 +88,7 @@ public class AbstractControllerTest {
         sessionService.signOut("127.0.0.1", user);
     }
 
-    private void createSession() {
-
-        User loginUser = new User();
-        loginUser.setId(1);
-        loginUser.setUserType(UserType.GENERAL_USER);
+    private void createSession(User loginUser) {
 
         user = loginUser;
 
@@ -102,4 +112,14 @@ public class AbstractControllerTest {
             result.put(Constants.MSG, status.getMsg());
         }
     }
+
+    @Configuration
+    @Profile(ProfileType.H2)
+    public static class RegistryServer {
+        @PostConstruct
+        public void startEmbedRegistryServer() throws Exception {
+            final TestingServer server = new TestingServer(true);
+            System.setProperty("registry.servers", server.getConnectString());
+        }
+    }
 }
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataSourceControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataSourceControllerTest.java
index e786373..f412ee6 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataSourceControllerTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataSourceControllerTest.java
@@ -24,8 +24,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 
 import org.apache.dolphinscheduler.api.enums.Status;
 import org.apache.dolphinscheduler.api.utils.Result;
-import org.apache.dolphinscheduler.common.datasource.mysql.MysqlDatasourceParamDTO;
 import org.apache.dolphinscheduler.common.utils.JSONUtils;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.mysql.MysqlDatasourceParamDTO;
 
 import java.util.HashMap;
 
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/EnvironmentControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/EnvironmentControllerTest.java
index 0b7233b..9842634 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/EnvironmentControllerTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/EnvironmentControllerTest.java
@@ -40,12 +40,8 @@ import org.springframework.util.MultiValueMap;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.google.common.base.Preconditions;
 
-/**
- * environment controller test
- */
 public class EnvironmentControllerTest extends AbstractControllerTest {
-
-    private static Logger logger = LoggerFactory.getLogger(EnvironmentControllerTest.class);
+    private static final Logger logger = LoggerFactory.getLogger(EnvironmentControllerTest.class);
 
     private String environmentCode;
 
@@ -60,6 +56,7 @@ public class EnvironmentControllerTest extends AbstractControllerTest {
         testCreateEnvironment();
     }
 
+    @Override
     @After
     public void after() throws Exception {
         testDeleteEnvironment();
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~dev b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~dev
deleted file mode 100644
index a96cec9..0000000
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java~dev
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.api.security;
-
-import org.apache.dolphinscheduler.api.ApiApplicationServer;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.TestPropertySource;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes = ApiApplicationServer.class)
-@TestPropertySource(properties = {
-        "security.authentication.type=LDAP",
-})
-public class SecurityConfigLDAPTest {
-
-    @Autowired
-    private SecurityConfig securityConfig;
-
-    @Test
-    public void testAuthenticator() {
-        Authenticator authenticator = securityConfig.authenticator();
-        Assert.assertNotNull(authenticator);
-    }
-}
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
index 9b68148..9fa7aa2 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
@@ -79,6 +79,7 @@ public class LdapAuthenticatorTest extends AbstractControllerTest {
     private String ip = "127.0.0.1";
     private UserType userType = UserType.GENERAL_USER;
 
+    @Override
     @Before
     public void setUp() {
         ldapAuthenticator = new LdapAuthenticator();
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
index 8cd435f..4cfdb0e 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
@@ -18,18 +18,23 @@
 package org.apache.dolphinscheduler.api.security.impl.ldap;
 
 import org.apache.dolphinscheduler.api.ApiApplicationServer;
+import org.apache.dolphinscheduler.common.enums.ProfileType;
 import org.apache.dolphinscheduler.common.enums.UserType;
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit4.SpringRunner;
 
+@Ignore
+@ActiveProfiles(ProfileType.H2)
 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = ApiApplicationServer.class)
 @TestPropertySource(
@@ -78,4 +83,4 @@ public class LdapServiceTest {
         String email2 = ldapService.ldapLogin("tesla", "error password");
         Assert.assertNull(email2);
     }
-}
\ No newline at end of file
+}
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticatorTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticatorTest.java
index 2ccc802..b58a4b5 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticatorTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticatorTest.java
@@ -57,6 +57,7 @@ public class PasswordAuthenticatorTest extends AbstractControllerTest {
     private User mockUser;
     private Session mockSession;
 
+    @Override
     @Before
     public void setUp() {
         authenticator = new PasswordAuthenticator();
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataAnalysisServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataAnalysisServiceTest.java
index f115370..292bf71 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataAnalysisServiceTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataAnalysisServiceTest.java
@@ -17,11 +17,6 @@
 
 package org.apache.dolphinscheduler.api.service;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-
 import org.apache.dolphinscheduler.api.dto.CommandStateCount;
 import org.apache.dolphinscheduler.api.enums.Status;
 import org.apache.dolphinscheduler.api.service.impl.DataAnalysisServiceImpl;
@@ -30,26 +25,9 @@ import org.apache.dolphinscheduler.common.enums.CommandType;
 import org.apache.dolphinscheduler.common.enums.ExecutionStatus;
 import org.apache.dolphinscheduler.common.enums.UserType;
 import org.apache.dolphinscheduler.common.utils.DateUtils;
-import org.apache.dolphinscheduler.dao.entity.CommandCount;
-import org.apache.dolphinscheduler.dao.entity.DefinitionGroupByUser;
-import org.apache.dolphinscheduler.dao.entity.ExecuteStatusCount;
-import org.apache.dolphinscheduler.dao.entity.Project;
-import org.apache.dolphinscheduler.dao.entity.User;
-import org.apache.dolphinscheduler.dao.mapper.CommandMapper;
-import org.apache.dolphinscheduler.dao.mapper.ErrorCommandMapper;
-import org.apache.dolphinscheduler.dao.mapper.ProcessDefinitionMapper;
-import org.apache.dolphinscheduler.dao.mapper.ProcessInstanceMapper;
-import org.apache.dolphinscheduler.dao.mapper.ProjectMapper;
-import org.apache.dolphinscheduler.dao.mapper.TaskInstanceMapper;
+import org.apache.dolphinscheduler.dao.entity.*;
+import org.apache.dolphinscheduler.dao.mapper.*;
 import org.apache.dolphinscheduler.service.process.ProcessService;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -61,6 +39,12 @@ import org.mockito.Mockito;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import java.text.MessageFormat;
+import java.util.*;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.*;
+
 /**
  * data analysis service test
  */
@@ -190,10 +174,10 @@ public class DataAnalysisServiceTest {
         Mockito.when(taskInstanceMapper.countTaskInstanceStateByUser(any(), any(), any())).thenReturn(
                 Collections.emptyList());
         result = dataAnalysisServiceImpl.countTaskStateByProject(user, 1, null, null);
-        assertThat(result.get(Constants.DATA_LIST)).extracting("totalCount").first().isEqualTo(0);
-        assertThat(result.get(Constants.DATA_LIST)).extracting("taskCountDtos").first().asList().hasSameSizeAs(
+        assertThat(result.get(Constants.DATA_LIST)).extracting("totalCount").isEqualTo(0);
+        assertThat(result.get(Constants.DATA_LIST)).extracting("taskCountDtos").asList().hasSameSizeAs(
                 ExecutionStatus.values());
-        assertThat(result.get(Constants.DATA_LIST)).extracting("taskCountDtos").first().asList().extracting(
+        assertThat(result.get(Constants.DATA_LIST)).extracting("taskCountDtos").asList().extracting(
                 "count").allMatch(count -> count.equals(0));
     }
 
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java
index 022ea24..d29b6be 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DataSourceServiceTest.java
@@ -21,22 +21,24 @@ import org.apache.dolphinscheduler.api.enums.Status;
 import org.apache.dolphinscheduler.api.service.impl.DataSourceServiceImpl;
 import org.apache.dolphinscheduler.api.utils.Result;
 import org.apache.dolphinscheduler.common.Constants;
-import org.apache.dolphinscheduler.common.datasource.ConnectionParam;
-import org.apache.dolphinscheduler.common.datasource.DatasourceUtil;
-import org.apache.dolphinscheduler.common.datasource.hive.HiveDataSourceParamDTO;
-import org.apache.dolphinscheduler.common.datasource.mysql.MysqlDatasourceParamDTO;
-import org.apache.dolphinscheduler.common.datasource.oracle.OracleDatasourceParamDTO;
-import org.apache.dolphinscheduler.common.datasource.postgresql.PostgreSqlDatasourceParamDTO;
-import org.apache.dolphinscheduler.common.enums.DbConnectType;
-import org.apache.dolphinscheduler.common.enums.DbType;
 import org.apache.dolphinscheduler.common.enums.UserType;
-import org.apache.dolphinscheduler.common.utils.CommonUtils;
 import org.apache.dolphinscheduler.common.utils.JSONUtils;
-import org.apache.dolphinscheduler.common.utils.PropertyUtils;
 import org.apache.dolphinscheduler.dao.entity.DataSource;
 import org.apache.dolphinscheduler.dao.entity.User;
 import org.apache.dolphinscheduler.dao.mapper.DataSourceMapper;
 import org.apache.dolphinscheduler.dao.mapper.DataSourceUserMapper;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.hive.HiveDataSourceParamDTO;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.mysql.MysqlDatasourceParamDTO;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.oracle.OracleDatasourceParamDTO;
+import org.apache.dolphinscheduler.plugin.datasource.api.datasource.postgresql.PostgreSqlDatasourceParamDTO;
+import org.apache.dolphinscheduler.plugin.datasource.api.plugin.DataSourceClientProvider;
+import org.apache.dolphinscheduler.plugin.datasource.api.utils.CommonUtils;
+import org.apache.dolphinscheduler.plugin.datasource.api.utils.DatasourceUtil;
+import org.apache.dolphinscheduler.plugin.datasource.api.utils.PasswordUtils;
+import org.apache.dolphinscheduler.spi.datasource.ConnectionParam;
+import org.apache.dolphinscheduler.spi.enums.DbConnectType;
+import org.apache.dolphinscheduler.spi.enums.DbType;
+import org.apache.dolphinscheduler.spi.utils.PropertyUtils;
 
 import java.sql.Connection;
 import java.util.ArrayList;
@@ -60,7 +62,7 @@ import org.powermock.modules.junit4.PowerMockRunner;
  */
 @RunWith(PowerMockRunner.class)
 @PowerMockIgnore({"sun.security.*", "javax.net.*"})
-@PrepareForTest({DatasourceUtil.class, CommonUtils.class})
+@PrepareForTest({DatasourceUtil.class, CommonUtils.class, DataSourceClientProvider.class, PasswordUtils.class})
 public class DataSourceServiceTest {
 
     @InjectMocks
@@ -307,13 +309,14 @@ public class DataSourceServiceTest {
         oracleDatasourceParamDTO.setConnectType(DbConnectType.ORACLE_SERVICE_NAME);
 
         ConnectionParam connectionParam = DatasourceUtil.buildConnectionParams(oracleDatasourceParamDTO);
-        String expected = "{\"user\":\"test\",\"password\":\"test\",\"address\":\"jdbc:oracle:thin:@//192.168.9.1:1521\","
-                + "\"database\":\"im\",\"jdbcUrl\":\"jdbc:oracle:thin:@//192.168.9.1:1521/im\",\"connectType\":\"ORACLE_SERVICE_NAME\"}";
+        String expected = "{\"user\":\"test\",\"password\":\"test\",\"address\":\"jdbc:oracle:thin:@//192.168.9.1:1521\",\"database\":\"im\",\"jdbcUrl\":\"jdbc:oracle:thin:@//192.168.9.1:1521/im\","
+                + "\"driverClassName\":\"oracle.jdbc.OracleDriver\",\"validationQuery\":\"select 1 from dual\",\"connectType\":\"ORACLE_SERVICE_NAME\"}";
         Assert.assertEquals(expected, JSONUtils.toJsonString(connectionParam));
 
         PowerMockito.mockStatic(CommonUtils.class);
+        PowerMockito.mockStatic(PasswordUtils.class);
         PowerMockito.when(CommonUtils.getKerberosStartupState()).thenReturn(true);
-        PowerMockito.when(CommonUtils.encodePassword(Mockito.anyString())).thenReturn("test");
+        PowerMockito.when(PasswordUtils.encodePassword(Mockito.anyString())).thenReturn("test");
         HiveDataSourceParamDTO hiveDataSourceParamDTO = new HiveDataSourceParamDTO();
         hiveDataSourceParamDTO.setHost("192.168.9.1");
         hiveDataSourceParamDTO.setPort(10000);
@@ -325,8 +328,8 @@ public class DataSourceServiceTest {
         hiveDataSourceParamDTO.setLoginUserKeytabPath("/opt/hdfs.headless.keytab");
         hiveDataSourceParamDTO.setLoginUserKeytabUsername("test2/hdfs-mycluster@ESZ.COM");
         connectionParam = DatasourceUtil.buildConnectionParams(hiveDataSourceParamDTO);
-        expected = "{\"user\":\"test\",\"password\":\"test\",\"address\":\"jdbc:hive2://192.168.9.1:10000\","
-                + "\"database\":\"im\",\"jdbcUrl\":\"jdbc:hive2://192.168.9.1:10000/im;principal=hive/hdfs-mycluster@ESZ.COM\",\"principal\":\"hive/hdfs-mycluster@ESZ.COM\","
+        expected = "{\"user\":\"test\",\"password\":\"test\",\"address\":\"jdbc:hive2://192.168.9.1:10000\",\"database\":\"im\",\"jdbcUrl\":\"jdbc:hive2://192.168.9.1:10000/im;"
+                + "principal=hive/hdfs-mycluster@ESZ.COM\",\"driverClassName\":\"org.apache.hive.jdbc.HiveDriver\",\"validationQuery\":\"select 1\",\"principal\":\"hive/hdfs-mycluster@ESZ.COM\","
                 + "\"javaSecurityKrb5Conf\":\"/opt/krb5.conf\",\"loginUserKeytabUsername\":\"test2/hdfs-mycluster@ESZ.COM\",\"loginUserKeytabPath\":\"/opt/hdfs.headless.keytab\"}";
         Assert.assertEquals(expected, JSONUtils.toJsonString(connectionParam));
 
@@ -346,8 +349,8 @@ public class DataSourceServiceTest {
         mysqlDatasourceParamDTO.setPassword("123456");
         mysqlDatasourceParamDTO.setOther(other);
         ConnectionParam connectionParam = DatasourceUtil.buildConnectionParams(mysqlDatasourceParamDTO);
-        String expected = "{\"user\":\"test\",\"password\":\"IUAjJCVeJipNVEl6TkRVMg==\",\"address\":\"jdbc:mysql://192.168.9.1:1521\","
-                + "\"database\":\"im\",\"jdbcUrl\":\"jdbc:mysql://192.168.9.1:1521/im\"}";
+        String expected = "{\"user\":\"test\",\"password\":\"IUAjJCVeJipNVEl6TkRVMg==\",\"address\":\"jdbc:mysql://192.168.9.1:1521\",\"database\":\"im\",\"jdbcUrl\":\"jdbc:mysql://192.168.9.1:1521/"
+                + "im\",\"driverClassName\":\"com.mysql.jdbc.Driver\",\"validationQuery\":\"select 1\",\"props\":{\"autoDeserialize\":\"yes\",\"allowUrlInLocalInfile\":\"true\"}}";
         Assert.assertEquals(expected, JSONUtils.toJsonString(connectionParam));
 
         PropertyUtils.setValue(Constants.DATASOURCE_ENCRYPTION_ENABLE, "false");
@@ -358,8 +361,8 @@ public class DataSourceServiceTest {
         mysqlDatasourceParamDTO.setUserName("test");
         mysqlDatasourceParamDTO.setPassword("123456");
         connectionParam = DatasourceUtil.buildConnectionParams(mysqlDatasourceParamDTO);
-        expected = "{\"user\":\"test\",\"password\":\"123456\",\"address\":\"jdbc:mysql://192.168.9.1:1521\","
-                + "\"database\":\"im\",\"jdbcUrl\":\"jdbc:mysql://192.168.9.1:1521/im\"}";
+        expected = "{\"user\":\"test\",\"password\":\"123456\",\"address\":\"jdbc:mysql://192.168.9.1:1521\",\"database\":\"im\","
+                + "\"jdbcUrl\":\"jdbc:mysql://192.168.9.1:1521/im\",\"driverClassName\":\"com.mysql.jdbc.Driver\",\"validationQuery\":\"select 1\"}";
         Assert.assertEquals(expected, JSONUtils.toJsonString(connectionParam));
     }
 
@@ -396,12 +399,15 @@ public class DataSourceServiceTest {
         ConnectionParam connectionParam = DatasourceUtil.buildConnectionParams(postgreSqlDatasourceParam);
 
         PowerMockito.mockStatic(DatasourceUtil.class);
+        PowerMockito.mockStatic(DataSourceClientProvider.class);
+        DataSourceClientProvider clientProvider = PowerMockito.mock(DataSourceClientProvider.class);
+        PowerMockito.when(DataSourceClientProvider.getInstance()).thenReturn(clientProvider);
 
         Result result = dataSourceService.checkConnection(dataSourceType, connectionParam);
         Assert.assertEquals(Status.CONNECTION_TEST_FAILURE.getCode(), result.getCode().intValue());
 
         Connection connection = PowerMockito.mock(Connection.class);
-        PowerMockito.when(DatasourceUtil.getConnection(Mockito.any(), Mockito.any())).thenReturn(connection);
+        PowerMockito.when(clientProvider.getConnection(Mockito.any(), Mockito.any())).thenReturn(connection);
         result = dataSourceService.checkConnection(dataSourceType, connectionParam);
         Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue());
 
diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java
index 50e0849..344ea89 100644
--- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java
+++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/MonitorServiceTest.java
@@ -20,10 +20,10 @@ package org.apache.dolphinscheduler.api.service;
 import org.apache.dolphinscheduler.api.enums.Status;
 import org.apache.dolphinscheduler.api.service.impl.MonitorServiceImpl;
 import org.apache.dolphinscheduler.common.Constants;
-import org.apache.dolphinscheduler.common.enums.DbType;
 import org.apache.dolphinscheduler.common.model.Server;
 import org.apache.dolphinscheduler.dao.MonitorDBDao;
 import org.apache.dolphinscheduler.dao.entity.MonitorRecord;
+import org.apache.dolphinscheduler.spi.enums.DbType;
 
 import org.apache.commons.collections.CollectionUtils;
 
diff --git a/dolphinscheduler-common/pom.xml b/dolphinscheduler-common/pom.xml
index ec114ed..f8600e3 100644
--- a/dolphinscheduler-common/pom.xml
+++ b/dolphinscheduler-common/pom.xml
@@ -27,10 +27,6 @@
     <name>dolphinscheduler-common</name>
 
     <packaging>jar</packaging>
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <codehaus.janino.version>3.1.0</codehaus.janino.version>
-    </properties>
     <dependencies>
         <!-- dolphinscheduler -->
         <dependency>
@@ -43,14 +39,6 @@
             <artifactId>httpclient</artifactId>
         </dependency>
         <dependency>
-            <groupId>io.airlift.resolver</groupId>
-            <artifactId>resolver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.sonatype.aether</groupId>
-            <artifactId>aether-api</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.ow2.asm</groupId>
             <artifactId>asm</artifactId>
         </dependency>
@@ -66,16 +54,9 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
-            <type>jar</type>
             <scope>test</scope>
         </dependency>
 
@@ -89,19 +70,6 @@
             <groupId>org.powermock</groupId>
             <artifactId>powermock-api-mockito2</artifactId>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.mockito</groupId>
-                    <artifactId>mockito-core</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jacoco</groupId>
-            <artifactId>org.jacoco.agent</artifactId>
-            <classifier>runtime</classifier>
-            <scope>test</scope>
         </dependency>
 
         <dependency>
@@ -625,11 +593,6 @@
         </dependency>
 
         <dependency>
-            <groupId>org.codehaus.janino</groupId>
-            <artifactId>janino</artifactId>
-            <version>${codehaus.janino.version}</version>
-        </dependency>
-        <dependency>
             <groupId>com.github.rholder</groupId>
             <artifactId>guava-retrying</artifactId>
             <exclusions>
@@ -646,7 +609,6 @@
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-all</artifactId>
-            <scope>compile</scope>
         </dependency>
     </dependencies>
 </project>
diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
index bebfa29..56494d3 100644
--- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
+++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
@@ -467,39 +467,37 @@ public final class Constants {
 
     public static final String SPRING_DATASOURCE_PASSWORD = "spring.datasource.password";
 
-    public static final String SPRING_DATASOURCE_VALIDATION_QUERY_TIMEOUT = "spring.datasource.validationQueryTimeout";
-
-    public static final String SPRING_DATASOURCE_INITIAL_SIZE = "spring.datasource.initialSize";
+    public static final String SPRING_DATASOURCE_CONNECTION_TIMEOUT = "spring.datasource.connectionTimeout";
 
     public static final String SPRING_DATASOURCE_MIN_IDLE = "spring.datasource.minIdle";
 
     public static final String SPRING_DATASOURCE_MAX_ACTIVE = "spring.datasource.maxActive";
 
-    public static final String SPRING_DATASOURCE_MAX_WAIT = "spring.datasource.maxWait";
-
-    public static final String SPRING_DATASOURCE_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "spring.datasource.timeBetweenEvictionRunsMillis";
+    public static final String SPRING_DATASOURCE_IDLE_TIMEOUT = "spring.datasource.idleTimeout";
 
-    public static final String SPRING_DATASOURCE_TIME_BETWEEN_CONNECT_ERROR_MILLIS = "spring.datasource.timeBetweenConnectErrorMillis";
+    public static final String SPRING_DATASOURCE_MAX_LIFE_TIME = "spring.datasource.maxLifetime";
 
-    public static final String SPRING_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS = "spring.datasource.minEvictableIdleTimeMillis";
+    public static final String SPRING_DATASOURCE_VALIDATION_TIMEOUT = "spring.datasource.validationTimeout";
 
     public static final String SPRING_DATASOURCE_VALIDATION_QUERY = "spring.datasource.validationQuery";
 
-    public static final String SPRING_DATASOURCE_TEST_WHILE_IDLE = "spring.datasource.testWhileIdle";
+    public static final String SPRING_DATASOURCE_LEAK_DETECTION_THRESHOLD = "spring.datasource.leakDetectionThreshold";
 
-    public static final String SPRING_DATASOURCE_TEST_ON_BORROW = "spring.datasource.testOnBorrow";
+    public static final String SPRING_DATASOURCE_INITIALIZATION_FAIL_TIMEOUT = "spring.datasource.initializationFailTimeout";
 
-    public static final String SPRING_DATASOURCE_TEST_ON_RETURN = "spring.datasource.testOnReturn";
+    public static final String SPRING_DATASOURCE_IS_AUTOCOMMIT = "spring.datasource.isAutoCommit";
 
-    public static final String SPRING_DATASOURCE_POOL_PREPARED_STATEMENTS = "spring.datasource.poolPreparedStatements";
+    public static final String SPRING_DATASOURCE_CACHE_PREP_STMTS = "spring.datasource.cachePrepStmts";
 
-    public static final String SPRING_DATASOURCE_DEFAULT_AUTO_COMMIT = "spring.datasource.defaultAutoCommit";
+    public static final String SPRING_DATASOURCE_PREP_STMT_CACHE_SIZE = "spring.datasource.prepStmtCacheSize";
 
-    public static final String SPRING_DATASOURCE_KEEP_ALIVE = "spring.datasource.keepAlive";
+    public static final String SPRING_DATASOURCE_PREP_STMT_CACHE_SQL_LIMIT = "spring.datasource.prepStmtCacheSqlLimit";
 
-    public static final String SPRING_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = "spring.datasource.maxPoolPreparedStatementPerConnectionSize";
+    public static final String CACHE_PREP_STMTS = "cachePrepStmts";
 
-    public static final String DEVELOPMENT = "development";
+    public static final String PREP_STMT_CACHE_SIZE = "prepStmtCacheSize";
+
+    public static final String PREP_STMT_CACHE_SQL_LIMIT = "prepStmtCacheSqlLimit";
 
     public static final String QUARTZ_PROPERTIES_PATH = "quartz.properties";
 
@@ -948,6 +946,19 @@ public final class Constants {
     public static final String COM_DB2_JDBC_DRIVER = "com.ibm.db2.jcc.DB2Driver";
     public static final String COM_PRESTO_JDBC_DRIVER = "com.facebook.presto.jdbc.PrestoDriver";
 
+
+    /**
+     * validation Query
+     */
+    public static final String POSTGRESQL_VALIDATION_QUERY = "select version()";
+    public static final String MYSQL_VALIDATION_QUERY = "select 1";
+    public static final String HIVE_VALIDATION_QUERY = "select 1";
+    public static final String CLICKHOUSE_VALIDATION_QUERY = "select 1";
+    public static final String ORACLE_VALIDATION_QUERY = "select 1 from dual";
+    public static final String SQLSERVER_VALIDATION_QUERY = "select 1";
+    public static final String DB2_VALIDATION_QUERY = "select 1 from sysibm.sysdummy1";
+    public static final String PRESTO_VALIDATION_QUERY = "select 1";
+
     /**
      * database type
      */
@@ -1022,12 +1033,6 @@ public final class Constants {
      */
     public static final int AUTHORIZE_READABLE_PERM = 4;
 
-
-    /**
-     * plugin configurations
-     */
-    public static final String PLUGIN_JAR_SUFFIX = ".jar";
-
     public static final int NORMAL_NODE_STATUS = 0;
     public static final int ABNORMAL_NODE_STATUS = 1;
     public static final int BUSY_NODE_STATUE = 2;
@@ -1041,9 +1046,6 @@ public final class Constants {
      */
     public static final String SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator");
 
-
-    public static final String EXCEL_SUFFIX_XLS = ".xls";
-
     /**
      * datasource encryption salt
      */
@@ -1080,21 +1082,7 @@ public final class Constants {
      * docker & kubernetes
      */
     public static final boolean DOCKER_MODE = !StringUtils.isEmpty(System.getenv("DOCKER"));
-    public static final boolean KUBERNETES_MODE = !StringUtils.isEmpty(System.getenv("KUBERNETES_SERVICE_HOST")) && !StringUtils.isEmpty(System.getenv("KUBERNETES_SERVICE_PORT"));
-
-    /**
-     * task parameter keys
-     */
-    public static final String TASK_PARAMS = "params";
-    public static final String TASK_PARAMS_DATASOURCE = "datasource";
-    public static final String TASK_PARAMS_DATASOURCE_NAME = "datasourceName";
-    public static final String TASK_DEPENDENCE = "dependence";
-    public static final String TASK_DEPENDENCE_DEPEND_TASK_LIST = "dependTaskList";
-    public static final String TASK_DEPENDENCE_DEPEND_ITEM_LIST = "dependItemList";
-    public static final String TASK_DEPENDENCE_PROJECT_ID = "projectId";
-    public static final String TASK_DEPENDENCE_PROJECT_NAME = "projectName";
-    public static final String TASK_DEPENDENCE_DEFINITION_ID = "definitionId";
-    public static final String TASK_DEPENDENCE_DEFINITION_NAME = "definitionName";
+    public static final Boolean KUBERNETES_MODE = !StringUtils.isEmpty(System.getenv("KUBERNETES_SERVICE_HOST")) && !StringUtils.isEmpty(System.getenv("KUBERNETES_SERVICE_PORT"));
 
     /**
      * dry run flag
diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/BaseHdfsDatasourceParamDTO.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/BaseHdfsDatasourceParamDTO.java
deleted file mode 100644
index 747d3ea..0000000
--- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/BaseHdfsDatasourceParamDTO.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.common.datasource;
-
-public abstract class BaseHdfsDatasourceParamDTO extends BaseDataSourceParamDTO {
-
-    protected String principal;
-
-    protected String javaSecurityKrb5Conf;
-
-    protected String loginUserKeytabUsername;
-
-    protected String loginUserKeytabPath;
-
-    public String getPrincipal() {
-        return principal;
-    }
-
-    public void setPrincipal(String principal) {
-        this.principal = principal;
-    }
-
-    public String getLoginUserKeytabUsername() {
-        return loginUserKeytabUsername;
-    }
-
-    public void setLoginUserKeytabUsername(String loginUserKeytabUsername) {
-        this.loginUserKeytabUsername = loginUserKeytabUsername;
-    }
-
-    public String getLoginUserKeytabPath() {
-        return loginUserKeytabPath;
-    }
-
-    public void setLoginUserKeytabPath(String loginUserKeytabPath) {
-        this.loginUserKeytabPath = loginUserKeytabPath;
-    }
-
-    public String getJavaSecurityKrb5Conf() {
-        return javaSecurityKrb5Conf;
-    }
-
-    public void setJavaSecurityKrb5Conf(String javaSecurityKrb5Conf) {
-        this.javaSecurityKrb5Conf = javaSecurityKrb5Conf;
-    }
-}
diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/DatasourceProcessor.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/DatasourceProcessor.java
deleted file mode 100644
index e76a088..0000000
--- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/DatasourceProcessor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.common.datasource;
-
-import org.apache.dolphinscheduler.common.enums.DbType;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.SQLException;
-
-public interface DatasourceProcessor {
-
-    /**
-     * check datasource param is valid
-     */
-    void checkDatasourceParam(BaseDataSourceParamDTO datasourceParam);
-
-    /**
-     * create BaseDataSourceParamDTO by connectionJson
-     *
-     * @param connectionJson see{@link org.apache.dolphinscheduler.dao.entity.Datasource}
-     * @return {@link BaseDataSourceParamDTO}
-     */
-    BaseDataSourceParamDTO createDatasourceParamDTO(String connectionJson);
-
-    /**
-     * create datasource connection parameter which will be stored at DataSource
-     * <p>
-     * see {@code org.apache.dolphinscheduler.dao.entity.DataSource.connectionParams}
-     */
-    ConnectionParam createConnectionParams(BaseDataSourceParamDTO datasourceParam);
-
-    /**
-     * deserialize json to datasource connection param
-     *
-     * @param connectionJson {@code org.apache.dolphinscheduler.dao.entity.DataSource.connectionParams}
-     * @return {@link BaseConnectionParam}
-     */
-    ConnectionParam createConnectionParams(String connectionJson);
-
-    /**
-     * get datasource Driver
-     */
-    String getDatasourceDriver();
-
-    /**
-     * get jdbcUrl by connection param, the jdbcUrl is different with ConnectionParam.jdbcUrl, this method will inject
-     * other to jdbcUrl
-     *
-     * @param connectionParam connection param
-     */
-    String getJdbcUrl(ConnectionParam connectionParam);
-
-    /**
-     * get connection by connectionParam
-     *
-     * @param connectionParam connectionParam
-     * @return {@link Connection}
-     */
-    Connection getConnection(ConnectionParam connectionParam) throws ClassNotFoundException, SQLException, IOException;
-
-    /**
-     * @return {@link DbType}
-     */
-    DbType getDbType();
-}
diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/clickhouse/ClickHouseDatasourceParamDTO.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/clickhouse/ClickHouseDatasourceParamDTO.java
deleted file mode 100644
index f4168fc..0000000
--- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/datasource/clickhouse/ClickHouseDatasourceParamDTO.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.common.datasource.clickhouse;
-
-import org.apache.dolphinscheduler.common.datasource.BaseDataSourceParamDTO;
-import org.apache.dolphinscheduler.common.enums.DbType;
... 25328 lines suppressed ...