SpEL在動態執行業務中的應用

前言

相信作java後端的coder都對SpEL有所瞭解。java

本篇blog不是詳細介紹SpEL的定義、功能和詳細的使用方法的文章,是想和你們分享一下實際業務中遇到的問題和最終使用SpEL作爲解決方案的思考過程。後端

在筆者所處的物聯網行業中平臺端須要對設備端上報的數據進行監控和告警。告警規則須要支持後臺配置,可動態配置告警指標和告警閾值以及告警短信和郵件的消息模板數組

這個業務須要中須要動態配置3個數據bash

  • 告警指標
  • 告警閾值
  • 告警消息模板

1. 告警指標

告警指標由業務決定了其所在領域內的關注點,程序須要可以根據配置取得對應的值ui

2. 告警閾值

告警閾值決定了告警的觸發條件相似於規則引擎中規則命中和工做流引擎中的網關。編碼

會遇到簡單的關係運算如 temperature > 40(溫度大於40°C觸發告警),多條件關係運算 temperature > 25 & humidity > 30 (溫度大於25°C而且溼度大於30%觸發告警)等業務需求。spa

3. 告警消息模板

產生了相應的告警事件後須要將告警信息經過短信或者郵件發送出去,根據市場需求平臺須要支持客戶能夠按照本身的行業特性自行定義告警的內容。code

基於SpEL強大的運行時執行,解決監控告警需求

解決動態獲取告警指標值

SpEL 支持訪問屬性,數組,集合,能夠根據一個特定的對象實例求其內部的屬性值cdn

好比須要獲取設備上報的電流值對象

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對象中的electricity屬性值
Object targetValue = expTargetValue.getValue(deviceStatusDto);
複製代碼

解決告警閾值即告警規則的命中問題

SpEL 支持關係運算

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) {
    // 觸發告警邏輯
    ...
}
複製代碼

告警消息模板

SpEL 支持對象調用等對象操做

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();
                
// 根據SpringEL告警模板生成告警內容
ExpressionParser parser = new SpelExpressionParser();
Expression expAlarmDesc = parser.parseExpression("'溫度告警SN:' + ueSn + '溫度:' + temperature + '℃'");
String alarmDesc = expAlarmDesc.getValue(deviceStatusDto, String.class);
複製代碼

使用告警配置表存儲SpEL表達式知足市場可自由配置化需求

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 '建立時間',
  `modify_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  `product_code` varchar(32) NOT NULL COMMENT '產品編碼',
  `alarm_target` varchar(255) NOT NULL COMMENT '告警指標(SprEL表達式)',
  `alarm_condition` varchar(255) NOT NULL COMMENT '告警條件(SprEL表達式)',
  `alarm_channel` varchar(255) NOT NULL COMMENT '告警通道 郵件:E_MAIL、App推送: PUSH、短信: SMS ,多個使用,號分割',
  `alarm_receiver` varchar(255) NOT NULL COMMENT '告警接收人',
  `alarm_template` varchar(500) NOT NULL COMMENT '告警內容模板(SprEL表達式',
  `alarm_frequency` int(10) NOT NULL COMMENT '告警頻率(告警間隔時間 單位:分鐘)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
複製代碼

告警規則配置示例
相關文章
相關標籤/搜索