SSM+WebSocket實現一個簡易網頁版通訊工具
阿新 • • 發佈:2018-11-14
編譯環境:jdk1.8 , tomcat8.0+ , IDEA
這裡主要講一下websocket的資訊傳遞,以如何實現多人實時線上聊天為例:
websocket主要的三個類
MyWebSocketConfig主要負責配置websocket的處理器和握手攔截器
MyHandShakeInterceptor 是websocket的攔截器
MyWebSocketHander是websocket的處理器
@Component @EnableWebSocket public class MyWebSocketConfig implements WebSocketConfigurer { @Autowired private MyWebSocketHander myWebSocketHander; private static final String LINK_URI = "websocket.do"; //新增websocket處理器,新增握手攔截器 攔截器先執行 然後到處理器 @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { webSocketHandlerRegistry.addHandler(myWebSocketHander,LINK_URI).addInterceptors(new MyHandShakeInterceptor()); } }
/* private static Map<WebSocketSession,String> map = new HashMap<WebSocketSession, String>(); * websocket握手攔截器 * 攔截握手前,握手後的兩個切面 */ @Component public class MyHandShakeInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception { if(serverHttpRequest instanceof ServletServerHttpRequest){ HttpServletRequest servletRequest = ((ServletServerHttpRequest)serverHttpRequest).getServletRequest(); User user = (User)servletRequest.getSession().getAttribute("user"); //這裡給map賦值 相當於websockethandler的afterConnectionEstablished方法裡的WebSocketSession //key是session,value是變數 map.put("ws_user", user); } return true; } @Override public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { } }
實時通訊的具體流程:
前端
<% String path = request.getContextPath();%> <html> link rel="stylesheet" href="<%=path%>/static/css/bootstrap.min.css" type="text/css"> <script src="<%=path%>/static/js/jquery.min.js"></script> <script src="<%=path%>/static/js/bootstrap.min.js" type="text/javascript"></script> <body> <div id="container" style="width:500px"> <div id="header"> <h1 id="title">chat-room</h1></div> <div class="middle"> <div id="menu"> <p id="tou">歡迎來到聊天室</p> </div> <div class="chatter" id="chatter"> <p id="msg"></p> </div> </div> <div id="content"> <textarea class="form-control" rows="3" placeholder="我想說....." id="msgContent"> </textarea> </div> <div style="background-color: #F8F8F8;"> <div id="buttons"> <button id="butSent" type="button" class="btn btn-default" onclick="getConnection()">連線 </button> <button type="button" class="btn btn-default" onclick="sendMsgClose()">斷開 </button> <button type="button" class="btn btn-default" onclick="sendMsg()"> 傳送 </button> </div> </div> <div id="footer"> Designed by Annie </div> </div> </body> <script> //開啟連結 function getConnection() { if (websocket == null) { websocket = new WebSocket(wsServer); websocket.onopen = function (evnt) { alert("連結伺服器成功!"); }; //從後臺接受資料的函式 websocket.onmessage = function (evnt) { var onlineUser = $("#onlineUser"); //將收到的資料轉換成物件 var message = eval("(" + evnt.data + ")"); //顯示線上人數及線上使用者 if (message.msgTyp === "notice") { var htmlOnline; $("#onlineNum").text(message.onlineNum); htmlOnline = "<p> " + message.userName + " </p>"; //實時更新線上使用者 onlineUser.html(""); $(onlineUser).append(htmlOnline); } else if (message.msgTyp === "msg") { showChat(evnt); } }; websocket.onerror = function (evnt) { alert("發生錯誤,與伺服器斷開了連結!") }; websocket.onclose = function (evnt) { alert("與伺服器斷開了連結!") }; } else { alert("連線已存在!") } } function showChat(evnt) { var message = eval("(" + evnt.data + ")"); var msg = $("#msg"); //msg.html是之前的聊天內容,空一行 msg.html(msg.html() + "<br/>" + "使用者: " + message.user + " 傳送時間:" + message.sendDate + "<br/>" + message.sendContent); } function sendMsg() { var msg = $("#msgContent"); if (websocket == null) { alert("連線未開啟!"); return; } var message = msg.val(); //輸入完成後,清空輸入區 msg.val(""); if (message == null || message === "") { alert("輸入不能為空的哦"); return; } //向後臺MyWebSocketHandler中的handerMessage傳送資訊 //這裡將資訊轉成JSON格式傳送 websocket.send(JSON.stringify({ message: message, type: "chatMsg" })); } /** * 關閉連線 */ function closeConnection() { if (websocket != null) { websocket.close(); websocket = null; alert("已經關閉連線") } else { alert("未開啟連線") } } </script> </html>
後臺MyWebSocketHander接受資料
@Component
public class MyWebSocketHander implements WebSocketHandler {
private final static List<WebSocketSession> USERS = new ArrayList<>();
private final static List<User> USER_ONLINE = new ArrayList<>();
/*
*在連結建立完後就在前端顯示線上使用者
*/
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
USERS.add(webSocketSession);
//每次有新的連線,就加入到user集合中
User user = (User) webSocketSession.getAttributes().get("ws_user");
USER_ONLINE.add(user);
List<String> userNamelist = new ArrayList<>();
for (User u : USER_ONLINE) {
String userName = u.getUserName();
userNamelist.add(userName);
}
//String類的format()方法用於建立格式化的字串以及連線多個字串物件。
//這裡傳到前端的應該是JSON格式
String messageFormat = "{onlineNum:\"%d\",userName:\"%s\" , msgTyp " +
":\"%s\"}";
String msg = String.format(messageFormat, USERS.size(), userNamelist,
"notice");
TextMessage testMsg = new TextMessage(msg + "");
//確保每個使用者資訊都能同步到
for (WebSocketSession wss : USERS) {
wss.sendMessage(testMsg);
}
}
/**
* 客戶端傳送伺服器的訊息時的處理函式,在這裡收到訊息之後可以分發訊息
*/
@Autowired
private ChatService chatService;
@Override
public void handleMessage(WebSocketSession webSocketSession,
WebSocketMessage<?> webSocketMessage) throws Exception {
String messageFormat = null;
//傳送訊息的時間
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String sentMsgDate = dateFormat.format(new Date());
User user = (User) webSocketSession.getAttributes().get("ws_user");
String msgContent = webSocketMessage.getPayload() + "";
JSONObject chat = JSON.parseObject(msgContent);
//訊息的內容
String msgJSON = chat.get("message").toString();
//訊息的樣式
String msgJSONType = chat.get("type").toString();
String chatMsg = "chatMsg";
if (msgJSONType.equals(chatMsg)) {
//將訊息儲存到資料庫
ChatMsg chatMessage = new ChatMsg(user.getId(), sentMsgDate,
msgJSON);
chatService.addMessage(chatMessage);
messageFormat = "{user:\"%s\",sendDate:\"%s\" ," +
"sendContent:\"%s\" , msgTyp :\"%s\"}";
String message = String.format(messageFormat, user.getUserName(),
sentMsgDate, msgJSON , "msg");
TextMessage toMsg = new TextMessage(message + "");
//遍歷所有的使用者,發信息,這個要注意哦,要不然不能做到多人同時聊天
for (WebSocketSession wss : USERS) {
wss.sendMessage(toMsg);
}
}
}
@Override
public void handleTransportError(WebSocketSession webSocketSession,
Throwable throwable) throws Exception {
USERS.remove(webSocketSession);
}
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession,
CloseStatus closeStatus) throws Exception {
User userRemove = (User) webSocketSession.getAttributes().get(
"ws_user");
USER_ONLINE.remove(userRemove);
USERS.remove(webSocketSession);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
所以websocket訊息傳送流程大致是
websocket.onopen開啟連結 --> websocket.send()傳送資料 -->後臺的MyWebSocketHander接收資料-->WebSocketSession.sendMessage將訊息傳送給前端 --> 前端websocket.onmessage()接收資料並顯示。
github地址:https://github.com/androidlearner2017/simple-chatroom.git
很簡單的一個demon,裡面有些功能還沒有完全實現,繼續修改中 ing