使用spring boot +WebSocket實現(後臺主動)訊息推送
前言:使用此webscoket務必確保生產環境能相容/支援!使用此webscoket務必確保生產環境能相容/支援!使用此webscoket務必確保生產環境能相容/支援!主要是tomcat的相容與支援。
有個需求:APP使用者產生某個操作,需要讓後臺管理系統部分人員感知(表現為一個頁面訊息)。
最早版本是後臺管理系統輪訓,每隔一段時間輪訓一次,由於訊息重要,每隔幾秒就查一次。這樣做明顯很不雅!會消耗大量資源,並且大部分請求是沒有用的(查不到資料進來),很藍瘦。
後來,想著用訊息推送的方式來處理這個邏輯。使用者在app產生了目標操作,即產生一個訊息,推送給後臺管理系統的對應使用者。
然後我就找各種資料,一開始同事推薦dwz,後來發現不太適用於目前的專案(也許能實現只是我不知道如何實現)。
後來瞭解到WebSocket,網上看了很多文件都是類似聊天室的場景,有些不同。在此,我主要側重介紹下 伺服器主動推送,由服務端來觸發。
WebSocket 主要能實現的場景:
1、網頁聊天室
2、伺服器訊息實時通知
WebSocket 使用方法應該有很多,在次介紹下使用 tomcat8+h5 環境下的實現。
ps:我自己的測試環境是tomcat7這樣寫是不行的。wang115032337《https://blog.csdn.net/wang115032337》這位朋友在他的環境下,tomcat7/8都可以用本文章的寫法,只不過需要去除WebSocketConfig類(有文章表示tomcat7和8對websocket的支援是不同的,本人未深入瞭解)
話不多說,直接上程式碼,想深入瞭解WebSocket 的請查閱相關介紹。
1.pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.使用@ServerEndpoint創立websocket endpoint( wang115032337這位朋友在他的環境下加入@ServerEndpoint類會報錯,直接刪除了仍可用@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.具體實現類可自己選擇url要不要帶引數package com.star.manager.service;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
//@ServerEndpoint("/websocket/{user}")
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
//靜態變數,用來記錄當前線上連線數。應該把它設計成執行緒安全的。
private static int onlineCount = 0;
//concurrent包的執行緒安全Set,用來存放每個客戶端對應的MyWebSocket物件。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//與某個客戶端的連線會話,需要通過它來給客戶端傳送資料
private Session session;
/**
* 連線建立成功呼叫的方法*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //線上數加1
log.info("有新連線加入!當前線上人數為" + getOnlineCount());
try {
sendMessage("連線成功");
} catch (IOException e) {
log.error("websocket IO異常");
}
}
// //連線開啟時執行
// @OnOpen
// public void onOpen(@PathParam("user") String user, Session session) {
// currentUser = user;
// System.out.println("Connected ... " + session.getId());
// }
/**
* 連線關閉呼叫的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //從set中刪除
subOnlineCount(); //線上數減1
log.info("有一連線關閉!當前線上人數為" + getOnlineCount());
}
/**
* 收到客戶端訊息後呼叫的方法
*
* @param message 客戶端傳送過來的訊息*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("來自客戶端的訊息:" + message);
//群發訊息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("發生錯誤");
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群發自定義訊息
* */
public static void sendInfo(String message) throws IOException {
log.info(message);
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
產生一個訊息:產生訊息場景有多種,http(s),定時任務,mq等,這貼一個httpq請求的controller程式碼
@RequestMapping(value="/pushVideoListToWeb",method=RequestMethod.POST,consumes = "application/json")
public @ResponseBody Map<String,Object> pushVideoListToWeb(@RequestBody Map<String,Object> param) {
Map<String,Object> result =new HashMap<String,Object>();
try {
WebSocketServer.sendInfo("有新客戶呼入,sltAccountId:"+CommonUtils.getValue(param, "sltAccountId"));
result.put("operationResult", true);
}catch (IOException e) {
result.put("operationResult", true);
}
return result;
}
重要的地方我都加粗了,主要是這段,使用這個方法,可以實現伺服器主動推送。
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
4.js(html就不寫了,隨便找個能觸發這個js的就可以)
//socket = new WebSocket("ws://localhost:9094/starManager/websocket/張三");
var socket;
if(typeof(WebSocket) == "undefined") {
console.log("您的瀏覽器不支援WebSocket");
}else{
console.log("您的瀏覽器支援WebSocket");
//實現化WebSocket物件,指定要連線的伺服器地址與埠 建立連線
//socket = new WebSocket("ws://localhost:9094/starManager/websocket/張三")
socket = new WebSocket("ws://localhost:9094/starManager/websocket");
//開啟事件
socket.onopen = function() {
console.log("Socket 已開啟");
//socket.send("這是來自客戶端的訊息" + location.href + new Date());
};
//獲得訊息事件
socket.onmessage = function(msg) {
console.log(msg.data);
//發現訊息進入 調後臺獲取
getCallingList();
};
//關閉事件
socket.onclose = function() {
console.log("Socket已關閉");
};
//發生了錯誤事件
socket.onerror = function() {
alert("Socket發生了錯誤");
}
$(window).unload(function(){
socket.close();
});
// $("#btnSend").click(function() {
// socket.send("這是來自客戶端的訊息" + location.href + new Date());
// });
//
// $("#btnClose").click(function() {
// socket.close();
// });
}
簡單說說:
通過前端程式碼
socket = new WebSocket("ws://localhost:9094/starManager/websocket");
其中,starManager是工程名,/webscoket是訪問路徑名
建立連線,前端呼叫scoket.open() 會使後臺在靜態成員變數webSocketSet裡面增加一個元素,相當於一個快取。後臺服務呼叫sendMessage
(指定某個使用者,定向)或sendInfo(遍歷webSocketSet逐個傳送,類似群發)方法,即可向已登入的客戶端推送訊息。
程式碼就這麼多。我的用這些程式碼就跑的起來。做的時候出現過頁面報404等錯誤,如果也是spring boot+h5,仔細核對下和我程式碼有無區別,加配置 路徑是有ok,問題應該不大。
如果你恰好也有可以用WebSocket實現的類似場景,希望對你有幫助。如有寫的不對或不夠好的地方,歡迎指正。
相關推薦
使用spring boot +WebSocket實現(後臺主動)訊息推送
前言:使用此webscoket務必確保生產環境能相容/支援!使用此webscoket務必確保生產環境能相容/支援!使用此webscoket務必確保生產環境能相容/支援!主要是tomcat的相容與支援。有個需求:APP使用者產生某個操作,需要讓後臺管理系統部分人員感知(表現為一
resin4.0.44+websocket 實現私信功能服務端訊息推送
最近專案開發中,碰到一個新的開發需求——私信功能。 專案要求:類似微博中傳送私信功能,給對方傳送一條私信訊息,如果對方線上就立馬接受到訊息提示,並顯示到頁面上。如果對方不線上,則下次登入以後,顯示訊息提示。 技術選擇:websocket也是目前比較流行的接收
Spring Boot入門系列(十八)整合mybatis,使用註解的方式實現增刪改查
之前介紹了Spring Boot 整合mybatis 使用xml配置的方式實現增刪改查,還介紹了自定義mapper 實現複雜多表關聯查詢。雖然目前 mybatis 使用xml 配置的方式 已經極大減輕了配置的複雜度,支援 generator 外掛 根據表結構自動生成實體類、配置檔案和dao層程式碼,減輕很大一
Spring Boot入門系列(十七)整合Mybatis,建立自定義mapper 實現多表關聯查詢!
之前講了Springboot整合Mybatis,介紹瞭如何自動生成pojo實體類、mapper類和對應的mapper.xml 檔案,並實現最基本的增刪改查功能。mybatis 外掛自動生成的mapper 實現了大部分基本、通用的方法,如:insert、update、delete、select 等大概20個左右
Spring Boot入門系列(十九)整合mybatis,使用註解實現動態Sql、引數傳遞等常用操作!
前面介紹了Spring Boot 整合mybatis 使用註解的方式實現資料庫操作,介紹瞭如何自動生成註解版的mapper 和pojo類。 接下來介紹使用mybatis 常用註解以及如何傳引數等資料庫操作中的常用操作。 其實,mybatis 註解方式 和 XML配置方式兩者的使用基本上相同,只有在構建 SQL
spring-boot-starter-actuator(健康監控)配置和使用
frame maven git 追蹤 包括 屬性 per dump zookeepe 在生產環境中,需要實時或定期監控服務的可用性。Spring Boot的actuator(健康監控)功能提供了很多監控所需的接口,可以對應用系統進行配置查看、相關功能統計等。 集成:
Java框架spring Boot學習筆記(十四):log4j介紹
inf alt 技術分享 images 使用 image 詳細 配置文件 -128 功能 日誌功能,通過log4j可以看到程序運行過程的詳細信息。 使用 導入log4j的jar包 復制log4j的配置文件,復制到src下面 3.設置日誌級別
spring boot系統學習(知識點筆記)
調試接口 .com tco map aid 結果 ota http 而且 一、http的註解配置 1、@SpringBootAplication=@SpringBootConfiguration(其實就是個@Configuration)+@EnableAutoConfi
spring boot 郵件傳送(帶附件)
首先開啟QQ郵箱的POP.SMTP伺服器,獲取授權碼。 設定-->賬戶-->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務 pom.xml需要載入三個jar,可以在這個網站裡下載:https://mvnrepository.com/
spring boot 整合 freemark(簡單結構)
一、建立Mean 專案 這個就不多說了 二、我的spring boot demo 結構 如下: 三、主要的配置檔案(application.properties ;pom.xml ; log4j2.xml) (1、)application.properties 檔案
Spring Boot 自動配置(auto-configurtion) 揭祕
本章,我們為你揭祕Spring Boot自動配置(Auto Configuration)執行機制,談到auto-configuration,肯定離不開@EnableAutoConfiguration註解。 package org.springframework.
Spring Boot 學習筆記(十二)——單元測試
依賴關係 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test&
Spring boot Mybatis 整合(完整版)
個人開源專案 springboot+mybatis+thymeleaf+docker構建的個人站點開源專案(集成了個人主頁、個人作品、個人部落格) 推薦開源專案 開源的springboot介面文件元件swagger2 更多幹貨 SpringBoot
spring-boot前世今生(簡單介紹)
序 本文主要講述spring boot的由來,即其它誕生的背景,初衷,現狀,及對未來的展望。 背景 在很早的年代,J2EE還是java企業級應用的王者規範,EJB風行其道。後來有一個叫Rod Johnson的音樂學博士,寫了本《Expert One on one J
spring boot整合hessian(十二)
1.首先新增hessian依賴 <dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifact
Spring Boot配置neo4j(簡單版)
圖資料庫的開發已經變得越來越流行,與springBoot結合也是很正常,在很早前就已經發布了相關Lib,但是當前網上的Spring Boot整合neo4j都極其複雜,也導致了本人在開發過程中耗費很長時間,顧寫下這個文章幫助大眾理順neo4j整合。只需要簡單六步,順序按照編寫
Spring Boot自動配置(Auto-Configuration),@EnableAutoConfiguration,Spring Beans和依賴注入
自動配置(Auto-Configuration) 自動配置(auto-configuration)是Spring Boot最重要的特性之一,因為該特性會根據應用的classpath(這個主要是根據maven pom.xml決定),annotations和其他的
使用Intellij中的Spring Initializr來快速構建Spring Boot/Cloud工程(十五)
在之前的所有Spring Boot和Spring Cloud相關博文中,都會涉及Spring Boot工程的建立。而建立的方式多種多樣,我們可以通過Maven來手工構建或是通過腳手架等方式快速搭建,也可以通過《Spring Boot快速入門》一文中提到的SPRING INITIALIZR頁面工具來建立,相信每
spring boot + webSocket 實現簡單會話與線上人數統計的demo
webSocket推送是常用於生產專案的模組,在我們部門做的一個彙報演示的demo中遇到了webSocket的一些問題。 自己下來看看了看webSocket的東西,結合spring boot 做了一個簡單的demo; 介紹的部分大家可以參考眾多的帖子,度娘 http://w
Spring boot +Mybatis 實戰(完整版)
個人開源專案 更多幹貨 正題 本專案使用的環境: 開發工具:Intellij IDEA 2017.1.3 springboot: 1.5.6 jdk:1.8.0_161 maven:3.3.9 額外功能 PageHelper 分頁外掛 myb