前言
相信做java后端的coder都對(duì)SpEL有所了解慷暂。
本篇blog不是詳細(xì)介紹SpEL的定義、功能和詳細(xì)的使用方法的文章命黔,是想和大家分享一下實(shí)際業(yè)務(wù)中遇到的問題和最終使用SpEL做為解決方案的思考過程呜呐。
在筆者所處的物聯(lián)網(wǎng)行業(yè)中平臺(tái)端需要對(duì)設(shè)備端上報(bào)的數(shù)據(jù)進(jìn)行監(jiān)控和告警。告警規(guī)則需要支持后臺(tái)配置悍募,可動(dòng)態(tài)配置告警指標(biāo)和告警閾值以及告警短信和郵件的消息模板蘑辑。
這個(gè)業(yè)務(wù)需要中需要?jiǎng)討B(tài)配置3個(gè)數(shù)據(jù)
- 告警指標(biāo)
- 告警閾值
- 告警消息模板
1. 告警指標(biāo)
告警指標(biāo)由業(yè)務(wù)決定了其所在領(lǐng)域內(nèi)的關(guān)注點(diǎn),程序需要能夠根據(jù)配置取得對(duì)應(yīng)的值
2. 告警閾值
告警閾值決定了告警的觸發(fā)條件類似于規(guī)則引擎中規(guī)則命中和工作流引擎中的網(wǎng)關(guān)坠宴。
會(huì)遇到簡(jiǎn)單的關(guān)系運(yùn)算如 temperature > 40(溫度大于40°C觸發(fā)告警)洋魂,多條件關(guān)系運(yùn)算 temperature > 25 & humidity > 30 (溫度大于25°C并且濕度大于30%觸發(fā)告警)等業(yè)務(wù)需求。
3. 告警消息模板
產(chǎn)生了相應(yīng)的告警事件后需要將告警信息通過短信或者郵件發(fā)送出去喜鼓,根據(jù)市場(chǎng)需求平臺(tái)需要支持客戶可以按照自己的行業(yè)特性自行定義告警的內(nèi)容副砍。
基于SpEL強(qiáng)大的運(yùn)行時(shí)執(zhí)行,解決監(jiān)控告警需求
解決動(dòng)態(tài)獲取告警指標(biāo)值
SpEL 支持訪問屬性,數(shù)組,集合庄岖,可以根據(jù)一個(gè)特定的對(duì)象實(shí)例求其內(nèi)部的屬性值
比如需要獲取設(shè)備上報(bào)的電流值
DeviceStatusDTO deviceStatusDto = DeviceStatusDTO.builder()
.ueSn("P004000000")
.productCode("6")
.storeId(20140L)
.ueType(4)
.voltage(30.0)
.electricity(10.0)
.temperature(40.0)
.lastReportTime(new Date())
.build();
ExpressionParser parser = new SpelExpressionParser();
Expression expTargetValue = parser.parseExpression("electricity");
// targetValue 即為deviceStatusDto對(duì)象中的electricity屬性值
Object targetValue = expTargetValue.getValue(deviceStatusDto);
解決告警閾值即告警規(guī)則的命中問題
SpEL 支持關(guān)系運(yùn)算
DeviceStatusDTO deviceStatusDto = DeviceStatusDTO.builder()
.ueSn("P004000000")
.productCode("6")
.storeId(20140L)
.ueType(4)
.voltage(30.0)
.electricity(10.0)
.temperature(40.0)
.lastReportTime(new Date())
.build();
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("temperature > 55");
boolean fire = exp.getValue(deviceStatusDto, Boolean.class);
if(fire) {
// 觸發(fā)告警邏輯
...
}
告警消息模板
SpEL 支持對(duì)象調(diào)用等對(duì)象操作
DeviceStatusDTO deviceStatusDto = DeviceStatusDTO.builder()
.ueSn("P004000000")
.productCode("6")
.storeId(20140L)
.ueType(4)
.voltage(30.0)
.electricity(10.0)
.temperature(40.0)
.lastReportTime(new Date())
.build();
// 根據(jù)SpringEL告警模板生成告警內(nèi)容
ExpressionParser parser = new SpelExpressionParser();
Expression expAlarmDesc = parser.parseExpression("'溫度告警SN:' + ueSn + '溫度:' + temperature + '℃'");
String alarmDesc = expAlarmDesc.getValue(deviceStatusDto, String.class);
使用告警配置表存儲(chǔ)SpEL表達(dá)式滿足市場(chǎng)可自由配置化需求
CREATE TABLE `e_ue_alarm_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`version` int(10) NOT NULL COMMENT '版本',
`create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間',
`modify_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時(shí)間',
`product_code` varchar(32) NOT NULL COMMENT '產(chǎn)品編碼',
`alarm_target` varchar(255) NOT NULL COMMENT '告警指標(biāo)(SprEL表達(dá)式)',
`alarm_condition` varchar(255) NOT NULL COMMENT '告警條件(SprEL表達(dá)式)',
`alarm_channel` varchar(255) NOT NULL COMMENT '告警通道 郵件:E_MAIL豁翎、App推送: PUSH、短信: SMS ,多個(gè)使用隅忿,號(hào)分割',
`alarm_receiver` varchar(255) NOT NULL COMMENT '告警接收人',
`alarm_template` varchar(500) NOT NULL COMMENT '告警內(nèi)容模板(SprEL表達(dá)式',
`alarm_frequency` int(10) NOT NULL COMMENT '告警頻率(告警間隔時(shí)間 單位:分鐘)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;