當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
WebSocket + Spring消息推送服务的快速实现
生活随笔
收集整理的這篇文章主要介紹了
WebSocket + Spring消息推送服务的快速实现
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
一.? ? 依賴(這里只列舉了websocket相關(guān)依賴)
<!-- spring webSocket依賴 --><dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>${spring.version}</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-messaging --><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>${spring.version}</version></dependency><!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api --><dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version><scope>provided</scope></dependency><!-- websocket客戶端 --><dependency><groupId>org.glassfish.tyrus.bundles</groupId><artifactId>tyrus-standalone-client</artifactId><version>1.13</version></dependency>二.? ? WebSocket服務(wù)端
????????2-1. 核心代碼
package com.github.websocket.server;import com.alibaba.fastjson.JSON; import com.github.CommonConstant; import com.github.session.SObject; import com.github.websocket.configuration.HttpSessionConfigurator; import com.github.websocket.msg.Msg; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger;import javax.servlet.http.HttpSession; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap;/*** @author : Crab2Died</br>* @DESC : <p>注解{@link ServerEndpoint}聲明websocket 服務(wù)端</p></br>* @date : 2017/5/25 9:43</br>*/ @ServerEndpoint(value = "/chat", configurator = HttpSessionConfigurator.class) public class WSServer {static private Logger logger = Logger.getLogger(WSServer.class);// 在線人數(shù) 線程安全private static int onlineCount = 0;// 連接集合 userId => server 鍵值對 線程安全static public final ConcurrentMap<String, WSServer> map = new ConcurrentHashMap<>();// 與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)private Session session;// 當前會話的httpsessionprivate HttpSession httpSession;/*** @param session websocket連接sesson* @param config {@link com.github.websocket.configuration.HttpSessionConfigurator}* @DESC <p>注解{@link OnOpen} 聲明客戶端連接進入的方法</p>*/@OnOpenpublic void onOpen(Session session, EndpointConfig config) {// 得到httpSessionthis.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());// 獲取session對象 SObject(這個就是java web登入后的保存的session對象,此處為用戶信息,包含了userId)SObject user = (SObject) this.httpSession.getAttribute(CommonConstant.USER_LOGIN_SESSION);this.session = session;// 將連接session對象存入mapmap.put(user.getUid(), this);// 連接數(shù)+1addOnlineCount();logger.info("有新的連接,當前連接數(shù)為:" + getOnlineCount());}/*** <p>{@link OnClose} 關(guān)閉連接</p>*/@OnClosepublic void onClose() {/*** 獲取當前連接信息 {@code CommonConstant.USER_LOGIN_SESSION} 為Http session 名*/SObject user = (SObject) this.httpSession.getAttribute(CommonConstant.USER_LOGIN_SESSION);// 移除連接map.remove(user.getUid());// 連接數(shù)-1subOnlineCount();logger.info("有一連接斷開,當前連接數(shù)為:" + getOnlineCount());}/*** <p>{@link OnMessage} 消息監(jiān)聽處理方法</p>** @param message 消息對象{@link com.github.websocket.msg.Msg}的JSON對象* @throws IOException 異常*/@OnMessagepublic void onMessage(String message) throws IOException {// 將消息轉(zhuǎn)Msg對象Msg msg = JSON.parseObject(message, Msg.class);//TODO 可以對msg做些處理...// 根據(jù)Msg消息對象獲取定點發(fā)送人的userIdWSServer _client = map.get(msg.getToUid());// 定點發(fā)送if (StringUtils.isNotEmpty(msg.getToUid())) {if (null != _client) {// 是否連接判斷if (_client.session.isOpen())// 消息發(fā)送_client.session.getBasicRemote().sendText(JSON.toJSONString(msg));}}// 群發(fā)if (StringUtils.isEmpty(msg.getToUid())) {// 群發(fā)已連接用戶for (WSServer client : map.values()) {client.session.getBasicRemote().sendText(JSON.toJSONString(msg));}}}/*** <p>{@link OnError} websocket系統(tǒng)異常處理</p>** @param t 異常*/@OnErrorpublic void onError(Throwable t) {logger.error(t);t.printStackTrace();}/*** <p>系統(tǒng)主動推送 這是個靜態(tài)方法在web啟動后可在程序的其他合適的地方和時間調(diào)用,這就實現(xiàn)了系統(tǒng)的主動推送</p>** @param msg 消息對象{@link com.github.websocket.msg.Msg}的JSON對象*/staticpublic void pushBySys(Msg msg) {//TODO 也可以實現(xiàn)定點推送// 群發(fā)for (WSServer client : map.values()) {try {client.session.getBasicRemote().sendText(JSON.toJSONString(msg));} catch (IOException e) {e.printStackTrace();}}}// 獲取連接數(shù)private static synchronized int getOnlineCount() {return WSServer.onlineCount;}// 增加連接數(shù)private static synchronized void addOnlineCount() {WSServer.onlineCount++;}// 減少連接數(shù)private static synchronized void subOnlineCount() {WSServer.onlineCount--;}}????????2-2. HttpSessionConfigurator類
package com.github.websocket.configuration;import javax.servlet.http.HttpSession; import javax.websocket.HandshakeResponse; import javax.websocket.server.HandshakeRequest; import javax.websocket.server.ServerEndpointConfig; import javax.websocket.server.ServerEndpointConfig.Configurator;/*** @author : Crab2Died</br>* @DESC : <p>講http request的session 存入websocket的session內(nèi)</p></br>* @date : 2017/5/25 16:08</br>*/ public class HttpSessionConfigurator extends Configurator {@Overridepublic void modifyHandshake(ServerEndpointConfig sec,HandshakeRequest request, HandshakeResponse response) {// 獲取當前Http連接的sessionHttpSession httpSession = (HttpSession) request.getHttpSession();// 將http session信息注入websocket sessionsec.getUserProperties().put(HttpSession.class.getName(), httpSession);} }????????2-3. Msg消息體
package com.github.websocket.msg;import java.util.Date;/*** @author : Crab2Died</br>* @DESC : <p>WebSocket消息模型</p></br>* @date : 2017/5/25 9:43</br>*/ public class Msg {// 推送人IDprivate String fromUid;// 定點推送人IDprivate String toUid;// 定點推送單位IDprivate String toOrgId;// 消息體private String data;// 推送時間private Date createDate = new Date();// 消息狀態(tài)private Integer flag;public Msg() {}public Msg(String fromUid, String toUid, String toOrgId, String data, Date createDate, Integer flag) {this.fromUid = fromUid;this.toUid = toUid;this.toOrgId = toOrgId;this.data = data;this.createDate = createDate;this.flag = flag;}public String getFromUid() {return fromUid;}public void setFromUid(String fromUid) {this.fromUid = fromUid;}public String getToUid() {return toUid;}public void setToUid(String toUid) {this.toUid = toUid;}public String getToOrgId() {return toOrgId;}public void setToOrgId(String toOrgId) {this.toOrgId = toOrgId;}public String getData() {return data;}public void setData(String data) {this.data = data;}public Date getCreateDate() {return createDate;}public void setCreateDate(Date createDate) {this.createDate = createDate;}public Integer getFlag() {return flag;}public void setFlag(Integer flag) {this.flag = flag;}@Overridepublic String toString() {return "Msg{" +"fromUid='" + fromUid + '\'' +", toUid='" + toUid + '\'' +", toOrgId='" + toOrgId + '\'' +", data='" + data + '\'' +", createDate=" + createDate +", flag=" + flag +'}';} }三.? ? 客戶端(HTML5)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>WebSocket</title> <script type="text/javascript">// 創(chuàng)建websocket實例var ws = new WebSocket("ws://localhost:8080/chat");/**監(jiān)聽三種狀態(tài)的變化js會回調(diào)*/ws.onopen = function(message) {// 連接回調(diào)};ws.onclose = function(message) {// 斷開連接回調(diào)};ws.onmessage = function(message) {// 消息監(jiān)聽showMessage(message.data);};//監(jiān)聽窗口關(guān)閉事件,當窗口關(guān)閉時,主動去關(guān)閉websocket連接,防止連接還沒斷開就關(guān)閉窗口,server端會拋異常。window.onbeforeunload = function() {ws.close();};//關(guān)閉連接function closeWebSocket() {ws.close();}//發(fā)送消息function send() {var input = document.getElementById("msg");var text = input.value;// 消息體JSON 對象 對應(yīng)JAVA 的 Msg對象var data = {// 定點發(fā)送給其他用戶的userIdtoUid : "3d535429-5fcb-4490-bcf7-96fd84bb17b6",data : text}ws.send(JSON.stringify(data));input.value = "";}function showMessage(message) {var text = document.createTextNode(JSON.parse(message).data);var br = document.createElement("br")var div = document.getElementById("showChatMessage");div.appendChild(text);div.appendChild(br);} </script> </head> <body><div>style="width: 600px; height: 240px; overflow-y: auto; border: 1px solid #333;"id="show"><div id="showChatMessage"></div><input type="text" size="80" id="msg" name="msg" placeholder="輸入聊天內(nèi)容" /><input type="button" value="發(fā)送" id="sendBn" name="sendBn" onclick="send()"></div> </body> </html>?
轉(zhuǎn)載于:https://my.oschina.net/crab2died/blog/911032
總結(jié)
以上是生活随笔為你收集整理的WebSocket + Spring消息推送服务的快速实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OPPO新旗舰参数曝光:三星2K屏幕+三
- 下一篇: gradle idea java ssm