SpringCloud整合SpringAdmin发送钉钉预警以及邮件预警

本片文章永远免费是为了让码友们少走弯路 

首先先声明版本

SpringCloud版本

           <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

SpringBoot版本

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
    </parent>

SpringAdmin版本

   <properties>
        <boot.admin.version>2.1.2</boot.admin.version>
    </properties>


        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>${boot.admin.version}</version>
        </dependency>

引导类上开启SpringAdmin服务注解

@EnableConfigurationProperties(DingTalkNotifierConfig.class)
@ComponentScans({@ComponentScan("com.fuyubl.areca.security.notifier"), @ComponentScan("com.fuyubl.areca.security.security")})
@SpringBootApplication
@EnableAdminServer
@EnableDiscoveryClient
public class MonitorApplication {
    public static void main(String[] args) {
        SpringApplication.run(MonitorApplication.class, args);
    }
}

yml配置文件

server:
  port: 8868
spring:
  application:
    name: areca-monitor
  mail:
    host: smtp.126.com
    username: 你的邮箱
    password: smtp秘钥
    properties:
      mail:
        smtp:
          auth: true
          starttls: true
          required: true
          ssl:
            enable: true
          socketFactory:
            port: 465
            class: javax.net.ssl.SSLSocketFactory
    port: 465
  security:
    user:
      name: admin
      password: 123456
  boot:
#服务状态发生改变发送邮件
    admin:
      notify:
        mail:
          to: xxx@126.com
          from: xxx@126.com
      dingtalk:
        enable: true
        type: text
        # 是否@所有人
        atAll: false
        #人员名单列表
        staff: 1333333000,





  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  profiles:
    active: ${PROFILES_ACTIVE:dev}

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      show-details: ALWAYS
    logfile:
      enabled: true

SpringAdmin安全认证

package com.fuyubl.areca.security.security;

import com.alibaba.nacos.common.util.HttpMethod;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        //httpSecurity.authorizeRequests().anyRequest().permitAll();
        httpSecurity.csrf().disable();

        httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

                .antMatchers(HttpMethod.POST).permitAll()
                .antMatchers(HttpMethod.PUT).permitAll()
                .antMatchers(HttpMethod.DELETE).permitAll()
                .antMatchers(HttpMethod.GET).permitAll();
        httpSecurity.headers().cacheControl();
    }

}

自定义监听服务状态 继承  AbstractEventNotifier  或者AbstractStatusChangeNotifier都可以

直接贴代码

package com.fuyubl.areca.security.notifier;

import com.alibaba.fastjson.JSONObject;
import com.fuyubl.areca.security.bean.DingTalkFactroy;
import com.fuyubl.areca.security.enums.ServerStatusInfo;
import com.fuyubl.areca.security.utils.DateUtils;
import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.notify.AbstractEventNotifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.Date;
import java.util.Map;

@Slf4j
@Component
public class DingDingNotifier extends AbstractEventNotifier {

    @Autowired
    private DingTalkFactroy factroy;

    public DingDingNotifier(InstanceRepository repository) {
        super(repository);
    }

    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
        String status = instance.getStatusInfo().getStatus();

        if (status.equals(ServerStatusInfo.STATUS_UNKNOWN.getStatus())) {
            log.info("服务状态未知~", instance.getStatusInfo().getStatus(), ServerStatusInfo.statusInfo(status));
        }
        String serviceName = instance.getRegistration().getName();
        String serviceUrl = instance.getRegistration().getServiceUrl();

        Map<String, Object> details = instance.getStatusInfo().getDetails();
        StringBuilder str = new StringBuilder();
        str.append("服务监控中心:>>>>>areca-monitor<<<<<" + "\n");
        str.append("【服务名称】 : " + serviceName + "" + "\n");
        str.append("【服务地址】" + serviceUrl + "\n");
        str.append("【状态】" + status + ":" + ServerStatusInfo.statusInfo(status) + "\n");
        str.append("【预警详情】:" + JSONObject.toJSONString(details) + "\n");
        str.append("【预警时间】" + DateUtils.pattern(new Date()) + "\n\n\n");

        return Mono.fromRunnable(() -> {
            factroy.builder().sendMag(str.toString());
        });
    }
}

钉钉发送信息的类型有很多种  普通文本,图文,超链接形式 于是我做成了抽象类结合抽象工厂模式去发送消息

package com.fuyubl.areca.security.notifier;

import com.fuyubl.areca.security.constant.DingTalkConstants;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;

/**
 * @author dlh
 * @date 2022/8/17 15:10
 */
@Slf4j
public abstract class DingTalkNotfier {


///我这边测试就先写死token和secret
    public static String access_token = "你的机器人token纯token";
    public static String secret = "SE开头的秘钥";

    /**
     * Msg消息发送
     */
    abstract void sendMag(String msg);

    /**
     * link
     *
     * @param msg
     * @param url
     */
    abstract void sendMag(String msg, String url,String title);


    /**
     * 获取URL
     *
     * @return
     * @throws Exception
     */
    public static String getUrl() {
        Long timestamp = System.currentTimeMillis();
        String sign = null;
        try {
            sign = getSign(timestamp, secret);
        } catch (Exception e) {
            log.error("发送钉钉消息时出现异常~", e, e.getMessage());
            e.printStackTrace();
        }
        return String.format(DingTalkConstants.API_SEND_MESSAGE_SIGN, access_token, timestamp, sign);
    }

    /**
     * 获取签名
     *
     * @param timestamp 时间戳
     * @param secret    钉钉群机器人的签名秘钥
     * @return
     * @throws Exception
     */
    private static String getSign(Long timestamp, String secret) throws Exception {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return URLEncoder.encode(new String(Base64.encode(signData)), "UTF-8");
    }

}

 普通文本类型

package com.fuyubl.areca.security.notifier;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.fuyubl.areca.security.bean.DingTalkNotifierConfig;
import com.fuyubl.areca.security.constant.DingTalkMagType;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author dlh
 * @date 2022/8/17 15:12
 */
@Slf4j
@Component
public class TextDingTalkNotifier extends DingTalkNotfier {

    @Autowired
    private DingTalkNotifierConfig config;

    /**
     * 钉钉发送文本消息
     */
    @Override
    void sendMag(String mag) {
        if (!config.getEnable()) {
            return;
        }
        //构建钉钉连接
        OapiRobotSendResponse execute = null;
        DingTalkClient client = new DefaultDingTalkClient(getUrl());
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype(DingTalkMagType.textType);

        //消息类型
        OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
        text.setContent(mag);
        request.setText(text);

        //发送人员名单
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        at.setAtMobiles(config.getStaff());
        at.setIsAtAll(config.getAtAll());
        request.setAt(at);
        try {
            execute = client.execute(request);
        } catch (ApiException e) {
            log.error("钉钉发送消息异常", e, e.getMessage());
            e.printStackTrace();
        }
        if (execute.isSuccess()) {
            log.info("钉钉发送消息成功~ ,请注意查收!");
        } else {
            log.error("消息发送失败:原因" + execute.getErrmsg(), execute.getErrcode());
        }
    }

    @Override
    void sendMag(String msg, String url, String total) {
        return;
    }
}
Markdown消息类型
package com.fuyubl.areca.security.notifier;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.fuyubl.areca.security.bean.DingTalkNotifierConfig;
import com.fuyubl.areca.security.constant.DingTalkMagType;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author dlh
 * @date 2022/8/17 15:51
 */
@Component
@Slf4j
public class MarkdownDingTalkNotfier extends DingTalkNotfier {
    @Autowired
    private DingTalkNotifierConfig config;


    @Override
    void sendMag(String msg) {
        return;
    }

    @Override
    void sendMag(String msg, String url, String title) {
        if (!config.getEnable()) {
            return;
        }
        OapiRobotSendResponse execute = null;
        DingTalkClient client = new DefaultDingTalkClient(getUrl());
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype(DingTalkMagType.markdownType);
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle(title);
        markdown.setText(msg);
        request.setMarkdown(markdown);
        try {
            execute = client.execute(request);
        } catch (ApiException e) {
            log.error("钉钉发送消息异常", e, e.getMessage());
            e.printStackTrace();
        }
        if (execute.isSuccess()) {
            log.info("钉钉发送消息成功~ ,请注意查收!");
        }else {
            log.error("消息发送失败:原因" + execute.getErrmsg(), execute.getErrcode());
        }
    }
}

还有最后一个link类型

package com.fuyubl.areca.security.notifier;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.fuyubl.areca.security.bean.DingTalkNotifierConfig;
import com.fuyubl.areca.security.constant.DingTalkMagType;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author dlh
 * @date 2022/8/17 15:44
 */
@Component
@Slf4j
public class LinkDingTalkNotifier extends DingTalkNotfier {

    @Autowired
    private DingTalkNotifierConfig config;

    @Override
    void sendMag(String msg) {
        return;
    }

    @Override
    void sendMag(String msg, String url, String title) {
        if (!config.getEnable()) {
            return;
        }
        OapiRobotSendResponse execute = null;
        DingTalkClient client = new DefaultDingTalkClient(getUrl());
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype(DingTalkMagType.linkType);
        OapiRobotSendRequest.Link link = new OapiRobotSendRequest.Link();
        link.setMessageUrl(url);
        link.setPicUrl("");
        link.setTitle(title);
        link.setText(msg);
        request.setLink(link);
        try {
            execute = client.execute(request);
        } catch (ApiException e) {
            log.error("钉钉发送消息异常", e, e.getMessage());
            e.printStackTrace();
        }
        if (execute.isSuccess()) {
            log.info("钉钉发送消息成功~ ,请注意查收!");
        }else {
            log.error("消息发送失败:原因" + execute.getErrmsg(), execute.getErrcode());
        }

    }


}

简单吧 其实没啥区别 需要的自己改改啥的 

时间工具类简单的 

public class DateUtils {
    private static final String forMart = "yyyy-MM-dd HH:mm:ss";

    public static String pattern(Date targt) {
        SimpleDateFormat sim = new SimpleDateFormat(forMart);
        return sim.format(targt);
    }
}

一些常量 

package com.fuyubl.areca.security.constant;

/**
 * @author dlh
 * @date 2022/8/17 15:15
 */
public interface DingTalkMagType {
    /**
     * 文本类型
     */
    String textType = "text";

    /**
     * 图文类型
     */
    String linkType = "link";

    /**
     * 超链接类型
     */
    String markdownType = "markdown";

}

钉钉发送url

package com.fuyubl.areca.security.constant;

public class DingTalkConstants {

    public static final String SERVER_URL = "https://oapi.dingtalk.com";

    public static final String API_SEND_MESSAGE = SERVER_URL + "/robot/send?access_token=%s";

    public static final String API_SEND_MESSAGE_SIGN = SERVER_URL + "/robot/send?access_token=%s&timestamp=%s&sign=%s";

}

读取配置文件

package com.fuyubl.areca.security.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author dlh
 * @date 2022/8/17 15:32
 */
@PropertySource("classpath:application.yml")
@Primary
@Component
@ConfigurationProperties(prefix = "spring.boot.admin.dingtalk", ignoreUnknownFields = true)
public class DingTalkNotifierConfig {
    /**
     * 是否启用钉钉
     */
    private Boolean enable;
    /**
     * 消息类型
     */
    private String type;
    /**
     * 是否推送给所有成员
     */
    private Boolean atAll;

    /**
     * 指定人员
     */
    private List staff;


    public Boolean getEnable() {
        return enable;
    }

    public void setEnable(Boolean enable) {
        this.enable = enable;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Boolean getAtAll() {
        return atAll;
    }

    public void setAtAll(Boolean atAll) {
        this.atAll = atAll;
    }

    public List getStaff() {
        return staff;
    }

    public void setStaff(List staff) {
        this.staff = staff;
    }



}

然后结合工厂模式 

package com.fuyubl.areca.security.bean;

import com.fuyubl.areca.security.constant.DingTalkMagType;
import com.fuyubl.areca.security.notifier.DingTalkNotfier;
import com.fuyubl.areca.security.notifier.LinkDingTalkNotifier;
import com.fuyubl.areca.security.notifier.MarkdownDingTalkNotfier;
import com.fuyubl.areca.security.notifier.TextDingTalkNotifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author dlh
 * @date 2022/8/17 15:55
 */
@Configuration
public class DingTalkFactroy {


    @Autowired
    private DingTalkNotifierConfig conf;

    @Bean
    public DingTalkNotfier builder() {
        switch (conf.getType()) {
            case DingTalkMagType.linkType:
                return new LinkDingTalkNotifier();
            case DingTalkMagType.textType:
                return new TextDingTalkNotifier();
            case DingTalkMagType.markdownType:
                return new MarkdownDingTalkNotfier();
        }
        return null;

    }
}

到这里就完篇 最主要注意的是 版本关系 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值