javascript
Spring4.3+Webscket 实现聊天、消息推送详解之具体实现(三)
2019獨角獸企業重金招聘Python工程師標準>>>
前面可能廢話太多了,下面進入正題,講解spring具體的實現方式。
先來說一下幾個核心的步驟吧: 1.構建websocket服務端業務處理程序 2.構建websocket服務端自身配置程序 3.注冊websocket服務端、配置、攔截過濾器等 3.客戶端發送握手請求并建立連接``` 這里輸入代碼
4.客戶端發送消息給服務端 5.服務端處理客戶端發送來的消息 6.服務端發送消息給客戶端(指定或者群發) 7.客戶端展現。所需jar包如圖: https://static.oschina.net/uploads/img/201609/12105945_t83F.png?第一步:構建websocket spring實現方式中,有一個核心的接口WebSocketHandler,此接口中定義了websokcet服務端核心的幾個方法,如用戶成功連接服務端方法afterConnectionEstablished、處理客戶端發送消息的方法handleTextMessage等等。查看源碼發現其有一個重要的實現類:.AbstractWebSocketHandler該類是一個抽象類,其有兩個實現類分別為:BinaryWebSocketHandler, TextWebSocketHandler。BinaryWebSocketHandler此類中定義了特殊的方法handleBinaryMessage(WebSocketSession session, BinaryMessage message),看其源碼中,BinaryMessage 構造函數里面,可以傳入一個字節形的數組,通過集成該類可用次方法用于附件上傳等功能。一般信息傳遞,可通過繼承TextWebSocketHandler類來實現。下面先貼出代碼:websockethandler處理程序。package cn.com.mt.websocket;
import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject;
import cn.com.mt.model.Common_Constant; import cn.com.mt.model.UserInfo; /**
- 該類為websocket服務端處理程序,你可以把他廣義上理解為這就是websocket的服務端處理程序
- @author 寒冰
- QQ群號: 67746867
*/ public class ContextWebSocketHandler extends TextWebSocketHandler{
/** 用于存放在線用戶集合,key用用戶的id,真實生產環境中,未避免大數據出現的性能、內存、速度等一系列問題,采取內存數據庫如redis存儲*/ private static final Map<String,WebSocketSession> users; static {users = new HashMap<String,WebSocketSession>(); }/*** 當客戶端有消息發送過來時,會進入此方法進行處理* session:消息來源者* message:封裝了發送過來的消息信息* 說明:再此處說明一下,消息格式最好如下:{to:消息接收者ID/Username唯一標識/服務端標識...,content:消息內容},方便業務操作*/ @Override protected void handleTextMessage(WebSocketSession session,TextMessage message) throws Exception {super.handleTextMessage(session, message);//如果想取得原始session中封存的用戶身份等信息,可通過:session.getAttributes().get(名稱)方法取得 UserInfo user = (UserInfo)session.getAttributes().get(Common_Constant.USER_INFO);//通過message.getPayload()方法獲取客戶端發送過來的有效信息String content = message.getPayload();JSONObject obj = JSON.parseObject(content);//取得標識令牌String token = obj.getString("to");if("server".equals(token)){//發送過來的信息為服務器接收的系統信息,則處理相關系統級業務邏輯,此處只做原樣信息返回TextMessage returnMessage = new TextMessage("{'token':'socket_info','fromUser':'server','content':'信息已經收到,內容為:"+obj.getString("content")+"'}");session.sendMessage(returnMessage);}else if("all".equals(token)){//發送過來的信息為廣播信息,則調用全部在線人員接收信息方法TextMessage returnMessage = new TextMessage("{'token':'broadcast','fromUser':'"+user.getUsername()+"','content':'"+obj.getString("content")+"'}");sendMessageToUsers(returnMessage);}else{//發給個人接收TextMessage returnMessage = new TextMessage("{'token':'info','fromUser':'"+user.getUsername()+"','toUser':'"+obj.getString("toUser")+"','content':'"+obj.getString("content")+"'}");sendMessageToUser(obj.getString("to"),returnMessage);}}/*** 用戶成功連接成功后會調用該方法* 說明:次方法中,我們在實際生產環境中可能用到的場景如:* 1.用戶上線之后,接收自身的離線消息。* 2.刷新全局在線用戶列表*/ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception {UserInfo user = (UserInfo)session.getAttributes().get(Common_Constant.USER_INFO);if(null != user){users.put(user.getUsername(), session);//放入在線用戶集合中}//發送給當前登錄用戶在線用戶列表信息sendMessageToUsers(new TextMessage("{'token':'refreshlines','list':"+getlineUsers()+"}"));}/*** 給某個用戶發送消息** @param userName* @param message*/ public void sendMessageToUser(String username, TextMessage message) {WebSocketSession user = users.get(username);/** 判定接收信息的一方是否存在并且在線狀態,如果在線就發送* 說明:在這個地方,真實的應用里面,處理邏輯應該是先在當前在線用戶列表里面,先取指定的用戶是否在線,如果不在線,則再去數據庫中查找該用戶是否存在,如果存在,則該消息* 將加入離線消息存儲邏輯處理,待該用戶上線時,服務器推送離線消息給該用戶。*/if(null != user && user.isOpen()){try {user.sendMessage(message);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}/*** 給所有在線用戶發送消息** @param message*/ public void sendMessageToUsers(TextMessage message) {for (Map.Entry<String,WebSocketSession> entry : users.entrySet()) { try {if (entry.getValue().isOpen()) {entry.getValue().sendMessage(message);}} catch (IOException e) {e.printStackTrace();}} }/*** 返回在線用戶列表,json字符串格式* @return*/ public String getlineUsers(){return JSON.toJSONString(users.keySet()); }@Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {if(session.isOpen()){session.close();}System.out.println("傳輸處理錯誤......");users.remove(session); }@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {System.out.println("websocket connection closed......");users.remove(session); }@Override public boolean supportsPartialMessages() {return false; }}
握手攔截器通過繼承HttpSessionHandshakeInterceptor實現,如下代碼:package cn.com.mt.websocket;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest; ? import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.socket.WebSocketHandler; ? import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import cn.com.mt.model.Common_Constant; import cn.com.mt.model.UserInfo; ? /** ?* HandShakeInterceptor是websocket握手攔截器,用于攔截websocket初始化連接的請求? ?* @author 寒冰 ?* QQ群號: 67746867 ?* ?*/ public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{ ?
?? ?/** ?? ? * 握手之前調用該方法 ?? ? */ ?? ?@Override ?? ?public boolean beforeHandshake(ServerHttpRequest request, ?? ??? ??? ?ServerHttpResponse response, WebSocketHandler wsHandler, ?? ??? ??? ?Map<String, Object> attributes) throws Exception { ?? ??? ?System.out.println("握手開始"); ?? ??? ?if (request instanceof ServletServerHttpRequest) { ? ? ? ? ? ? ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; ? ? ? ? ? ? HttpSession session = servletRequest.getServletRequest().getSession(false); ? ? ? ? ? ? if (session != null) { ? ? ? ? ? ? ? ? //握手之初,封裝一下當前用戶的信息,為的是在后面的消息處理邏輯中,取出session中封裝的用戶信息 ? ? ? ? ? ? ? ? UserInfo user = (UserInfo) session.getAttribute(Common_Constant.USER_INFO); ? ? ? ? ? ? ? ? if (user==null) { ? ? ? ? ? ? ? ? ?? ? attributes.put(Common_Constant.USER_INFO,null); ? ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ?? ?attributes.put(Common_Constant.USER_INFO,user); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return super.beforeHandshake(request, response, wsHandler, attributes); ?? ?}
?? ?@Override ?? ?public void afterHandshake(ServerHttpRequest request, ?? ??? ??? ?ServerHttpResponse response, WebSocketHandler wsHandler, ?? ??? ??? ?Exception ex) { ?? ??? ?System.out.println("握手完成"); ?? ??? ?super.afterHandshake(request, response, wsHandler, ex); ?? ?}
?? } ?
通過xml注冊websocket相關信息如下: spring-websocket.xml<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ? ? xmlns:websocket="http://www.springframework.org/schema/websocket" ? ? xmlns:context="http://www.springframework.org/schema/context" ? ? ?xmlns:mvc="http://www.springframework.org/schema/mvc" ? ? xsi:schemaLocation=" ? ? ? ? http://www.springframework.org/schema/beans ? ? ? ? http://www.springframework.org/schema/beans/spring-beans.xsd ? ? ? ? http://www.springframework.org/schema/websocket ? ? ? ? http://www.springframework.org/schema/websocket/spring-websocket.xsd ? ? ? ? http://www.springframework.org/schema/context ? ? ? ? http://www.springframework.org/schema/context/spring-context.xsd ? ? ? ? http://www.springframework.org/schema/mvc? ? ? ? ? http://www.springframework.org/schema/mvc/spring-mvc.xsd"> ? ? ? ?? ? ? <!-- 聲明服務端處理程序 --> ? ? <bean id="contextwebsocketHandler" class="cn.com.mt.websocket.ContextWebSocketHandler"/> ? ? ? ? ? ?<!-- 注冊服務端處理程序路徑及相關握手攔截器 --> ? ? ?websocket:handlers ? ? ? ? <websocket:mapping path="/chandler" handler="contextwebsocketHandler"/> ? ? ? ?websocket:handshake-interceptors ? ? ? ? ? ?<bean class="cn.com.mt.websocket.HandshakeInterceptor"></bean> ? ? ? ?</websocket:handshake-interceptors> ? ? </websocket:handlers> ? ?? ? ? <!-- 注冊服務端處理程序路徑及相關握手攔截器 ?開啟sockjs方式,開啟之后,前端必須用sockjs方式發起請求連接--> ? ? websocket:handlers ? ? ? ? <websocket:mapping path="/jhandler" handler="contextwebsocketHandler"/> ? ? ? ?websocket:handshake-interceptors ? ? ? ? ? ?<bean class="cn.com.mt.websocket.HandshakeInterceptor"></bean> ? ? ? ?</websocket:handshake-interceptors> ? ? ? ?websocket:sockjs/ ? ? </websocket:handlers>
?? ?<!-- 配置websocket消息的最大緩沖區長度 --> ?? ?<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean"> ?? ? ? ?<property name="maxTextMessageBufferSize" value="8192"/> ?? ? ? ?<property name="maxBinaryMessageBufferSize" value="8192"/> ?? ?</bean> ??
? ? </beans>
上述的代碼中,用到了兩個自己寫的類,一個是實體類UserInfo,一個是用于定義常量的類,如下: UserInfo:package cn.com.mt.model; /** ?* 用戶信息實體 ?*@author 寒冰 ?*QQ群號: 67746867 ?* ?*/ public class UserInfo {
?? ?private int id; ?? ? ?? ?private String username; ?? ?
?? ?public int getId() { ?? ??? ?return id; ?? ?}
?? ?public void setId(int id) { ?? ??? ?this.id = id; ?? ?}
?? ?public String getUsername() { ?? ??? ?return username; ?? ?}
?? ?public void setUsername(String username) { ?? ??? ?this.username = username; ?? ?}
?? ? ?? ? }
Common_Constant:package cn.com.mt.model; /** ?* 系統統一常量定義實體 ?* @author 寒冰 ?* QQ群號: 67746867 ?* ?*/ public class Common_Constant {
?? ?public static final String USER_INFO = "USER_INFO";//用戶身份信息 ?? ? ?? ? }
同時為了記錄登陸用戶信息,寫了一個action,LoginAction,代碼如下:package cn.com.mt.action;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;
import cn.com.mt.model.Common_Constant; import cn.com.mt.model.UserInfo;
/** ?* 登陸action ?*@author 寒冰 ?*QQ群號: 67746867 ?* ?*/ @Controller public class LoginAction {
?? ?/** ?? ? * 登陸驗證 ?? ? * 說明:此處僅為闡明websocket在線用戶業務,不做用戶身份信息認證聲明。 ?? ? * 特別說明:如做集群部署,如需解決session同步問題,需做session共享。 ?? ? * @param userinfo ?? ? * @param request ?? ? * @return ?? ? */ ?? ?@RequestMapping("/login.action") ?? ?public String login(UserInfo userinfo,String index,HttpServletRequest request){ ?? ??? ?request.getSession().setAttribute(Common_Constant.USER_INFO, userinfo); ?? ??? ? ?? ??? ?return "0".equals(index)?"index0":"index1"; ?? ?} }
為了能夠websocketSession與httpsession能掛上關聯,需額外添加請求攔截器RequestListener,讓每一次的請求都帶著session信息,如下實現:package cn.com.mt.listener;
import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.http.HttpServletRequest; /** ?* 用戶請求/響應監聽器 ?*? ?* 此監聽器的主要作用是讓用戶每次向websocket發出的請求,都帶上session信息 ?* @author 寒冰 ?* QQ群號: 67746867 ?* ?*/ public class RequestListener implements ServletRequestListener {
?? ?@Override ?? ?public void requestInitialized(ServletRequestEvent request) { ?? ??? ?// TODO Auto-generated method stub ?? ??? ? ((HttpServletRequest) request.getServletRequest()).getSession(); ?? ?} ?? ? ?? ?@Override ?? ?public void requestDestroyed(ServletRequestEvent arg0) { ?? ??? ?// TODO Auto-generated method stub ?? ??? ? ?? ?}
}
最后貼出web.xml 配置文件:<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> ?? ?? ?? ?? ? <display-name>yao_yan</display-name> ? <servlet> ?? ??? ?<servlet-name>spring</servlet-name> ?? ??? ?<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> ?? ??? ?<init-param> ?? ??? ??? ?<param-name>contextConfigLocation</param-name> ?? ??? ??? ?<param-value>classpath*:spring-*.xml</param-value> ?? ??? ?</init-param> ? ? ? ? <load-on-startup>1</load-on-startup> ? ? ? ? <async-supported>true</async-supported> ?? ?</servlet>
?? ?<!-- websocket URL標識 --> ?? ?<servlet-mapping> ?? ??? ?<servlet-name>spring</servlet-name> ?? ??? ?<url-pattern>/socket/</url-pattern> ?? ?</servlet-mapping> ?? ? ?? ?<!-- action URL標識 --> ?? ?<servlet-mapping> ?? ??? ?<servlet-name>spring</servlet-name> ?? ??? ?<url-pattern>.action</url-pattern> ?? ?</servlet-mapping> ?? ? ?? ? ?? ? ?? ?<!-- 注冊請求監聽器 --> ?? ?<listener> ? ?? ? ? <listener-class>cn.com.mt.listener.RequestListener</listener-class> ?? ?</listener> </web-app>
前端登陸login.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>Insert title here</title> <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script> <script> ?$(function(){ ?? ?? ?? ? $("#login").click(function(){ ?? ??? ? var username = $.trim($("#username").val()); ?? ??? ? if(""==username){ ?? ??? ??? ? alert("enter username please....."); ?? ??? ??? ? return ; ?? ??? ? }else{ ?? ??? ??? ? f1.submit(); ?? ??? ? } ?? ? }); ?}); </script> </head> <body> <form action="login.action" method="post" name="f1"> username:<input type="text" name="username" id="username"> <input type="radio" name="index" value="0" checked="checked">普通方式 <input type="radio" name="index" value="1">sockjs方式 <input type="button" id="login" value="login"> </form>
</body> </html> ```
普通方式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>Insert title here</title> <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script><script>var socket_url = "ws://192.168.1.107:8888/yao_yan/socket/chandler";var ?websocket ;$(function(){//連接websocket服務器$("#connect").click(function(){websocket = new WebSocket(socket_url);?websocket.onopen = function (evt) { onOpen(evt) };?websocket.onclose = function (evt) { onClose(evt) };?websocket.onmessage = function (evt) { onMessage(evt) };?websocket.onerror = function (evt) { onError(evt) };?});//注冊發送消息按鈕事件$("#send").click(function(){var who = $("input[name='who']:checked").val();//獲取消息接收方類別var content = $.trim($("#content").val());//獲取消息內容var msg = "{";if(""==content){alert("輸入消息內容!");return;}if("server"==who){msg+="'to':'server',";$("#msg").after("<p>你對服務器說:"+content+"</p>");}else if("all"==who){msg+="'to':'all',";$("#msg").after("<p>你對大家說:"+content+"</p>");}else if("one"==who){var to_user = $.trim($("#userlist").val());if(""==to_user){alert("選擇接收消息方!");return ;}msg+="'to':'"+to_user+"',";$("#msg").after("<p>你對"+to_user+"說:"+content+"</p>");}msg += "'content':'"+content+"'}";sendd(msg);});});//連接成功websocket服務器時執行function onOpen(evt) {?$("#msg").text("<p>成功連接到websocket服務器</p>");$("#send").removeAttr("disabled");//發送信息按鈕可用$("#connect").attr("disabled","disabled");//連接服務器按鈕不可用}?//連接關閉時執行function onClose(evt) {?console.log("連接關閉。。。。");?}?//服務器有推送消息過來時執行function onMessage(evt) {var obj = eval('(' + evt.data + ')');if(obj.token=="refreshlines"){//判定token為刷新在線用戶列表refresh_line_users(obj.list);}else if(obj.token=="broadcast"){//廣播消息$("#msg").after("<p>"+obj.fromUser+" 對大家說:"+obj.content+"</p>");}else if(obj.token=="info"){//私信$("#msg").after("<p>"+obj.fromUser+" 對你說:"+obj.content+"</p>");}else if(obj.token=="socket_info"){//系統提醒消息$("#msg").after("<p>"+obj.fromUser+" 響應消息:"+obj.content+"</p>");}}?//有錯誤信息時執行function onError(evt) {?console.log('Error occured: ' + evt.data);?}//向服務器發送消息,此方式實際生產中考慮消息加密傳遞function sendd(msg){websocket.send(msg);}//刷新在線用戶列表function refresh_line_users(data){$("#userlist").empty();for(var i=0;i<data.length;i++){$("#userlist").append("<option value='"+$.trim(data[i])+"'>"+$.trim(data[i])+"</option>");}$("#userlist").append("<option value='all'>全部</option>");} </script> </head> <body> <h1>普通請求方式</h1>響應提示區域:<div id="msg" style="color:red"></div><hr><br>消息內容:<input type="text" id="content" name="content"><br><br>在線列表:<select id="userlist"></select><br><br>我要發消息給:<input type="radio" id="server" name="who" value="server" checked="checked">服務器識別消息<input type="radio" id="one" name="who" value="one">個人<input type="radio" id="all" name="who" value="all">廣播<br><br><input type="button" id="connect" value="連接websocket服務器"><input type="button" id="send" value="發送" disabled="disabled"></body> </html>sockjs方式:
<%@ 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>Insert title here</title> <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script> <script src="js/sockjs-1.1.1.min.js"></script> ? <script>var socket_url = "http://192.168.1.107:8888/yao_yan/socket/jhandler";var ?sock ;$(function(){//連接websocket服務器$("#connect").click(function(){sock = new SockJS(socket_url);sock.onopen = function (evt) { onOpen(evt) };?sock.onclose = function (evt) { onClose(evt) };?sock.onmessage = function (evt) { onMessage(evt) };?sock.onerror = function (evt) { onError(evt) };?});//注冊發送消息按鈕事件$("#send").click(function(){var who = $("input[name='who']:checked").val();//獲取消息接收方類別var content = $.trim($("#content").val());//獲取消息內容var msg = "{";if(""==content){alert("輸入消息內容!");return;}if("server"==who){msg+="'to':'server',";$("#msg").after("<p>你對服務器說:"+content+"</p>");}else if("all"==who){msg+="'to':'all',";$("#msg").after("<p>你對大家說:"+content+"</p>");}else if("one"==who){var to_user = $.trim($("#userlist").val());if(""==to_user){alert("選擇接收消息方!");return ;}msg+="'to':'"+to_user+"',";$("#msg").after("<p>你對"+to_user+"說:"+content+"</p>");}msg += "'content':'"+content+"'}";sendd(msg);});});//連接成功websocket服務器時執行function onOpen(evt) {?$("#msg").after("<font color='red'>系統提示:</font><p>你已經成功連接到websocket服務器!!!現在可以聊天了</p>");$("#send").removeAttr("disabled");//發送信息按鈕可用$("#connect").attr("disabled","disabled");//連接服務器按鈕不可用}?//連接關閉時執行function onClose(evt) {?console.log("連接關閉。。。。");?}?//服務器有推送消息過來時執行function onMessage(evt) {var obj = eval('(' + evt.data + ')');if(obj.token=="refreshlines"){//判定token為刷新在線用戶列表refresh_line_users(obj.list);}else if(obj.token=="broadcast"){//廣播消息$("#msg").after("<p>"+obj.fromUser+" 對大家說:"+obj.content+"</p>");}else if(obj.token=="info"){//私信$("#msg").after("<p>"+obj.fromUser+" 對你說:"+obj.content+"</p>");}else if(obj.token=="socket_info"){//系統提醒消息$("#msg").after("<p>"+obj.fromUser+" 響應消息:"+obj.content+"</p>");}}?//有錯誤信息時執行function onError(evt) {?console.log('Error occured: ' + evt.data);?}//向服務器發送消息,此方式實際生產中考慮消息加密傳遞function sendd(msg){sock.send(msg);}//刷新在線用戶列表function refresh_line_users(data){$("#userlist").empty();for(var i=0;i<data.length;i++){$("#userlist").append("<option value='"+$.trim(data[i])+"'>"+$.trim(data[i])+"</option>");}$("#userlist").append("<option value='all'>全部</option>");} </script> </head> <body> <h1>sockjs請求方式</h1>響應提示區域:<div id="msg" style="color:red"></div><hr><br>消息內容:<input type="text" id="content" name="content"><br><br>在線列表:<select id="userlist"></select><br><br>我要發消息給:<input type="radio" id="server" name="who" value="server" checked="checked">服務器識別消息<input type="radio" id="one" name="who" value="one">個人<input type="radio" id="all" name="who" value="all">廣播<br><br><input type="button" id="connect" value="連接websocket服務器"><input type="button" id="send" value="發送" disabled="disabled"></body> </html>下面的章節,會詳細介紹上述代碼。
轉載于:https://my.oschina.net/tianshibuzuoai/blog/745675
總結
以上是生活随笔為你收集整理的Spring4.3+Webscket 实现聊天、消息推送详解之具体实现(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nginx与Serssion一致性问题
- 下一篇: 组策略 之 恢复默认组策