Websocket實現前後臺通訊,demo小測試
阿新 • • 發佈:2018-11-07
新需求大概如下:使用者登入系統,登入成功之後建立websocket連線,實現通訊
總體思路:前端不是我負責,只是簡單的做個功能,先實現登入,把使用者標識存入HttpSeesion,再建立websocket連線,攔截器HandshakeInterceptor攔截請求,把使用者標識存入Map<String, Object> attributes,然後處理器handler處理各種操作。
/** * @author wangqq * @version 建立時間:2018年11月1日 下午2:59:21 * 實現WebSocketConfigure配置自己的socket連結*/ @Configuration //用於定義配置類,可替換xml配置檔案 @EnableWebSocket @EnableWebMvc //啟動Spring MVC特性 public class WebsocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { // TODO Auto-generated method stub registry.addHandler(handler(), "show").addInterceptors(interceptor()).setAllowedOrigins("*"); } @Beanpublic WebSocketHandler handler(){ return new Hanlder(); } @Bean public HandshakeInterceptor interceptor() { return new HandshakeInterceptor(); } }
registry.addHandler第一個引數是處理器,自己可以寫,第二個引數是前後臺建立連結的路徑,
addInterceptors 新增攔截,再握手之前之後,處理自己的業務
setAllowedOrigins 解決跨域,*代表不限,如果要指定域名則要http或者https開頭
/** * @author wangqq * @version 建立時間:2018年11月1日 下午3:06:36 * 類說明 */ public class Hanlder extends TextWebSocketHandler { private Logger logger = Logger.getLogger(Hanlder.class); private static final Map<Integer,WebSocketSession> hotels; static{ hotels = new HashMap<Integer, WebSocketSession>(); } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // TODO Auto-generated method stub Integer hotelid = IHelper.toInteger(session.getAttributes().get("hotelid")); logger.info("-----------------afterConnectionEstablished-----------------"); if(null != hotelid){ logger.info(String.format("酒店連線,id:%s", hotelid)); hotels.put(hotelid, session);
JSONObject json = new JSONObject(); json.put("code","testMessage"); session.sendMessage(new TextMessage(json.toString())); } //super.afterConnectionEstablished(session); } /** * js呼叫websocket.send時候,會呼叫該方法 */ @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // TODO Auto-generated method stub logger.info(String.format("收到酒店(id:%s)發來訊息,訊息詳情:%s", session.getAttributes().get("hotelid"),message.toString())); super.handleTextMessage(session, message); //這裡可以給使用者發訊息 logger.info("執行Hanlder---------客戶端收到請求"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { // TODO Auto-generated method stub Integer hotelid = IHelper.toInteger(session.getAttributes().get("hotelid")); logger.info(String.format("使用者退出,酒店id:%s", hotelid)); hotels.remove(hotelid); super.afterConnectionClosed(session, status); } /** * 給單個使用者發訊息 * @param hotelid * @param message * @throws IOException */ public void sendMessage(Integer hotelid,TextMessage message) throws Exception{ if(hotels.containsKey(hotelid)){ if(hotels.get(hotelid).isOpen()){ hotels.get(hotelid).sendMessage(message); } } } /** * 給所有線上使用者發訊息 * @param message * @throws IOException */ public void sendMessage(TextMessage message) throws Exception{ for(Integer id : hotels.keySet()){ WebSocketSession session = hotels.get(id); if(session.isOpen()){ session.sendMessage(message); } } } /** * 多個線上使用者,不同訊息 * @param data * @throws Exception */ public void sendMessage(Map<Integer, TextMessage> data) throws Exception{ for(Map.Entry<Integer, TextMessage> entry : data.entrySet()){ Integer hotelid = entry.getKey(); this.sendMessage(hotelid, entry.getValue()); } } /** * 多個使用者,同一訊息 * @param hotelids * @param message * @throws Exception */ public void sendMessage(List<Integer> hotelids,TextMessage message) throws Exception{ for(Integer id : hotelids){ this.sendMessage(id, message); } } }
/** * @author wangqq * @version 建立時間:2018年11月2日 下午1:42:00 * 類說明 */ public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { private Logger logger = Logger.getLogger(HandshakeInterceptor.class); @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { // TODO Auto-generated method stub logger.info("-----------beforeHandshake---------"); if(request instanceof ServletServerHttpRequest){ ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest)request; HttpSession session = serverHttpRequest.getServletRequest().getSession(); if(null != session){ logger.info("攔截請求,存入attribute,酒店id:"+session.getAttribute("hotelid")); if(null!=session.getAttribute("hotelid")){ attributes.put("hotelid", session.getAttribute("hotelid")); } } } return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { // TODO Auto-generated method stub logger.info("-----------afterHandshake--------------"); super.afterHandshake(request, response, wsHandler, ex); } }
前端頁面(簡單的不能再簡單,沒有考慮瀏覽器支不支援)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> <script language="JavaScript" src="jquery/jquery-1.11.3.min.js" charset="UTF-8"></script> <script type="text/javascript"> var ws = $(function(){ $.ajaxSettings.async=false; $.post('<%=basePath%>/show/doSaveSession',{'hotelid':1},function(data){ console.log("執行儲存session");//模擬先登入 }); $.ajaxSettings.async=true; ws = new WebSocket("ws://localhost:7001/show"); ws.onopen = function () { console.log("建立連結"); } ws.onclose = function () { console.log("onclose"); } ws.onmessage = function (msg) { console.log("----------------"); console.log(msg.data); } }); </script> </head> <body> This is my JSP page. <br> </body> </html>
執行結果:
前臺
後臺: