當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring项目中使用webservice实现h5的websocket通信
生活随笔
收集整理的這篇文章主要介紹了
Spring项目中使用webservice实现h5的websocket通信
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、在項(xiàng)目中建立一個(gè)webservice來做后臺(tái)操作。
package org.calonlan.soulpower.websocket;import java.text.SimpleDateFormat; import java.util.Date;import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint;/*** 這里使用注釋的方式來向系統(tǒng)指明,我的這個(gè)WebSocketTest是一個(gè)webservice。 同時(shí)指定了路徑為/websocket/{uCode}* 其中的{uCode}是一個(gè)變化的參數(shù),在網(wǎng)頁端動(dòng)態(tài)的輸入。這樣我就可以通過@PathParam("uCode")這個(gè)注釋在參數(shù)中獲得用戶的信息等等了。* * */ @ServerEndpoint("/websocket/{uCode}") public class WebSocketTest {/*** @param message* 這里是客戶端傳來的消息,我這里只是簡(jiǎn)單的測(cè)試文本消息,消息的種類可以有很多種。* @param uCode* 這就是{uCode}中傳來的路徑參數(shù),可以用來傳遞用戶的信息。例如帳號(hào)。* @throws Exception* 偷懶的人總是拋出一個(gè)EXCEPTION*/@OnMessage// 當(dāng)有消息傳來的時(shí)候進(jìn)行處理的方法public void onMessage(String message, @PathParam("uCode") String uCode)throws Exception {System.out.println("revived:" + message);// 輸出一下接收到的消息String tem[] = message.split("##to##");// 消息的格式是// tousername##to##message,分隔以后第一個(gè)就是要發(fā)送的用戶名,第二個(gè)就是消息了if (SessionUtils.hasConnection(tem[0])) {// 從sessionUtils中判斷一下是否要發(fā)送的用戶名是否已經(jīng)登錄,登錄的話做以下操作/* 弄個(gè)時(shí)間開始 */SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String x = sdf.format(new Date());/* 弄個(gè)時(shí)間結(jié)束 *//** 消息的發(fā)送,可以選擇AsyncRemote也可以選擇* BasicRemote,區(qū)別在于AsyncRemote是不會(huì)阻塞的,系統(tǒng)不會(huì)去管消息是否發(fā)送完成直接占用通道去發(fā)* 。使用它的話要用戶自己去實(shí)現(xiàn)控制,所以我選擇BasicRemote,*/SessionUtils.get(tem[0]).getBasicRemote().sendText(uCode + "##to##" + x + ":" + tem[1]);} else {// 沒有登錄的話做以下操作SessionUtils.get(uCode).getBasicRemote().sendText("用戶不在線");}}/*** @param uCode* 同上* @param session* 這個(gè)是用戶建立的session信息,用來唯一標(biāo)識(shí)這個(gè)用戶的通信* @throws Exception* 你懂得*/@OnOpen// 用戶建立鏈接的時(shí)候執(zhí)行的方法public void onOpen(@PathParam("uCode") String uCode, Session session)throws Exception {if (SessionUtils.hasConnection(uCode)) {// 判斷緩存中是否有uCode,如果有執(zhí)行括號(hào)內(nèi)的方法SessionUtils.get(uCode).close();// 因?yàn)橐呀?jīng)登錄了,那么將已經(jīng)登錄的下線SessionUtils.remove(uCode);// 移除掉緩存中的<uCode,Session>SessionUtils.put(uCode, session);// 添加新的<uCode,Session>System.out.println(uCode + "has join server");} else {System.out.println(uCode + "has join server");/* 如果沒有緩存相關(guān)的<uCode,Session>,那么直接添加 */SessionUtils.put(uCode, session);}}@OnClose//客戶端斷開鏈接時(shí)執(zhí)行的方法public void onClose(@PathParam("uCode") String uCode) {System.out.println(uCode + "has left server");SessionUtils.remove(uCode);//直接移除就好了,session已經(jīng)關(guān)閉了System.out.println("left deal was finished");}@OnError//客戶端出錯(cuò)誤的時(shí)候執(zhí)行的方法public void onError(Throwable e, Session session) {if (SessionUtils.clients.containsValue(session)) {//移除出錯(cuò)的sessionSessionUtils.remove(session);}}}二、實(shí)現(xiàn)用來管理session的uti類。 package org.calonlan.soulpower.websocket;import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;import javax.websocket.Session;public class SessionUtils {/*<uCode,Session>的緩存*/public static Map<String, Session> clients = new ConcurrentHashMap<String, Session>();public static void put(String uCode, Session session) {//添加clients.put(uCode, session);}public static Session get(String uCode) {//根據(jù)uCode來獲取return clients.get(uCode);}public static void remove(String uCode) {//根據(jù)uCode來移除clients.remove(uCode);}public static void remove(Session session) {//根據(jù)session來移除Iterator<java.util.Map.Entry<String, Session>> ito = clients.entrySet().iterator();while (ito.hasNext()) {java.util.Map.Entry<String, Session> entry = ito.next();if (entry.getKey().equals(session))remove(entry.getKey());}}public static boolean hasConnection(String uCode) {//根據(jù)uCode來判斷是否包含對(duì)應(yīng)用戶名的<uCode,Session>return clients.containsKey(uCode);} }
三、html頁面實(shí)現(xiàn) <%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <title>WebSoket Demo</title> <script type="text/JavaScript"> //驗(yàn)證瀏覽器是否支持WebSocket協(xié)議if (!window.WebSocket) { alert("WebSocket not supported by this browser!"); } var ws;function display() { //創(chuàng)建webSocket,后面的${id}與{uCode}相對(duì)應(yīng)ws=new WebSocket("ws://localhost:8080/newback/websocket/${id}"); //監(jiān)聽消息ws.onmessage = function(event) { log(event.data);}; //綁定關(guān)閉事件 ws.onclose = function(event) {/*這段代碼的作用是,如果同一個(gè)id在其他的頁面登錄,那么就強(qiáng)制當(dāng)前的頁面下線,關(guān)閉。在服務(wù)器端我們?cè)谕粋€(gè)id登錄時(shí)關(guān)閉了以前的socket,所以這里在關(guān)閉事件中進(jìn)行操作*/var opened=window.open('about:blank','_self'); opened.opener=null; opened.close();}; //建立websocket的事件,可以用來做一些初始化操作;比如如果用戶不在線其他人發(fā)送了消息我可以放在數(shù)據(jù)庫(kù)里,用戶一上線就調(diào)用查詢方法ws.onopen = function(event) { }; //出現(xiàn)錯(cuò)誤的時(shí)候的方法ws.onerror =function(event){};} var log = function(s) {//打印消息的方法if (document.readyState !== "complete") { log.buffer.push(s); } else { document.getElementById("contentId").innerHTML += (s + "\n"); } }function sendMsg(){//這里是發(fā)送消息,我制做了c1、c2之間的通話var msg=document.getElementById("messageId");var client='${id}';if(client=='c1')ws.send("c2##to##"+msg.value);//發(fā)送消息elsews.send("c1##to##"+msg.value);}</script> </head> <body οnlοad="display();"> <div id="valueLabel"></div> <textarea rows="20" cols="30" id="contentId"></textarea><br/><input name="message" id="messageId"/><button id="sendButton" onClick="javascript:sendMsg()" >Send</button></body> </html>
四、測(cè)試。
1.登錄c1
服務(wù)器端顯示
2.登錄c2
服務(wù)器端顯示
登錄完成,就可以互相發(fā)送消息了。
c1發(fā)送給c2
c2發(fā)送給c1同樣的道理。
這里還看到了很多不是發(fā)送的消息,這是我在后臺(tái)設(shè)置的定時(shí)任務(wù)。服務(wù)器可以定時(shí)的給客戶端發(fā)送一些消息。
五、定時(shí)任務(wù)
這里我遍歷sessionutils中的map,給所有用戶都發(fā)送
package org.calonlan.soulpower.timertask;import java.util.Iterator; import java.util.Map; import java.util.Map.Entry;import javax.websocket.Session;import org.calonlan.soulpower.util.ComputerUtil; import org.calonlan.soulpower.websocket.SessionUtils; import org.hyperic.sigar.SigarException;public class TimerTask {public void printTimeStamp() throws SigarException {Map<String, Session> map = SessionUtils.clients;Iterator<Entry<String, Session>> ito = map.entrySet().iterator();while (ito.hasNext()) {Entry<String, Session> entry = ito.next();try {if (entry.getValue().isOpen()) {entry.getValue().getBasicRemote().sendText(ComputerUtil.getMemory());entry.getValue().getBasicRemote().sendText(ComputerUtil.getCPU());entry.getValue().getBasicRemote().sendText(ComputerUtil.getDisk());} else {map.remove(entry.getKey());}} catch (Exception e) {System.out.println("錯(cuò)誤");e.printStackTrace();map.remove(entry.getKey());}}}public TimerTask() {}public void doTask() throws SigarException {this.printTimeStamp();}}總結(jié)
以上是生活随笔為你收集整理的Spring项目中使用webservice实现h5的websocket通信的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蓝桥杯第六届国赛JAVA真题----切开
- 下一篇: As的哲学态度