1. 程式人生 > >ssm中spring websocket 實現伺服器推送訊息 以及 一對一聊天

ssm中spring websocket 實現伺服器推送訊息 以及 一對一聊天

上網看了很多方式,最後覺得這種方式比較簡單易懂,這邊主要有三個類(包括註解的配置檔案)就可以實現後臺內容

文末會展示結果例項,如果是你所需要的效果,直接拿去用吧~專案中複製直接用

本文根據網上整理並修改!!!

本文思路來自:連結

現在開始。開始前請確保pom已經引入需要的包

首先是配置檔案類(註解)

/** 
 * Spring WebSocket的配置,這裡採用的是註解的方式 
 */  
  
@Configuration  
@EnableWebMvc//這個標註可以不加,如果有加,要extends WebMvcConfigurerAdapter  
@EnableWebSocket  
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {  
  
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {  
        //1.註冊WebSocket  
        String websocket_url = "/websocket/socketServer";                        //設定websocket的地址  
        registry.addHandler(webSocketHandler(), websocket_url).                          //註冊Handler  
                addInterceptors(new WebSocketHandshakeInterceptor());                   //註冊Interceptor  
  
        //2.註冊SockJS,提供SockJS支援(主要是相容ie8)  
        String sockjs_url = "/sockjs/socketServer";                              //設定sockjs的地址  
        registry.addHandler(webSocketHandler(), sockjs_url).                            //註冊Handler  
                addInterceptors(new WebSocketHandshakeInterceptor()).                   //註冊Interceptor  
                withSockJS();                                                           //支援sockjs協議  
    }  
  
    @Bean
    public TextWebSocketHandler webSocketHandler() {  
        return new WebSocketHandler();  
    }  
}  

然後是連線攔截器類,主要是攔截連線並且設定使用者session標識作用,這樣在最後一個處理請求類可以分清是哪個已連線使用者發出的請求~,

/** 
 * WebSocket握手攔截器 
 */  
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {  
 
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> attributes) throws Exception {  

    	if (request instanceof ServletServerHttpRequest) {
    		ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;  
            HttpSession session = servletRequest.getServletRequest().getSession(false);  
            if (session != null) {  
                String userName = (String) session.getAttribute("SESSION_USERNAME");  //這邊獲得登入時設定的唯一使用者標識
                if (userName == null) {  
                    userName = "未知" + session.getId();  
                }  
                attributes.put("WEBSOCKET_USERNAME", userName);  //將使用者標識放入引數列表後,下一步的websocket處理器可以讀取這裡面的資料
            }  
        }  
        return true;  
    }  
  
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {  
        System.out.println("After Handshake");  
    }
}  

我在參考部落格的基礎上修改成一對一識別的方式,識別使用者的方式是根據‘@‘分隔符處理傳來的字串,格式是

“目標使用者標識@文字資訊”,這樣可以知道是要發給哪個已連線使用者的,如果沒有找到這個使用者標識,返回給使用者對方不線上或者對方線上異常 資訊。。。返回的資訊可以是“狀態碼@文字資訊(或者是提示資訊)”前端根據狀態碼來顯示是否是正常聊天內容還是異常資訊。。。 在文末看例項就知道啦

處理器:

/**
 * Websocket處理器
 */

public class WebSocketHandler extends TextWebSocketHandler {

	// 已建立連線的使用者
	private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();

	/**
	 * 處理前端傳送的文字資訊 js呼叫websocket.send時候,會呼叫該方法
	 * 
	 * @param session
	 * @param message
	 * @throws Exception
	 */
	@Override
	protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
		String username = (String) session.getAttributes().get("WEBSOCKET_USERNAME");

		// 獲取提交過來的訊息詳情
		System.out.println("收到使用者 " + username + " 的訊息:" + message.toString());
		// 分割成id和資訊內容
		String[] messageInfo = message.getPayload().split("@");
		if (messageInfo.length != 2) {
			sendMessageToUser(username, new TextMessage("
[email protected]
伺服器出錯請稍後再發送吧")); } else { String target = messageInfo[0]; String content = messageInfo[1]; // 遍歷所有已連線使用者 for (WebSocketSession user : users) { if (user.getAttributes().get("WEBSOCKET_USERNAME").equals(target)) { //遇到匹配使用者 連線正常則傳送訊息 if (user.isOpen()) { sendMessageToUser(target, new TextMessage("[email protected]"+content)); }else{//若異常則傳送失敗 sendMessageToUser(username, new TextMessage("[email protected]對方線上異常,傳送失敗")); } return; } } //未找到匹配使用者 傳送失敗 sendMessageToUser(username, new TextMessage("[email protected]對方暫時不線上")); } } /** * 當新連線建立的時候,被呼叫 連線成功時候,會觸發頁面上onOpen方法 * * @param session * @throws Exception */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { users.add(session); String username = (String) session.getAttributes().get("WEBSOCKET_USERNAME"); System.out.println("使用者 " + username + " Connection Established"); session.sendMessage(new TextMessage(username + " connect")); } /** * 當連線關閉時被呼叫 * * @param session * @param status * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { String username = (String) session.getAttributes().get("WEBSOCKET_USERNAME"); System.out.println("使用者 " + username + " Connection closed. Status: " + status); users.remove(session); } /** * 傳輸錯誤時呼叫 * * @param session * @param exception * @throws Exception */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { String username = (String) session.getAttributes().get("WEBSOCKET_USERNAME"); if (session.isOpen()) { session.close(); } System.out.println("使用者: " + username + " websocket connection closed......"); users.remove(session); } /** * 給所有線上使用者傳送訊息 * * @param message */ public void sendMessageToUsers(TextMessage message) { for (WebSocketSession user : users) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } } /** * 給某個使用者傳送訊息 * * @param userName * @param message */ public void sendMessageToUser(String userName, TextMessage message) { for (WebSocketSession user : users) { if (user.getAttributes().get("WEBSOCKET_USERNAME").equals(userName)) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } break; } } } }

接下來是例項:

先建立一個登入控制器,這樣能區分使用者。

@Controller
public class WebSocketController {

	@Bean // 這個註解會從Spring容器拿出Bean
	public WebSocketHandler infoHandler() {
		return new WebSocketHandler();
	}

	@RequestMapping("/login")
	public String login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String username = request.getParameter("username");
		System.out.println(username + "登入");
		HttpSession session = request.getSession();
		session.setAttribute("SESSION_USERNAME", username);
		return "websocket";
	}
}

然後是登陸頁面 index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
	<h2>Wellcome</h2>
	<form action="login">
		登入名:<input type="text" name="username" /> <input type="submit"
			value="登入" />
	</form>
</body>
</html>

聊天介面:websocket.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"  
         pageEncoding="utf-8" %>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
    <title>Java API for WebSocket (JSR-356)</title>  
</head>  
<body>  
<script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>  
<script type="text/javascript" src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js"></script>  
<script type="text/javascript">  
    var websocket = null;  
    if ('WebSocket' in window) {  
        //Websocket的連線  
        websocket = new WebSocket("ws://localhost:8080/Creator/websocket/socketServer");//WebSocket對應的地址  
    }  
    else if ('MozWebSocket' in window) {  
        //Websocket的連線  
        websocket = new MozWebSocket("ws://localhost:8080/Creator/websocket/socketServer");//SockJS對應的地址  
    }  
    else {  
        //SockJS的連線  
        websocket = new SockJS("http://localhost:8080/Creator/sockjs/socketServer");    //SockJS對應的地址  
    }  
    websocket.onopen = onOpen;  
    websocket.onmessage = onMessage;  
    websocket.onerror = onError;  
    websocket.onclose = onClose;  
  
    function onOpen(openEvt) {  
        //alert(openEvt.Data);   
    }  
  
    function onMessage(evt) {  
        $("#content").append(evt.data+"<br>"); // 接收後臺傳送的資料
    }  
    function onError() {  
    }  
    function onClose() {  
    }  
  
    function doSend() {  
        if (websocket.readyState == websocket.OPEN) {  
            websocket.send($("#targetName").val()+"@"+$("#inputMsg").val());//呼叫後臺handleTextMessage方法  
            alert("傳送成功!");  
        } else {  
        
            alert("連線失敗!"+websocket.readyState);  
        }  
    }  
  
    window.close = function () {  
        websocket.onclose();  
    }  
</script>  
請輸入目標名稱:<input type="text" id = "targetName" />
請輸入:<textarea rows="3" cols="100" id="inputMsg" name="inputMsg"></textarea>  
<button onclick="doSend();">傳送</button>  
<div id="content"></div>
</body>  
</html>  

最後看成果:

首先隨便傳送訊息,檢視會有什麼反應:


最後是雙方互相傳送訊息:


好了 大功告成!!

相關推薦

ssmspring websocket 實現伺服器訊息 以及 一對一聊天

上網看了很多方式,最後覺得這種方式比較簡單易懂,這邊主要有三個類(包括註解的配置檔案)就可以實現後臺內容文末會展示結果例項,如果是你所需要的效果,直接拿去用吧~專案中複製直接用本文根據網上整理並修改!!!本文思路來自:連結現在開始。開始前請確保pom已經引入需要的包首先是配置

spring boot 整合websocket實現實時

websocket暫時能想到的應用是瀏覽器聊天和後臺日誌實時顯示到前臺。 當後臺啟動程式後,等待前臺連線,連線上之後,前後臺就可以相互發送資料了。 先貼上pom配置: <dependency> <groupId&g

Java WebSocket程式設計(二):WebSocket實現主動互動

WebSocket協議 WebSocket協議通訊機制 WebSocket協議是獨立的、基於TCP的協議。其本質是先通過HTTP/HTTPS協議進行握手後建立一個用於交換資料的TCP連線,此後伺服器端與客戶器端通過此TCP連線進行實時通訊。 WebSocket開啟握手

websocket 後端訊息實現

引入jar包 <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-websocket</artifactId>

WebSocket實現實時資料到前端

@Component @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer{ @Resource goodsWebSocketHandler handler;

Spring+Websocket實現伺服器與Andoird端通訊

本部落格伺服器端內容參考於部落格:http://www.cnblogs.com/3dianpomian/p/5902084.html。 寫這篇部落格的原因是在網上查閱了很多資料,關於websocket的介紹和程式碼很多,但是很少有統一給出伺服器端和Andori

使用MQTT協議的訂閱釋出模式,實現伺服器訊息到客戶端功能。

3、手機端設定相同的連線主題引數,訂閱訊息。關鍵程式碼:PC端//伺服器埠 賬號 密碼 private String host = "tcp://127.0.0.1:61613"; private String userName = "admin"; private Stri

HTML5伺服器訊息之Server-Sent Events

一、Server-Sent 事件定義: Server-Sent 事件指的是網頁自動從伺服器獲得更新。 以前也可能做到這一點,前提是網頁不得不詢問是否有可用的更新。通過 Server-Sent 事件,更新能夠自動到達。 二、例子: 1.Html: @{ ViewBa

HTML5伺服器訊息的各種解決辦法

AJAX 正常的一個頁面在瀏覽器中是這樣工作的: 使用者向給予瀏覽器一個需要訪問的地址瀏覽器根據這個地址訪問伺服器,並與伺服器之間建立一個TCP連線(HTTP請求)伺服器根據這個地址和一些其它資料,組建一段HTML文字,將寫入TCP連線,然後關閉連線瀏覽器得到了來自伺服

.NET基於comet伺服器技術(web實時聊天)

Comet 也稱反向 Ajax 或伺服器端推技術.其思想很簡單:將資料直接從伺服器推到瀏覽器,而不必等到瀏覽器請求資料。 主要思想:伺服器端將資料推送到客戶端(瀏覽器) 系統簡單說明如下: { 系統所用資料庫:sqlite資料庫   UserInfo:使用者資訊表

java伺服器訊息技術

其實有很多種方式實現伺服器推送,它們各有各的優缺點: 1.傳統輪詢:此方法是利用 HTML 裡面 meta 標籤的重新整理功能,在一定時間間隔後進行頁面的轉載,以此迴圈往復。它的最大缺點就是頁面刷性給人帶來的體驗很差,而且伺服器的壓力也會比較大。 2.Ajax 輪詢:非同步響應機制,即通過不間斷的客戶端 A

spring boot使用websocket實現點對點通訊與伺服器

WebSocket介紹    websocket是html中一種新的協議,它實現了真正的長連線,實現了瀏覽器與伺服器的全雙工通訊(指在通訊的任意時刻,線路上存在A到B和B到A的雙向訊號傳輸)。 現在我們接觸的協議大多是htttp協議,在瀏覽器中通過http協議實現了單向的通訊

Java Spring WebSocket實現後端訊息主動

這篇文章將介紹如何構建一個簡單的WebSocket訊息推送Demo使用eclipse建立maven專案後引入相關的依賴jar包,如下:<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://m

Spring+Websocket實現訊息

本文主要有三個步驟 1、使用者登入後建立websocket連線,預設選擇websocket連線,如果瀏覽器不支援,則使用sockjs進行模擬連線 2、建立連線後,服務端返回該使用者的未讀訊息 3、服務端進行相關操作後,推送給某一個使用者或者所有使用者新訊息 相關

spring boot +websocket 伺服器主動訊息

WebSocket協議是基於TCP的一種新的網路協議。它實現了瀏覽器與伺服器全雙工(full-duplex)通訊——允許伺服器主動傳送資訊給客戶端這裡我將使用springboot2.0 整合的websocket 實現簡單的伺服器推送訊息1.gradle新增依賴compile(

WebSocket】---實現定時比特幣交易信息

per 有一個 clas ins stack 編號 known onu dhx 實現定時推送比特幣交易信息 實現功能:跟虛擬幣交易所一樣,時時更新當前比特幣的價格,最高價,最低價,買一價等等...... 提示:(1)本篇博客是在上一遍基礎上搭建,上一篇博客地址:【

通過spring提供的DeferredResult實現長輪詢服務端訊息

DeferredResult字面意思就是推遲結果,是在servlet3.0以後引入了非同步請求之後,spring封裝了一下提供了相應的支援,也是一個很老的特性了。DeferredResult可以允許容器執行緒快速釋放以便可以接受更多的請求提升吞吐量,讓真正的業務邏輯在

JavaEE開發之SpringMVC的靜態資源對映及伺服器技術

在上篇部落格中,我們聊了《》。本篇部落格我們繼續的來聊SpringMVC的東西,下方我們將會聊到js、css這些靜態檔案的載入配置,以及伺服器推送的兩種實現方式。當然我們在伺服器推送時,會用到JQuery的東西,所以我們先聊一下如何載入靜態資原始檔,然後我們再聊如何實現伺服器推送。 下方給出了兩種實現伺服器推

HTML5伺服器’技術 -Server-Sent Events

一直以來,HTTP協議都是嚴格遵循Request-Response模型的。客戶端傳送一個Request到伺服器,伺服器對Request作出響應並將Response傳送回客戶端。也就是說,所有的互動都是由客戶端發起的,伺服器不會發起任何互動。為了建立互動性更強的web應用程

如何實現android和伺服器長連線呢?訊息的原理

GGSN(Gateway GPRS Support Node 閘道器GPRS支援結點)模組就實現了NAT功能。因為大部分移動無線網路運營商都是為了減少閘道器的NAT對映表的負荷,所以如果發現鏈路中有一段時間沒有資料通訊時,會刪除其對應表,造成鏈路中斷。(關於NAT的作用及其原理可以檢視我的另一篇博文:關於使用