欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用AOP實(shí)現(xiàn)系統(tǒng)告警的方法詳解

 更新時(shí)間:2022年09月19日 09:24:43   作者:知了一笑  
在開(kāi)發(fā)的過(guò)程中會(huì)遇到各種各樣的開(kāi)發(fā)問(wèn)題,服務(wù)器宕機(jī)、網(wǎng)絡(luò)抖動(dòng)、代碼本身的bug等等。針對(duì)代碼的bug,我們可以提前預(yù)支,通過(guò)發(fā)送告警信息來(lái)警示我們?nèi)ジ深A(yù),盡早處理。本文將利用AOP實(shí)現(xiàn)系統(tǒng)告警,需要的可以參考一下

一、業(yè)務(wù)背景

在開(kāi)發(fā)的過(guò)程中會(huì)遇到各種各樣的開(kāi)發(fā)問(wèn)題,服務(wù)器宕機(jī)、網(wǎng)絡(luò)抖動(dòng)、代碼本身的bug等等。針對(duì)代碼的bug,我們可以提前預(yù)支,通過(guò)發(fā)送告警信息來(lái)警示我們?nèi)ジ深A(yù),盡早處理。

二、告警的方式

1、釘釘告警

通過(guò)在企業(yè)釘釘群,添加群機(jī)器人的方式,通過(guò)機(jī)器人向群內(nèi)發(fā)送報(bào)警信息。至于釘釘機(jī)器人怎么創(chuàng)建,發(fā)送消息的api等等,請(qǐng)參考官方文檔

2、企業(yè)微信告警

同樣的套路,企業(yè)微信也是,在企業(yè)微信群中,添加群機(jī)器人。通過(guò)機(jī)器人發(fā)送告警信息。具體請(qǐng)看官方文檔

3、郵件告警

與上述不同的是,郵件是發(fā)送給個(gè)人的,當(dāng)然也可以是批量發(fā)送,只實(shí)現(xiàn)了發(fā)送文本格式的方式,至于markdown格式,有待考察。郵件發(fā)送相對(duì)比較簡(jiǎn)單,這里就不展開(kāi)贅述。

三、源碼解析

1、Alarm自定義注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public?@interface?Alarm?{

????/**
?????*?報(bào)警標(biāo)題
?????*
?????*?@return?String
?????*/
????String?title()?default?"";

????/**
?????*?發(fā)送報(bào)警格式:目前支持text,markdown
?????*?@return
?????*/
????MessageTye?messageType()?default?MessageTye.TEXT;

????/**
?????*?告警模板id
?????*?@return
?????*/
????String?templateId()?default?"";

????/**
?????*?成功是否通知:true-通知,false-不通知
?????*?@return
?????*/
????boolean?successNotice()?default?false;
}

1.1、注解使用

@Alarm標(biāo)記在方法上使用,被標(biāo)記的方法發(fā)生異常,會(huì)根據(jù)配置,讀取配置信息,發(fā)送異常堆棧信息。使用方法如下所示:

@Alarm(title?=?"某某業(yè)務(wù)告警",?messageType?=?MessageTye.MARKDOWN,?templateId?=?"errorTemp")

1.2、注解字段解析

title

告警消息標(biāo)題:可以定義為業(yè)務(wù)信息,如導(dǎo)師身份計(jì)算

messageType

告警消息展示類型:目前支持text文本類型,markdown類型

templateId

消息模板id:與配置文件中配置的模板id一致

successNotice

正常情況是否也需要發(fā)送告警信息,默認(rèn)值是fasle,表示不需要發(fā)送。當(dāng)然,有些業(yè)務(wù)場(chǎng)景正常情況也需要發(fā)送,比如:支付出單通知等。

2、配置文件分析

2.1、釘釘配置文件

spring:
??alarm:
????dingtalk:
?????#?開(kāi)啟釘釘發(fā)送告警
??????enabled:?true
?????#?釘釘群機(jī)器人唯一的token
??????token:?xxxxxx
?????#?安全設(shè)置:加簽的密鑰
??????secret:?xxxxxxx

2.2、企業(yè)微信配置文件

spring:
??alarm:
????wechat:
?????#?開(kāi)啟企業(yè)微信告警
??????enabled:?true
?????#?企業(yè)微信群機(jī)器人唯一key
??????key:?xxxxxdsf
?????#?被@人的手機(jī)號(hào)
??????to-user:?1314243

2.3、郵件配置文件

spring:
??alarm:????
????mail:
??????enabled:?true
??????smtpHost:?xxx@qq.com
??????smtpPort:?22
??????to:?xxx@qq.com
??????from:?132@qq.com
??????username:?wsrf
??????password:?xxx

2.4、自定義模板配置

spring:
??alarm:
????template:
??????#?開(kāi)啟通過(guò)模板配置
??????enabled:?true
??????#?配置模板來(lái)源為文件
??????source:?FILE
??????#?配置模板數(shù)據(jù)
??????templates:
????????errorTemp:
??????????templateId:?errorTemp
??????????templateName:?服務(wù)異常模板
??????????templateContent:?這里是配置模板的內(nèi)容
  • spring:alarm:template:enabled,Boolean類型,表示開(kāi)啟告警消息使用模板發(fā)送。
  • spring:alarm:template:source,模板來(lái)源,枚舉類:JDBC(數(shù)據(jù)庫(kù))、FILE(配置文件)、MEMORY(內(nèi)存),目前只支持FILE,其他兩種可自行擴(kuò)展。
  • spring:alarm:template:templates,配置模板內(nèi)容,是一個(gè)map,errorTemp是模板id,需要使用哪種模板,就在@Alarm中的templateId設(shè)置為對(duì)應(yīng)配置文件中的templateId。

3、核心AOP分析

3.1、原理分析

3.2、自定義切面

@Aspect
@Slf4j
@RequiredArgsConstructor
public?class?AlarmAspect?{
????private?final?AlarmTemplateProvider?alarmTemplateProvider;

????private?final?static?String?ERROR_TEMPLATE?=?"\n\n<font?color=\"#F37335\">異常信息:</font>\n"?+
????????????"```java\n"?+
????????????"#{[exception]}\n"?+
????????????"```\n";

????private?final?static?String?TEXT_ERROR_TEMPLATE?=?"\n異常信息:\n"?+
????????????"#{[exception]}";

????private?final?static?String?MARKDOWN_TITLE_TEMPLATE?=?"#?【#{[title]}】\n"?+
????????????"\n請(qǐng)求狀態(tài):<font color=\"#{[stateColor]}\">#{[state]}</font>\n\n";

????private?final?static?String?TEXT_TITLE_TEMPLATE?=?"【#{[title]}】\n"?+
????????????"請(qǐng)求狀態(tài):#{[state]}\n";

????@Pointcut("@annotation(alarm)")
????public?void?alarmPointcut(Alarm?alarm)?{

????}

????@Around(value?=?"alarmPointcut(alarm)",?argNames?=?"joinPoint,alarm")
????public?Object?around(ProceedingJoinPoint?joinPoint,?Alarm?alarm)?throws?Throwable?{
????????Object?result?=?joinPoint.proceed();
????????if?(alarm.successNotice())?{
????????????String?templateId?=?alarm.templateId();
????????????String?fileTemplateContent?=?"";
????????????if?(Objects.nonNull(alarmTemplateProvider))?{
????????????????AlarmTemplate?alarmTemplate?=?alarmTemplateProvider.loadingAlarmTemplate(templateId);
????????????????fileTemplateContent?=?alarmTemplate.getTemplateContent();
????????????}
????????????String?templateContent?=?"";
????????????MessageTye?messageTye?=?alarm.messageType();
????????????if?(messageTye.equals(MessageTye.TEXT))?{
????????????????templateContent?=?TEXT_TITLE_TEMPLATE.concat(fileTemplateContent);
????????????}?else?if?(messageTye.equals(MessageTye.MARKDOWN))?{
????????????????templateContent?=?MARKDOWN_TITLE_TEMPLATE.concat(fileTemplateContent);
????????????}
????????????Map<String,?Object>?alarmParamMap?=?new?HashMap<>();
????????????alarmParamMap.put("title",?alarm.title());
????????????alarmParamMap.put("stateColor",?"#45B649");
????????????alarmParamMap.put("state",?"成功");
????????????sendAlarm(alarm,?templateContent,?alarmParamMap);
????????}
????????return?result;
????}


????@AfterThrowing(pointcut?=?"alarmPointcut(alarm)",?argNames?=?"joinPoint,alarm,e",?throwing?=?"e")
????public?void?doAfterThrow(JoinPoint?joinPoint,?Alarm?alarm,?Exception?e)?{
????????log.info("請(qǐng)求接口發(fā)生異常?:?[{}]",?e.getMessage());
????????String?templateId?=?alarm.templateId();
????????//?加載模板中配置的內(nèi)容,若有
????????String?templateContent?=?"";
????????String?fileTemplateContent?=?"";
????????if?(Objects.nonNull(alarmTemplateProvider))?{
????????????AlarmTemplate?alarmTemplate?=?alarmTemplateProvider.loadingAlarmTemplate(templateId);
????????????fileTemplateContent?=?alarmTemplate.getTemplateContent();
????????}
????????MessageTye?messageTye?=?alarm.messageType();
????????if?(messageTye.equals(MessageTye.TEXT))?{
????????????templateContent?=?TEXT_TITLE_TEMPLATE.concat(fileTemplateContent).concat(TEXT_ERROR_TEMPLATE);
????????}?else?if?(messageTye.equals(MessageTye.MARKDOWN))?{
????????????templateContent?=?MARKDOWN_TITLE_TEMPLATE.concat(fileTemplateContent).concat(ERROR_TEMPLATE);
????????}
????????Map<String,?Object>?alarmParamMap?=?new?HashMap<>();
????????alarmParamMap.put("title",?alarm.title());
????????alarmParamMap.put("stateColor",?"#FF4B2B");
????????alarmParamMap.put("state",?"失敗");
????????alarmParamMap.put("exception",?ExceptionUtil.stacktraceToString(e));
????????sendAlarm(alarm,?templateContent,?alarmParamMap);
????}

????private?void?sendAlarm(Alarm?alarm,?String?templateContent,?Map<String,?Object>?alarmParamMap)?{
????????ExpressionParser?parser?=?new?SpelExpressionParser();
????????TemplateParserContext?parserContext?=?new?TemplateParserContext();
????????String?message?=?parser.parseExpression(templateContent,?parserContext).getValue(alarmParamMap,?String.class);
????????MessageTye?messageTye?=?alarm.messageType();
????????NotifyMessage?notifyMessage?=?new?NotifyMessage();
????????notifyMessage.setTitle(alarm.title());
????????notifyMessage.setMessageTye(messageTye);
????????notifyMessage.setMessage(message);
????????AlarmFactoryExecute.execute(notifyMessage);
????}
}

4、模板提供器

4.1、AlarmTemplateProvider

定義一個(gè)抽象接口AlarmTemplateProvider,用于被具體的子類實(shí)現(xiàn)

public?interface?AlarmTemplateProvider?{


????/**
?????*?加載告警模板
?????*
?????*?@param?templateId?模板id
?????*?@return?AlarmTemplate
?????*/
????AlarmTemplate?loadingAlarmTemplate(String?templateId);
}

4.2、BaseAlarmTemplateProvider

抽象類BaseAlarmTemplateProvider實(shí)現(xiàn)該抽象接口

public?abstract?class?BaseAlarmTemplateProvider?implements?AlarmTemplateProvider?{

????@Override
????public?AlarmTemplate?loadingAlarmTemplate(String?templateId)?{
????????if?(StringUtils.isEmpty(templateId))?{
????????????throw?new?AlarmException(400,?"告警模板配置id不能為空");
????????}
????????return?getAlarmTemplate(templateId);
????}

????/**
?????*?查詢告警模板
?????*
?????*?@param?templateId?模板id
?????*?@return?AlarmTemplate
?????*/
????abstract?AlarmTemplate?getAlarmTemplate(String?templateId);
}

4.3、YamlAlarmTemplateProvider

具體實(shí)現(xiàn)類YamlAlarmTemplateProvider,實(shí)現(xiàn)從配置文件中讀取模板,該類在項(xiàng)目啟動(dòng)時(shí),會(huì)被加載進(jìn)spring的bean容器

@RequiredArgsConstructor
public?class?YamlAlarmTemplateProvider?extends?BaseAlarmTemplateProvider?{

????private?final?TemplateConfig?templateConfig;

????@Override
????AlarmTemplate?getAlarmTemplate(String?templateId)?{
????????Map<String,?AlarmTemplate>?configTemplates?=?templateConfig.getTemplates();
????????AlarmTemplate?alarmTemplate?=?configTemplates.get(templateId);
????????if?(ObjectUtils.isEmpty(alarmTemplate))?{
????????????throw?new?AlarmException(400,?"未發(fā)現(xiàn)告警配置模板");
????????}
????????return?alarmTemplate;
????}
}

4.4、MemoryAlarmTemplateProvider和JdbcAlarmTemplateProvider

抽象類BaseAlarmTemplateProvider還有其他兩個(gè)子類,分別是MemoryAlarmTemplateProviderJdbcAlarmTemplateProvider。但是這兩個(gè)子類暫時(shí)還未實(shí)現(xiàn)邏輯,后續(xù)可以自行擴(kuò)展。

@RequiredArgsConstructor
public?class?MemoryAlarmTemplateProvider?extends?BaseAlarmTemplateProvider?{

????private?final?Function<String,?AlarmTemplate>?function;
????@Override
????AlarmTemplate?getAlarmTemplate(String?templateId)?{
????????AlarmTemplate?alarmTemplate?=?function.apply(templateId);
????????if?(ObjectUtils.isEmpty(alarmTemplate))?{
????????????throw?new?AlarmException(400,?"未發(fā)現(xiàn)告警配置模板");
????????}
????????return?alarmTemplate;
????}
}
@RequiredArgsConstructor
public?class?JdbcAlarmTemplateProvider?extends?BaseAlarmTemplateProvider?{

????private?final?Function<String,?AlarmTemplate>?function;

????@Override
????AlarmTemplate?getAlarmTemplate(String?templateId)?{
????????AlarmTemplate?alarmTemplate?=?function.apply(templateId);
????????if?(ObjectUtils.isEmpty(alarmTemplate))?{
????????????throw?new?AlarmException(400,?"未發(fā)現(xiàn)告警配置模板");
????????}
????????return?alarmTemplate;
????}
}

兩個(gè)類中都有Function<String, AlarmTemplate>接口,為函數(shù)式接口,可以供外部自行去實(shí)現(xiàn)邏輯。

5、告警發(fā)送

5.1、AlarmFactoryExecute

該類內(nèi)部保存了一個(gè)容器,主要用于緩存真正的發(fā)送類

public?class?AlarmFactoryExecute?{

????private?static?List<AlarmWarnService>?serviceList?=?new?ArrayList<>();

????public?AlarmFactoryExecute(List<AlarmWarnService>?alarmLogWarnServices)?{
????????serviceList?=?alarmLogWarnServices;
????}

????public?static?void?addAlarmLogWarnService(AlarmWarnService?alarmLogWarnService)?{
????????serviceList.add(alarmLogWarnService);
????}

????public?static?List<AlarmWarnService>?getServiceList()?{
????????return?serviceList;
????}

????public?static?void?execute(NotifyMessage?notifyMessage)?{
????????for?(AlarmWarnService?alarmWarnService?:?getServiceList())?{
????????????alarmWarnService.send(notifyMessage);
????????}
????}
}

5.2、AlarmWarnService

抽象接口,只提供一個(gè)發(fā)送的方法

public?interface?AlarmWarnService?{

????/**
?????*?發(fā)送信息
?????*
?????*?@param?notifyMessage?message
?????*/
????void?send(NotifyMessage?notifyMessage);

}

5.3、BaseWarnService

與抽象的模板提供器AlarmTemplateProvider一樣的套路,該接口有一個(gè)抽象的實(shí)現(xiàn)類BaseWarnService,該類對(duì)外暴露send方法,用于發(fā)送消息,內(nèi)部用doSendMarkdown,doSendText方法實(shí)現(xiàn)具體的發(fā)送邏輯,當(dāng)然具體發(fā)送邏輯還是得由其子類去實(shí)現(xiàn)。

@Slf4j
public?abstract?class?BaseWarnService?implements?AlarmWarnService?{

????@Override
????public?void?send(NotifyMessage?notifyMessage)?{
????????if?(notifyMessage.getMessageTye().equals(MessageTye.TEXT))?{
????????????CompletableFuture.runAsync(()?->?{
????????????????try?{
????????????????????doSendText(notifyMessage.getMessage());
????????????????}?catch?(Exception?e)?{
????????????????????log.error("send?text?warn?message?error",?e);
????????????????}
????????????});
????????}?else?if?(notifyMessage.getMessageTye().equals(MessageTye.MARKDOWN))?{
????????????CompletableFuture.runAsync(()?->?{
????????????????try?{
????????????????????doSendMarkdown(notifyMessage.getTitle(),?notifyMessage.getMessage());
????????????????}?catch?(Exception?e)?{
????????????????????log.error("send?markdown?warn?message?error",?e);
????????????????}
????????????});
????????}
?}

????/**
?????*?發(fā)送Markdown消息
?????*
?????*?@param?title???Markdown標(biāo)題
?????*?@param?message?Markdown消息
?????*?@throws?Exception?異常
?????*/
????protected?abstract?void?doSendMarkdown(String?title,?String?message)?throws?Exception;

????/**
?????*?發(fā)送文本消息
?????*
?????*?@param?message?文本消息
?????*?@throws?Exception?異常
?????*/
????protected?abstract?void?doSendText(String?message)?throws?Exception;
}

5.4、DingTalkWarnService

主要實(shí)現(xiàn)了釘釘發(fā)送告警信息的邏輯

@Slf4j
public?class?DingTalkWarnService?extends?BaseWarnService?{

????private?static?final?String?ROBOT_SEND_URL?=?"https://oapi.dingtalk.com/robot/send?access_token=";
????private?final?String?token;

????private?final?String?secret;

????public?DingTalkWarnService(String?token,?String?secret)?{
????????this.token?=?token;
????????this.secret?=?secret;
????}

????public?void?sendRobotMessage(DingTalkSendRequest?dingTalkSendRequest)?throws?Exception?{
????????String?json?=?JSONUtil.toJsonStr(dingTalkSendRequest);
????????String?sign?=?getSign();
????????String?body?=?HttpRequest.post(sign).contentType(ContentType.JSON.getValue()).body(json).execute().body();
????????log.info("釘釘機(jī)器人通知結(jié)果:{}",?body);
????}

????/**
?????*?獲取簽名
?????*
?????*?@return?返回簽名
?????*/
????private?String?getSign()?throws?Exception?{
????????long?timestamp?=?System.currentTimeMillis();
????????String?stringToSign?=?timestamp?+?"\n"?+?secret;
????????Mac?mac?=?Mac.getInstance("HmacSHA256");
????????mac.init(new?SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8),?"HmacSHA256"));
????????byte[]?signData?=?mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
????????return?ROBOT_SEND_URL?+?token?+?"&timestamp="?+?timestamp?+?"&sign="?+?URLEncoder.encode(new?String(Base64.getEncoder().encode(signData)),?StandardCharsets.UTF_8.toString());
????}

????@Override
????protected?void?doSendText(String?message)?throws?Exception?{
????????DingTalkSendRequest?param?=?new?DingTalkSendRequest();
????????param.setMsgtype(DingTalkSendMsgTypeEnum.TEXT.getType());
????????param.setText(new?DingTalkSendRequest.Text(message));
????????sendRobotMessage(param);
????}

????@Override
????protected?void?doSendMarkdown(String?title,?String?message)?throws?Exception?{
????????DingTalkSendRequest?param?=?new?DingTalkSendRequest();
????????param.setMsgtype(DingTalkSendMsgTypeEnum.MARKDOWN.getType());
????????DingTalkSendRequest.Markdown?markdown?=?new?DingTalkSendRequest.Markdown(title,?message);
????????param.setMarkdown(markdown);
????????sendRobotMessage(param);
????}
}

5.5、WorkWeXinWarnService

主要實(shí)現(xiàn)了發(fā)送企業(yè)微信告警信息的邏輯

@Slf4j
public?class?WorkWeXinWarnService?extends?BaseWarnService?{
????private?static?final?String?SEND_MESSAGE_URL?=?"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=%s";
????private?final?String?key;

????private?final?String?toUser;

????public?WorkWeXinWarnService(String?key,?String?toUser)?{
????????this.key?=?key;
????????this.toUser?=?toUser;
????}

????private?String?createPostData(WorkWeXinSendMsgTypeEnum?messageTye,?String?contentValue)?{
????????WorkWeXinSendRequest?wcd?=?new?WorkWeXinSendRequest();
????????wcd.setMsgtype(messageTye.getType());
????????List<String>?toUsers?=?Arrays.asList("@all");
????????if?(StringUtils.isNotEmpty(toUser))?{
????????????String[]?split?=?toUser.split("\\|");
????????????toUsers?=?Arrays.asList(split);
????????}
????????if?(messageTye.equals(WorkWeXinSendMsgTypeEnum.TEXT))?{
????????????WorkWeXinSendRequest.Text?text?=?new?WorkWeXinSendRequest.Text(contentValue,?toUsers);
????????????wcd.setText(text);
????????}?else?if?(messageTye.equals(WorkWeXinSendMsgTypeEnum.MARKDOWN))?{
????????????WorkWeXinSendRequest.Markdown?markdown?=?new?WorkWeXinSendRequest.Markdown(contentValue,?toUsers);
????????????wcd.setMarkdown(markdown);
????????}
????????return?JSONUtil.toJsonStr(wcd);
????}

????@Override
????protected?void?doSendText(String?message)?{
????????String?data?=?createPostData(WorkWeXinSendMsgTypeEnum.TEXT,?message);
????????String?url?=?String.format(SEND_MESSAGE_URL,?key);
????????String?resp?=?HttpRequest.post(url).body(data).execute().body();
????????log.info("send?work?weixin?message?call?[{}],?param:{},?resp:{}",?url,?data,?resp);
????}

????@Override
????protected?void?doSendMarkdown(String?title,?String?message)?{
????????String?data?=?createPostData(WorkWeXinSendMsgTypeEnum.MARKDOWN,?message);
????????String?url?=?String.format(SEND_MESSAGE_URL,?key);
????????String?resp?=?HttpRequest.post(url).body(data).execute().body();
????????log.info("send?work?weixin?message?call?[{}],?param:{},?resp:{}",?url,?data,?resp);
????}
}

5.6、MailWarnService

主要實(shí)現(xiàn)郵件告警邏輯

@Slf4j
public?class?MailWarnService?extends?BaseWarnService?{

????private?final?String?smtpHost;

????private?final?String?smtpPort;

????private?final?String?to;

????private?final?String?from;

????private?final?String?username;

????private?final?String?password;

????private?Boolean?ssl?=?true;

????private?Boolean?debug?=?false;

????public?MailWarnService(String?smtpHost,?String?smtpPort,?String?to,?String?from,?String?username,?String?password)?{
????????this.smtpHost?=?smtpHost;
????????this.smtpPort?=?smtpPort;
????????this.to?=?to;
????????this.from?=?from;
????????this.username?=?username;
????????this.password?=?password;
????}

????public?void?setSsl(Boolean?ssl)?{
????????this.ssl?=?ssl;
????}

????public?void?setDebug(Boolean?debug)?{
????????this.debug?=?debug;
????}

????@Override
????protected?void?doSendText(String?message)?throws?Exception?{
????????Properties?props?=?new?Properties();
????????props.setProperty("mail.smtp.auth",?"true");
????????props.setProperty("mail.transport.protocol",?"smtp");
????????props.setProperty("mail.smtp.host",?smtpHost);
????????props.setProperty("mail.smtp.port",?smtpPort);
????????props.put("mail.smtp.ssl.enable",?true);
????????Session?session?=?Session.getInstance(props);
????????session.setDebug(false);
????????MimeMessage?msg?=?new?MimeMessage(session);
????????msg.setFrom(new?InternetAddress(from));
????????for?(String?toUser?:?to.split(","))?{
????????????msg.setRecipient(MimeMessage.RecipientType.TO,?new?InternetAddress(toUser));
????????}
????????Map<String,?String>?map?=?JSONUtil.toBean(message,?Map.class);
????????msg.setSubject(map.get("subject"),?"UTF-8");
????????msg.setContent(map.get("content"),?"text/html;charset=UTF-8");
????????msg.setSentDate(new?Date());
????????Transport?transport?=?session.getTransport();
????????transport.connect(username,?password);
????????transport.sendMessage(msg,?msg.getAllRecipients());
????????transport.close();
????}

????@Override
????protected?void?doSendMarkdown(String?title,?String?message)?throws?Exception?{
????????log.warn("暫不支持發(fā)送Markdown郵件");
????}
}

6、AlarmAutoConfiguration自動(dòng)裝配類

運(yùn)用了springboot自定義的starter,再META-INF包下的配置文件spring.factories下,配置上該類

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
????com.seven.buttemsg.autoconfigure.AlarmAutoConfiguration

自動(dòng)裝配類,用于裝載自定義的bean

@Slf4j
@Configuration
public?class?AlarmAutoConfiguration?{

????//?郵件相關(guān)配置裝載
????@Configuration
????@ConditionalOnProperty(prefix?=?MailConfig.PREFIX,?name?=?"enabled",?havingValue?=?"true")
????@EnableConfigurationProperties(MailConfig.class)
????static?class?MailWarnServiceMethod?{

????????@Bean
????????@ConditionalOnMissingBean(MailWarnService.class)
????????public?MailWarnService?mailWarnService(final?MailConfig?mailConfig)?{
????????????MailWarnService?mailWarnService?=?new?MailWarnService(mailConfig.getSmtpHost(),?mailConfig.getSmtpPort(),?mailConfig.getTo(),?mailConfig.getFrom(),?mailConfig.getUsername(),?mailConfig.getPassword());
????????????mailWarnService.setSsl(mailConfig.getSsl());
????????????mailWarnService.setDebug(mailConfig.getDebug());
????????????AlarmFactoryExecute.addAlarmLogWarnService(mailWarnService);
????????????return?mailWarnService;
????????}
????}

????//?企業(yè)微信相關(guān)配置裝載
????@Configuration
????@ConditionalOnProperty(prefix?=?WorkWeXinConfig.PREFIX,?name?=?"enabled",?havingValue?=?"true")
????@EnableConfigurationProperties(WorkWeXinConfig.class)
????static?class?WorkWechatWarnServiceMethod?{

????????@Bean
????????@ConditionalOnMissingBean(MailWarnService.class)
????????public?WorkWeXinWarnService?workWechatWarnService(final?WorkWeXinConfig?workWeXinConfig)?{
????????????return?new?WorkWeXinWarnService(workWeXinConfig.getKey(),?workWeXinConfig.getToUser());
????????}

????????@Autowired
????????void?setDataChangedListener(WorkWeXinWarnService?workWeXinWarnService)?{
????????????AlarmFactoryExecute.addAlarmLogWarnService(workWeXinWarnService);
????????}
????}

????//?釘釘相關(guān)配置裝載
????@Configuration
????@ConditionalOnProperty(prefix?=?DingTalkConfig.PREFIX,?name?=?"enabled",?havingValue?=?"true")
????@EnableConfigurationProperties(DingTalkConfig.class)
????static?class?DingTalkWarnServiceMethod?{

????????@Bean
????????@ConditionalOnMissingBean(DingTalkWarnService.class)
????????public?DingTalkWarnService?dingTalkWarnService(final?DingTalkConfig?dingtalkConfig)?{
????????????DingTalkWarnService?dingTalkWarnService?=?new?DingTalkWarnService(dingtalkConfig.getToken(),?dingtalkConfig.getSecret());
????????????AlarmFactoryExecute.addAlarmLogWarnService(dingTalkWarnService);
????????????return?dingTalkWarnService;
????????}
????}

????//?消息模板配置裝載
????@Configuration
????@ConditionalOnProperty(prefix?=?TemplateConfig.PREFIX,?name?=?"enabled",?havingValue?=?"true")
????@EnableConfigurationProperties(TemplateConfig.class)
????static?class?TemplateConfigServiceMethod?{

????????@Bean
????????@ConditionalOnMissingBean
????????public?AlarmTemplateProvider?alarmTemplateProvider(TemplateConfig?templateConfig)?{
????????????if?(TemplateSource.FILE?==?templateConfig.getSource())?{
????????????????return?new?YamlAlarmTemplateProvider(templateConfig);
????????????}?else?if?(TemplateSource.JDBC?==?templateConfig.getSource())?{
????????????????//?數(shù)據(jù)庫(kù)(如mysql)讀取文件,未實(shí)現(xiàn),可自行擴(kuò)展
????????????????return?new?JdbcAlarmTemplateProvider(templateId?->?null);
????????????}?else?if?(TemplateSource.MEMORY?==?templateConfig.getSource())?{
????????????????//?內(nèi)存(如redis,本地內(nèi)存)讀取文件,未實(shí)現(xiàn),可自行擴(kuò)展
????????????????return?new?MemoryAlarmTemplateProvider(templateId?->?null);
????????????}
????????????return?new?YamlAlarmTemplateProvider(templateConfig);
????????}


????}
????@Bean
????public?AlarmAspect?alarmAspect(@Autowired(required?=?false)?AlarmTemplateProvider?alarmTemplateProvider)?{
????????return?new?AlarmAspect(alarmTemplateProvider);
????}
}

四、總結(jié)

主要借助spring的切面技術(shù),以及springboot的自動(dòng)裝配原理,實(shí)現(xiàn)了發(fā)送告警邏輯。對(duì)業(yè)務(wù)代碼無(wú)侵入,只需要在業(yè)務(wù)代碼上標(biāo)記注解,就可實(shí)現(xiàn)可插拔的功能,比較輕量。

以上就是利用AOP實(shí)現(xiàn)系統(tǒng)告警的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于AOP系統(tǒng)告警的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論