From f78657473e85487c09cd3c10112db48a0c4a7c4e Mon Sep 17 00:00:00 2001
From: xiaoQQya <xiaoQQya@126.com>
Date: 星期一, 06 十一月 2023 20:34:58 +0800
Subject: [PATCH] fix(报警推送): 修复报警推送功能无效的问题
---
web_src/src/main.js | 13 +--
/dev/null | 37 ---------
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java | 11 +-
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/sse/SseController.java | 55 +++++++++++++
web_src/src/layout/UiHeader.vue | 16 ++-
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java | 77 +++++++++++--------
6 files changed, 121 insertions(+), 88 deletions(-)
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
index 6a24735..9cb3a1f 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
@@ -1,12 +1,12 @@
package com.genersoft.iot.vmp.conf.security;
import com.genersoft.iot.vmp.conf.UserSetting;
-import org.springframework.core.annotation.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
@@ -28,6 +28,7 @@
/**
* 閰嶇疆Spring Security
+ *
* @author lin
*/
@Configuration
@@ -75,6 +76,7 @@
matchers.add("/js/**");
matchers.add("/api/device/query/snap/**");
matchers.add("/record_proxy/*/**");
+ matchers.add("/api/emit");
matchers.addAll(userSetting.getInterfaceAuthenticationExcludes());
// 鍙互鐩存帴璁块棶鐨勯潤鎬佹暟鎹�
web.ignoring().antMatchers(matchers.toArray(new String[0]));
@@ -83,6 +85,7 @@
/**
* 閰嶇疆璁よ瘉鏂瑰紡
+ *
* @param auth
* @throws Exception
*/
@@ -111,7 +114,7 @@
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
- .antMatchers("/api/user/login","/index/hook/**","/zlm_Proxy/FhTuMYqB2HeCuNOb/record/t/1/2023-03-25/16:35:07-16:35:16-9353.mp4").permitAll()
+ .antMatchers("/api/user/login", "/index/hook/**").permitAll()
.anyRequest().authenticated()
// 寮傚父澶勭悊鍣�
.and()
@@ -124,7 +127,7 @@
}
- CorsConfigurationSource configurationSource(){
+ CorsConfigurationSource configurationSource() {
// 閰嶇疆璺ㄥ煙
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
@@ -135,7 +138,7 @@
corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader()));
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
- url.registerCorsConfiguration("/**",corsConfiguration);
+ url.registerCorsConfiguration("/**", corsConfiguration);
return url;
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java
index 9ee6477..aef5907 100755
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java
@@ -1,55 +1,68 @@
package com.genersoft.iot.vmp.gb28181.event.alarm;
-import org.springframework.context.ApplicationListener;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
- * @description: 鎶ヨ浜嬩欢鐩戝惉
- * @author: lawrencehj
- * @data: 2021-01-20
+ * 鎶ヨ浜嬩欢鐩戝惉鍣�.
+ *
+ * @author lawrencehj
+ * @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
+ * @since 2021/01/20
*/
-
@Component
public class AlarmEventListener implements ApplicationListener<AlarmEvent> {
- private final static Logger logger = LoggerFactory.getLogger(AlarmEventListener.class);
+ private static final Logger logger = LoggerFactory.getLogger(AlarmEventListener.class);
- private static Map<String, SseEmitter> sseEmitters = new Hashtable<>();
+ private static final Map<String, PrintWriter> SSE_CACHE = new ConcurrentHashMap<>();
- public void addSseEmitters(String browserId, SseEmitter sseEmitter) {
- sseEmitters.put(browserId, sseEmitter);
+ public void addSseEmitter(String browserId, PrintWriter writer) {
+ SSE_CACHE.put(browserId, writer);
+ logger.info("SSE 鍦ㄧ嚎鏁伴噺: {}", SSE_CACHE.size());
+ }
+
+ public void removeSseEmitter(String browserId, PrintWriter writer) {
+ SSE_CACHE.remove(browserId, writer);
+ logger.info("SSE 鍦ㄧ嚎鏁伴噺: {}", SSE_CACHE.size());
}
@Override
- public void onApplicationEvent(AlarmEvent event) {
+ public void onApplicationEvent(@NotNull AlarmEvent event) {
if (logger.isDebugEnabled()) {
- logger.debug("璁惧鎶ヨ浜嬩欢瑙﹀彂锛宒eviceId锛�" + event.getAlarmInfo().getDeviceId() + ", "
- + event.getAlarmInfo().getAlarmDescription());
+ logger.debug("璁惧鎶ヨ浜嬩欢瑙﹀彂, deviceId: {}, {}", event.getAlarmInfo().getDeviceId(), event.getAlarmInfo().getAlarmDescription());
}
- String msg = "<strong>璁惧缂栫爜锛�</strong> <i>" + event.getAlarmInfo().getDeviceId() + "</i>"
- + "<br><strong>鎶ヨ鎻忚堪锛�</strong> <i>" + event.getAlarmInfo().getAlarmDescription() + "</i>"
- + "<br><strong>鎶ヨ鏃堕棿锛�</strong> <i>" + event.getAlarmInfo().getAlarmTime() + "</i>"
- + "<br><strong>鎶ヨ浣嶇疆锛�</strong> <i>" + event.getAlarmInfo().getLongitude() + "</i>"
- + ", <i>" + event.getAlarmInfo().getLatitude() + "</i>";
- for (Iterator<Map.Entry<String, SseEmitter>> it = sseEmitters.entrySet().iterator(); it.hasNext();) {
- Map.Entry<String, SseEmitter> emitter = it.next();
- logger.info("鎺ㄩ�佸埌SSE杩炴帴锛屾祻瑙堝櫒ID: " + emitter.getKey());
+ String msg = "<strong>璁惧缂栧彿锛�</strong> <i>" + event.getAlarmInfo().getDeviceId() + "</i>"
+ + "<br><strong>閫氶亾缂栧彿锛�</strong> <i>" + event.getAlarmInfo().getChannelId() + "</i>"
+ + "<br><strong>鎶ヨ鎻忚堪锛�</strong> <i>" + event.getAlarmInfo().getAlarmDescription() + "</i>"
+ + "<br><strong>鎶ヨ鏃堕棿锛�</strong> <i>" + event.getAlarmInfo().getAlarmTime() + "</i>";
+
+ for (Iterator<Map.Entry<String, PrintWriter>> it = SSE_CACHE.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry<String, PrintWriter> response = it.next();
+ logger.info("鎺ㄩ�佸埌 SSE 杩炴帴, 娴忚鍣� ID: {}", response.getKey());
try {
- emitter.getValue().send(msg);
- } catch (IOException | IllegalStateException e) {
- if (logger.isDebugEnabled()) {
- logger.debug("SSE杩炴帴宸插叧闂�");
+ PrintWriter writer = response.getValue();
+
+ if (writer.checkError()) {
+ it.remove();
+ continue;
}
- // 绉婚櫎宸插叧闂殑杩炴帴
+
+ String sseMsg = "event:message\n" +
+ "data:" + msg + "\n" +
+ "\n";
+ writer.write(sseMsg);
+ writer.flush();
+ } catch (Exception e) {
it.remove();
}
}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java
deleted file mode 100755
index b1ad3b9..0000000
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.genersoft.iot.vmp.vmanager.gb28181.SseController;
-
-import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
-
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
-/**
- * @description: SSE鎺ㄩ��
- * @author: lawrencehj
- * @data: 2021-01-20
- */
-@Tag(name = "SSE鎺ㄩ��")
-
-@Controller
-@RequestMapping("/api")
-public class SseController {
- @Autowired
- AlarmEventListener alarmEventListener;
-
- @GetMapping("/emit")
- public SseEmitter emit(@RequestParam String browserId) {
- final SseEmitter sseEmitter = new SseEmitter(0L);
- try {
- alarmEventListener.addSseEmitters(browserId, sseEmitter);
- }catch (Exception e){
- sseEmitter.completeWithError(e);
- }
- return sseEmitter;
- }
-}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/sse/SseController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/sse/SseController.java
new file mode 100644
index 0000000..575f22b
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/sse/SseController.java
@@ -0,0 +1,55 @@
+package com.genersoft.iot.vmp.vmanager.gb28181.sse;
+
+import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+
+/**
+ * SSE 鎺ㄩ��.
+ *
+ * @author lawrencehj
+ * @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
+ * @since 2021/01/20
+ */
+@Tag(name = "SSE 鎺ㄩ��")
+@RestController
+@RequestMapping("/api")
+public class SseController {
+
+ @Resource
+ private AlarmEventListener alarmEventListener;
+
+ /**
+ * SSE 鎺ㄩ��.
+ *
+ * @param response 鍝嶅簲
+ * @param browserId 娴忚鍣↖D
+ * @throws IOException IOEXCEPTION
+ * @author <a href="mailto:xiaoQQya@126.com">xiaoQQya</a>
+ * @since 2023/11/06
+ */
+ @GetMapping("/emit")
+ public void emit(HttpServletResponse response, @RequestParam String browserId) throws IOException, InterruptedException {
+ response.setContentType("text/event-stream");
+ response.setCharacterEncoding("utf-8");
+
+ PrintWriter writer = response.getWriter();
+ alarmEventListener.addSseEmitter(browserId, writer);
+
+ while (!writer.checkError()) {
+ Thread.sleep(1000);
+ writer.write(":keep alive\n\n");
+ writer.flush();
+ }
+ alarmEventListener.removeSseEmitter(browserId, writer);
+ }
+}
diff --git a/web_src/src/layout/UiHeader.vue b/web_src/src/layout/UiHeader.vue
index 2cdca02..fdfcb9f 100755
--- a/web_src/src/layout/UiHeader.vue
+++ b/web_src/src/layout/UiHeader.vue
@@ -37,7 +37,6 @@
</template>
<script>
-
import changePasswordDialog from '../components/dialog/changePassword.vue'
import userService from '../components/service/UserService'
import {Notification} from 'element-ui';
@@ -55,18 +54,19 @@
};
},
created() {
- console.log(4444)
console.log(JSON.stringify(userService.getUser()))
if (this.$route.path.startsWith("/channelList")) {
this.activeIndex = "/deviceList"
-
}
},
mounted() {
window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
- // window.addEventListener('unload', e => this.unloadHandler(e))
this.alarmNotify = this.getAlarmSwitchStatus() === "true";
- this.sseControl();
+
+ // TODO: 姝ゅ寤惰繜杩炴帴 sse, 閬垮厤 sse 杩炴帴鏃� browserId 杩樻湭鐢熸垚, 鍚庣画寰呬紭鍖�
+ setTimeout(() => {
+ this.sseControl()
+ }, 3000);
},
methods: {
loginout() {
@@ -107,10 +107,12 @@
this.sseSource = new EventSource('/api/emit?browserId=' + this.$browserId);
this.sseSource.addEventListener('message', function (evt) {
that.$notify({
- title: '鏀跺埌鎶ヨ淇℃伅',
+ title: '鎶ヨ淇℃伅',
dangerouslyUseHTMLString: true,
message: evt.data,
- type: 'warning'
+ type: 'warning',
+ position: 'bottom-right',
+ duration: 3000
});
console.log("鏀跺埌淇℃伅锛�" + evt.data);
});
diff --git a/web_src/src/main.js b/web_src/src/main.js
index a6c6e1b..328bb25 100755
--- a/web_src/src/main.js
+++ b/web_src/src/main.js
@@ -1,21 +1,19 @@
import Vue from 'vue';
import App from './App.vue';
-
-Vue.config.productionTip = false;
-import ElementUI from 'element-ui';
+import ElementUI, {Notification} from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import router from './router/index.js';
import axios from 'axios';
import VueCookies from 'vue-cookies';
-import echarts from 'echarts';
import VCharts from 'v-charts';
import VueClipboard from 'vue-clipboard2';
-import {Notification} from 'element-ui';
import Fingerprint2 from 'fingerprintjs2';
import VueClipboards from 'vue-clipboards';
import Contextmenu from "vue-contextmenujs"
import userService from "./components/service/UserService"
+
+Vue.config.productionTip = false;
// 鐢熸垚鍞竴ID
@@ -29,10 +27,9 @@
//console.log(values) //浣跨敤鐨勬祻瑙堝櫒淇℃伅npm
// 鐢熸垚鏈�缁坕d
let port = window.location.port;
- console.log(port);
const fingerPrint = Fingerprint2.x64hash128(values.join(port), 31)
Vue.prototype.$browserId = fingerPrint;
- console.log("鍞竴鏍囪瘑鐮侊細" + fingerPrint);
+ console.log("娴忚鍣� ID: " + fingerPrint);
});
Vue.use(VueClipboard);
@@ -75,7 +72,7 @@
);
Vue.prototype.$axios = axios;
-Vue.prototype.$cookies.config(60*30);
+Vue.prototype.$cookies.config(60 * 30);
new Vue({
router: router,
--
Gitblit v1.8.0