通知的设计

1.通知的模块设计

将不同的通知方式设计为不同的插件,引入不同的插件包,并将支持的插件配置到数据库里,从数据库中load出来配置然后进行安装流程

image

2.插件的管理

AlertPluginManager

package org.apache.dolphinscheduler.alert.plugin;

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.common.enums.PluginType;
import org.apache.dolphinscheduler.common.enums.WarningType;
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.ParamsOptions;
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
import org.apache.dolphinscheduler.spi.params.base.Validate;
import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
import org.apache.dolphinscheduler.spi.plugin.PrioritySPIFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

@Component
@Slf4j
public final class AlertPluginManager {

    private final PluginDao pluginDao;

    public AlertPluginManager(PluginDao pluginDao) {
        this.pluginDao = pluginDao;
    }

    private final Map<Integer, AlertChannel> alertPluginMap = new HashMap<>();

    public void start() {
        log.info("AlertPluginManager start ...");
        checkAlertPluginExist(); // 检查插件是否存在
        installAlertPlugin();  // 多抽象了一层安装插件的逻辑
        log.info("AlertPluginManager started ...");
    }

    public Optional<AlertChannel> getAlertChannel(int id) {
        return Optional.ofNullable(alertPluginMap.get(id));
    }

    public int size() {
        return alertPluginMap.size();
    }

    private void checkAlertPluginExist() {
        if (!pluginDao.checkPluginDefineTableExist()) {
            log.error("Plugin Define Table t_ds_plugin_define Not Exist . Please Create it First !");
            System.exit(1);
        }
    }

    private void installAlertPlugin() {
        final PluginParams warningTypeParams = getWarningTypeParams();

        PrioritySPIFactory<AlertChannelFactory> prioritySPIFactory =
                new PrioritySPIFactory<>(AlertChannelFactory.class);
        for (Map.Entry<String, AlertChannelFactory> entry : prioritySPIFactory.getSPIMap().entrySet()) {
            String name = entry.getKey();
            AlertChannelFactory factory = entry.getValue(); // 找到对应的通信管道工厂

            log.info("Registering alert plugin: {} - {}", name, factory.getClass());

            final AlertChannel alertChannel = factory.create(); // 生成对应的通信管道

            log.info("Registered alert plugin: {} - {}", name, factory.getClass());

            final List<PluginParams> params = new ArrayList<>(factory.params());
            params.add(0, warningTypeParams);

            final String paramsJson = PluginParamsTransfer.transferParamsToJson(params);

            final PluginDefine pluginDefine = new PluginDefine(name, PluginType.ALERT.getDesc(), paramsJson);
            final int id = pluginDao.addOrUpdatePluginDefine(pluginDefine);
			// 安装插件其实就是从库里load出来已支持的配置,然后加载成插件对象,放到map里
            alertPluginMap.put(id, alertChannel);
        }
    }

    private PluginParams getWarningTypeParams() {
        return RadioParam.newBuilder(AlertConstants.NAME_WARNING_TYPE, AlertConstants.WARNING_TYPE)
                .addParamsOptions(
                        new ParamsOptions(WarningType.SUCCESS.getDescp(), WarningType.SUCCESS.getDescp(), false))
                .addParamsOptions(
                        new ParamsOptions(WarningType.FAILURE.getDescp(), WarningType.FAILURE.getDescp(), false))
                .addParamsOptions(new ParamsOptions(WarningType.ALL.getDescp(), WarningType.ALL.getDescp(), false))
                .setValue(WarningType.ALL.getDescp())
                .addValidate(Validate.newBuilder().setRequired(true).build())
                .build();
    }
}

3.通知的抽象

3.1 定义通知管道接口

AlertChannel.java

public interface AlertChannel {

    /**
     * process and send alert
     *
     * @param info alert info
     * @return process alarm result
     */
    AlertResult process(AlertInfo info);

    default @NonNull AlertResult closeAlert(AlertInfo info) {
        return new AlertResult("true", "no need to close alert");
    }
}

3.2 定义微信通知的实现管道

WeChatAlertChannel.java

public final class WeChatAlertChannel implements AlertChannel {

    @Override
    public AlertResult process(AlertInfo info) {
        AlertData alertData = info.getAlertData();
        Map<String, String> paramsMap = info.getAlertParams();
        if (null == paramsMap) {
            return new AlertResult("false", "we chat params is null");
        }
        return new WeChatSender(paramsMap).sendEnterpriseWeChat(alertData.getTitle(), alertData.getContent());
    }
}

3.3 定义通知管道工厂,用来生成通知管道,不同的通知方式对应不同的工厂

AlertChannelFactory.java

public interface AlertChannelFactory extends PrioritySPI {

    /**
     * Returns the name of the alert channel
     *
     * @return the name of the alert channel
     */
    String name();

    /**
     * Create an alert channel
     *
     * @return alert channel
     */
    AlertChannel create();

    /**
     * Returns the configurable parameters that this plugin needs to display on the web ui
     */
    List<PluginParams> params();

    default SPIIdentify getIdentify() {
        return SPIIdentify.builder().name(name()).build();
    }
}

微信的通知管道工厂WeChatAlertChannelFactory.java


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.AlertInputTips;
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(AlertInputTips.CORP_ID.getMsg())
                .addValidate(Validate.newBuilder()
                        .setRequired(true)
                        .build())
                .build();

        InputParam secretParam = InputParam
                .newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET,
                        WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_SECRET)
                .setPlaceholder(AlertInputTips.SECRET.getMsg())
                .addValidate(Validate.newBuilder()
                        .setRequired(true)
                        .build())
                .build();

        InputParam usersParam = InputParam
                .newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS,
                        WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_USERS)
                .setPlaceholder(AlertInputTips.WECHAT_MENTION_USERS.getMsg())
                .addValidate(Validate.newBuilder()
                        .setRequired(false)
                        .build())
                .build();

        InputParam agentIdParam = InputParam
                .newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID,
                        WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_AGENT_ID)
                .setPlaceholder(AlertInputTips.WECHAT_AGENT_ID.getMsg())
                .addValidate(Validate.newBuilder()
                        .setRequired(true)
                        .build())
                .build();

        RadioParam sendType = RadioParam
                .newBuilder(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SEND_TYPE,
                        WeChatAlertParamsConstants.ENTERPRISE_WE_CHAT_SEND_TYPE)
                .addParamsOptions(new ParamsOptions(WeChatType.APP.getDescp(), WeChatType.APP.getDescp(), false))
                .addParamsOptions(
                        new ParamsOptions(WeChatType.APPCHAT.getDescp(), WeChatType.APPCHAT.getDescp(), false))
                .setValue(WeChatType.APP.getDescp())
                .addValidate(Validate.newBuilder().setRequired(true).build())
                .build();

        RadioParam showType = RadioParam.newBuilder(AlertConstants.NAME_SHOW_TYPE, AlertConstants.SHOW_TYPE)
                .addParamsOptions(new ParamsOptions(ShowType.MARKDOWN.getDescp(), ShowType.MARKDOWN.getDescp(), false))
                .addParamsOptions(new ParamsOptions(ShowType.TEXT.getDescp(), ShowType.TEXT.getDescp(), false))
                .setValue(ShowType.MARKDOWN.getDescp())
                .addValidate(Validate.newBuilder().setRequired(true).build())
                .build();

        return Arrays.asList(corpIdParam, secretParam, usersParam, agentIdParam, sendType, showType);
    }

    @Override
    public AlertChannel create() {
        return new WeChatAlertChannel();
    }
}

3.4 定义微信通知的发送器WeChatSender

WeChatSender.java

@Slf4j
public final class WeChatSender {

    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}";
    private static final String MSG_REG_EXP = "{msg}";
    private static final String USER_REG_EXP = "{toUser}";
    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 weChatAgentIdChatId;
    private final String weChatUsers;
    private final String weChatTokenUrlReplace;
    private final String weChatToken;
    private final String sendType;
    private final String showType;

    WeChatSender(Map<String, String> config) {
        weChatAgentIdChatId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_AGENT_ID);
        weChatUsers = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_USERS);
        String weChatCorpId = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_CORP_ID);
        String weChatSecret = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SECRET);
        String weChatTokenUrl = WeChatAlertConstants.WE_CHAT_TOKEN_URL;
        sendType = config.get(WeChatAlertParamsConstants.NAME_ENTERPRISE_WE_CHAT_SEND_TYPE);
        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();
    }

    private static String post(String url, String data) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(data, WeChatAlertConstants.CHARSET));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String resp;
            try {
                HttpEntity entity = response.getEntity();
                resp = EntityUtils.toString(entity, WeChatAlertConstants.CHARSET);
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
            log.info("Enterprise WeChat send [{}], param:{}, resp:{}",
                    url, data, resp);
            return resp;
        }
    }

    /**
     * convert text to markdown style
     *
     * @param title   the title
     * @param content the content
     * @return markdown text
     */
    private static String markdownText(String title, String content) {
        if (StringUtils.isNotEmpty(content)) {
            List<LinkedHashMap> mapItemsList = JSONUtils.toList(content, LinkedHashMap.class);
            if (null == mapItemsList || mapItemsList.isEmpty()) {
                log.error("itemsList is null");
                throw new RuntimeException("itemsList is null");
            }

            StringBuilder contents = new StringBuilder(100);
            contents.append(String.format("`%s`%n", title));
            for (LinkedHashMap mapItems : mapItemsList) {

                Set<Map.Entry<String, Object>> entries = mapItems.entrySet();
                for (Entry<String, Object> entry : entries) {
                    contents.append(WeChatAlertConstants.MARKDOWN_QUOTE);
                    contents.append(entry.getKey()).append(":").append(entry.getValue());
                    contents.append(WeChatAlertConstants.MARKDOWN_ENTER);
                }

            }
            return contents.toString();
        }
        return null;
    }

    private static String get(String url) throws IOException {
        String resp;

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                resp = EntityUtils.toString(entity, WeChatAlertConstants.CHARSET);
                EntityUtils.consume(entity);
            }

            HashMap<String, Object> map = JSONUtils.parseObject(resp, HashMap.class);
            if (map != null && null != map.get("access_token")) {
                return map.get("access_token").toString();
            } else {
                return null;
            }
        }
    }

    private static String mkString(Iterable<String> list) {
        if (null == list || StringUtils.isEmpty("|")) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String item : list) {
            if (first) {
                first = false;
            } else {
                sb.append("|");
            }
            sb.append(item);
        }
        return sb.toString();
    }

    private static AlertResult checkWeChatSendMsgResult(String result) {
        AlertResult alertResult = new AlertResult();
        alertResult.setStatus(ALERT_STATUS);

        if (null == result) {
            alertResult.setMessage("we chat send fail");
            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");
            log.info("send we chat msg error,resp error");
            return alertResult;
        }
        if (sendMsgResponse.errcode == 0) {
            alertResult.setStatus("true");
            alertResult.setMessage("we chat alert send success");
            return alertResult;
        }
        alertResult.setStatus(ALERT_STATUS);
        alertResult.setMessage(sendMsgResponse.getErrmsg());
        return alertResult;
    }

    /**
     * send Enterprise WeChat
     *
     * @return Enterprise WeChat resp, demo: {"errcode":0,"errmsg":"ok","invaliduser":""}
     */
    public AlertResult sendEnterpriseWeChat(String title, String content) {
        AlertResult alertResult;
        String data = markdownByAlert(title, content);
        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 = "";
        Map<String, String> contentMap = new HashMap<>();
        contentMap.put(WeChatAlertConstants.WE_CHAT_CONTENT_KEY, data);
        String msgJson = "";
        if (sendType.equals(WeChatType.APP.getDescp())) {
            enterpriseWeChatPushUrlReplace = WeChatAlertConstants.WE_CHAT_PUSH_URL.replace(TOKEN_REGEX, weChatToken);
            WechatAppMessage wechatAppMessage = new WechatAppMessage(weChatUsers, showType,
                    Integer.valueOf(weChatAgentIdChatId), contentMap, WE_CHAT_MESSAGE_SAFE_PUBLICITY,
                    WE_CHAT_ENABLE_ID_TRANS, WE_CHAT_DUPLICATE_CHECK_INTERVAL_ZERO);
            msgJson = JSONUtils.toJsonString(wechatAppMessage);
        } else if (sendType.equals(WeChatType.APPCHAT.getDescp())) {
            enterpriseWeChatPushUrlReplace =
                    WeChatAlertConstants.WE_CHAT_APP_CHAT_PUSH_URL.replace(TOKEN_REGEX, weChatToken);
            WechatAppChatMessage wechatAppChatMessage =
                    new WechatAppChatMessage(weChatAgentIdChatId, showType, contentMap, WE_CHAT_MESSAGE_SAFE_PUBLICITY);
            msgJson = JSONUtils.toJsonString(wechatAppChatMessage);
        }

        try {
            return checkWeChatSendMsgResult(post(enterpriseWeChatPushUrlReplace, msgJson));
        } 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) {
        return markdownText(title, content);
    }

    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()
                    + ")";
        }
    }
}

4.maven结构

4.1 dolphinscheduler-alert-wechat

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.apache.dolphinscheduler</groupId>
        <artifactId>dolphinscheduler-alert-plugins</artifactId>
        <version>dev-SNAPSHOT</version>
    </parent>
    <artifactId>dolphinscheduler-alert-wechat</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.apache.dolphinscheduler</groupId>
            <artifactId>dolphinscheduler-alert-api</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>
    </dependencies>
</project>

4.2 dolphinscheduler-alert-plugins

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.apache.dolphinscheduler</groupId>
        <artifactId>dolphinscheduler-alert</artifactId>
        <version>dev-SNAPSHOT</version>
    </parent>
    <artifactId>dolphinscheduler-alert-plugins</artifactId>
    <packaging>pom</packaging>

    <modules>
        <module>dolphinscheduler-alert-all</module>
        <module>dolphinscheduler-alert-api</module>
        <module>dolphinscheduler-alert-email</module>
        <module>dolphinscheduler-alert-wechat</module>
        <module>dolphinscheduler-alert-dingtalk</module>
        <module>dolphinscheduler-alert-script</module>
        <module>dolphinscheduler-alert-http</module>
        <module>dolphinscheduler-alert-feishu</module>
        <module>dolphinscheduler-alert-slack</module>
        <module>dolphinscheduler-alert-pagerduty</module>
        <module>dolphinscheduler-alert-webexteams</module>
        <module>dolphinscheduler-alert-telegram</module>
    </modules>

</project>

4.3 dolphinscheduler-alert-server 通知服务后台,与dolphinscheduler-alert-plugins同级

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.apache.dolphinscheduler</groupId>
        <artifactId>dolphinscheduler-alert</artifactId>
        <version>dev-SNAPSHOT</version>
    </parent>
    <artifactId>dolphinscheduler-alert-server</artifactId>
    <packaging>jar</packaging>
    <name>${project.artifactId}</name>
    <dependencies>
        <!-- dolphinscheduler -->
        <dependency>
            <groupId>org.apache.dolphinscheduler</groupId>
            <artifactId>dolphinscheduler-remote</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dolphinscheduler</groupId>
            <artifactId>dolphinscheduler-meter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dolphinscheduler</groupId>
            <artifactId>dolphinscheduler-alert-all</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.dolphinscheduler</groupId>
            <artifactId>dolphinscheduler-dao</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.dolphinscheduler</groupId>
            <artifactId>dolphinscheduler-registry-all</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </dependency>
        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>janino</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-fabric8-config</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>*.yaml</exclude>
                        <exclude>*.xml</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <id>dolphinscheduler-alert-server</id>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <phase>package</phase>
                        <configuration>
                            <finalName>alert-server</finalName>
                            <descriptors>
                                <descriptor>src/main/assembly/dolphinscheduler-alert-server.xml</descriptor>
                            </descriptors>
                            <appendAssemblyId>false</appendAssemblyId>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>docker</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

4.4 dolphinscheduler-alert 通知模块最上层级

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.apache.dolphinscheduler</groupId>
        <artifactId>dolphinscheduler</artifactId>
        <version>dev-SNAPSHOT</version>
    </parent>
    <artifactId>dolphinscheduler-alert</artifactId>
    <packaging>pom</packaging>

    <modules>
        <module>dolphinscheduler-alert-plugins</module>
        <module>dolphinscheduler-alert-server</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.dolphinscheduler</groupId>
                <artifactId>dolphinscheduler-bom</artifactId>
                <version>${project.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

image

posted @ 2023-07-07 11:33  SpecialSpeculator  阅读(54)  评论(0编辑  收藏  举报