服務端代碼:
第一步:初始化websocket 【推薦帶sessionid 到websocket 作爲參數】 ${sessionId}
function openWebSocket(){
//判斷當前瀏覽器是否支持WebSocket
if ('WebSocket' in window) {
console.info(window.location.host);
ws = new WebSocket("ws://"+window.location.host+"/visualizationWebSocket.do?sessionId="+${sessionId});
} else {
ws = new SockJS("http://"+window.location.host+"/wechat/sockjs/visualizationWebSocket/info?type=mall");
}
ws.onopen = function () {
console.info("當網絡連接建立時觸發該事件");
};
//這個事件是接受後端傳過來的數據
ws.onmessage = function (event) {
//根據業務邏輯解析數據
console.info("onmessage 當websocket接收到服務器發來的消息的時觸發的事件,也是通信中最重要的一個監聽事件。msg.data\n" +
"websocket還定義了一個readyState屬性,這個屬性可以返回websocket所處的狀態:"+event.data);
};
ws.onclose = function (event) {
console.info("關閉該websocket鏈接");
};
}
第二步:初始化websocket,會自動調用 倆個類中的方法
第一個方法 : VisualizationHandshakeInterceptor.java 類中的beforeHandshake ,在這裏可以獲得從前端的傳過來的參數。並且做攔截,校驗路徑是否是正常的
package com.zzw.wechat.interfaces.websocket;
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 javax.servlet.http.HttpServletRequest;
import java.util.Map;
//回話攔截器
public class VisualizationHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
//獲取請求參數,首先我們要獲取HttpServletRequest對象才能獲取請求參數;當ServerHttpRequset的層次結構打開後其子類可以獲取到我們想要的http對象,那麼就簡單了。
//我這裏是把獲取的請求數據綁定到session的map對象中(attributes)
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
System.out.println("beforeHandshake: ");
String sessionId = servletRequest.getParameter("sessionId");
if(sessionId!=null){
attributes.put("sessionId",sessionId);
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("After Handshake");
super.afterHandshake(request, response, wsHandler, ex);
}
}
第二個方法:
VisualizationWebSocketHandler.java 類中的 afterConnectionEstablished 方法,在方法中可以獲得參數。
package com.zzw.wechat.interfaces.websocket;
import net.sf.json.JSONObject;
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 java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class VisualizationWebSocketHandler extends TextWebSocketHandler {
private static final Map<String,WebSocketSession> sessions = new HashMap<String, WebSocketSession>();
private static final Map<String,Thread> threads = new HashMap<String, Thread>();
private Thread polingVisualization = null;
//用戶標識
private static final String CLIENT_ID = "sessionId";
/* @Autowired
private IVisualizationService visualizationService;*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Object sessionId = session.getAttributes().get("sessionId");
System.out.println("afterConnectionEstablished=誰連接了.="+sessionId);
if(sessionId!=null){
sessions.put(sessionId.toString(),session);
Iterator iterator= sessions.keySet().iterator();
while(iterator.hasNext()){
String key = iterator.next().toString();
System.out.println("map key===="+key);
System.out.println("map value===="+sessions.get(key));
}
}
super.afterConnectionEstablished(session);
}
//afterConnectionClosed 通信關閉調用的方法
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
System.out.println("---關閉連接");
Object sessionId = session.getAttributes().get("sessionId");
if(sessionId!=null){
sessions.remove(sessionId.toString());
}
/*Thread thread = threads.get(session.getId());
if(thread != null){
thread.interrupt();
try {
thread.join();
threads.remove(session.getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sessions.remove(session.getId());
sessions.remove(CLIENT_ID);
polingVisualization = null;
try {
super.afterConnectionClosed(session, status);
} catch (Exception e) {
}*/
}
// 作用一:客戶端返回消息,服務端接收的方法
//作用二:把接收消息,返回到前端
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
String payload = message.getPayload();
System.out.println("payload接收的信息===="+payload);
JSONObject payloadJson = JSONObject.fromObject(payload);
String sessionId=payloadJson.get("sessionId").toString();
TextMessage returnMessage = new TextMessage(payloadJson.toString());
WebSocketSession sessionaa = sessions.get(sessionId);
sessionaa.sendMessage(returnMessage);
sessions.remove(sessionId);
/* System.out.println("handleTextMessage: \n"+session.getId());*/
/*super.handleTextMessage(session, message);
Thread thread = threads.get(session.getId());
if(thread == null){
WebSocketSession sessi = sessions.get(session.getId());
if(sessi == null){
sessions.put(session.getId(),session);
} else {
session = sessi;
}
final WebSocketSession localSession = session;
final TextMessage localMessage = message;
}*/
}
}
客戶端代碼:
第三步:客戶端建立連接通信 MyClient.java 可直接拿去用
package com.zzw.wechat.interfaces.wechat;
import javax.websocket.ClientEndpoint;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import org.apache.log4j.Logger;
@ClientEndpoint
public class MyClient {
private static Logger logger = Logger.getLogger(MyClient.class);
private Session session;
@OnOpen
public void open(Session session) {
logger.info("Client WebSocket is opening...");
this.session = session;
}
@OnMessage
public void onMessage(String message) {
logger.info("Server send message: " + message);
}
@OnClose
public void onClose() {
logger.info("Websocket closed");
}
public void send(String message) {
this.session.getAsyncRemote().sendText(message);
}
}
第四步:客戶端發送消息給服務端【客戶端響應的方法,然後通過myclient 給服務端接收消息】
@RequestMapping(value = "/sendMsg")
@ResponseBody
public WebResultInfo sendMsg(@RequestBody Map<String,Object> map){
try {
//給服務端發送消息
System.out.println(map.get("sessionId"));
JSONObject json = new JSONObject();
json.put("rsult","客戶端內容");
json.put("sessionId",map.get("sessionId"));
WebSocketContainer container = ContainerProvider.getWebSocketContainer(); // 獲取WebSocket連接器,其中具體實現可以參照websocket-api.jar的源碼,Class.forName("org.apache.tomcat.websocket.WsWebSocketContainer");
String uri = "ws://localhost:8099/visualizationWebSocket.do";
MyClient client = new MyClient();
Session mysession = container.connectToServer(client, new URI(uri)); // 連接會話
mysession.getBasicRemote().sendText(json.toString()); // 發送文本消息
mysession.close();
}catch (Exception e){
e.printStackTrace();
}
return WebResultInfo.success();
}
【第四步:注,當客戶端發送消息給服務端,會調用VisualizationWebSocketHandler.java 類中的 afterConnectionEstablished 方法】,然後 afterConnectionEstablished 會相應給前端的 onmessage 方法。
ws.onmessage = function (event) {
//根據業務邏輯解析數據
console.info("onmessage 當websocket接收到服務器發來的消息的時觸發的事件,也是通信中最重要的一個監聽事件。msg.data\n" +
"websocket還定義了一個readyState屬性,這個屬性可以返回websocket所處的狀態:"+event.data);
};