使用spring4的websocket支持

jopen 9年前發布 | 126K 次閱讀 WebSocket 開發 WebSocket

J2EE7版(JSR-356)
http://liuxing.info/2015/02/09/websocket-demo

相關依賴請參考上文,spring需要4.x

websocket處理器

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
import org.springframework.web.socket.handler.TextWebSocketHandler;

/**

  • 功能說明:WebSocket處理器
  • 可以繼承 {@link TextWebSocketHandler}/{@link BinaryWebSocketHandler},
  • 或者簡單的實現{@link WebSocketHandler}接口
  • 作者:liuxing(2015-01-25 03:42) */ public class TelWebSocketHandler extends TextWebSocketHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(TelWebSocketHandler.class);

    /**

    • 建立連接
    • @param session
    • @throws Exception */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { String inquiryId = MapUtils.getString(session.getAttributes(), "inquiryId"); int empNo = MapUtils.getInteger(session.getAttributes(), "empNo"); TelSocketSessionUtils.add(inquiryId, empNo, session); }

      /**

    • 收到客戶端消息
    • @param session
    • @param message
    • @throws Exception */ @Override public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String inquiryId = MapUtils.getString(session.getAttributes(), "inquiryId"); int empNo = MapUtils.getInteger(session.getAttributes(), "empNo"); TelSocketSessionUtils.sendMessage(inquiryId, empNo, "【來自服務器的復讀機】:" + message.getPayload().toString()); }

      /**

    • 出現異常
    • @param session
    • @param exception
    • @throws Exception */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { String inquiryId = MapUtils.getString(session.getAttributes(), "inquiryId"); int empNo = MapUtils.getInteger(session.getAttributes(), "empNo");

      LOGGER.error("websocket connection exception: " + TelSocketSessionUtils.getKey(inquiryId, empNo)); LOGGER.error(exception.getMessage(), exception);

      TelSocketSessionUtils.remove(inquiryId, empNo); }

      /**

    • 連接關閉
    • @param session
    • @param closeStatus
    • @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { String inquiryId = MapUtils.getString(session.getAttributes(), "inquiryId"); int empNo = MapUtils.getInteger(session.getAttributes(), "empNo"); TelSocketSessionUtils.remove(inquiryId, empNo); }

      /**

    • 是否分段發送消息
    • @return */ @Override public boolean supportsPartialMessages() { return false; }

}</pre>

websocket連接的攔截器

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 javax.servlet.http.HttpSession; import java.util.Map;

/**

  • 功能說明:websocket連接的攔截器
  • 有兩種方式
  • 一種是實現接口HandshakeInterceptor,實現beforeHandshake和afterHandshake函數
  • 一種是繼承HttpSessionHandshakeInterceptor,重載beforeHandshake和afterHandshake函數
  • 我這里是參照spring官方文檔中的繼承HttpSessionHandshakeInterceptor的方式
  • 作者:liuxing(2015-01-25 03:46) */ public class TelWebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(TelWebSocketHandshakeInterceptor.class);

    /**

    • 從請求中獲取唯一標記參數,填充到數據傳遞容器attributes
    • @param serverHttpRequest
    • @param serverHttpResponse
    • @param wsHandler
    • @param attributes
    • @return
    • @throws Exception */ @Override public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { if (getSession(serverHttpRequest) != null) {

       ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) serverHttpRequest;
       HttpServletRequest request = servletRequest.getServletRequest();
       attributes.put("inquiryId", request.getParameter("inquiryId"));
       attributes.put("empNo", request.getParameter("empNo"));
      

      }

      super.beforeHandshake(serverHttpRequest, serverHttpResponse, wsHandler, attributes);

      return true; }

      @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); }

      private HttpSession getSession(ServerHttpRequest request) { if (request instanceof ServletServerHttpRequest) {

       ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
       return serverRequest.getServletRequest().getSession(false);
      

      } return null; }

}</pre>

session工具類

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;

/**

  • 功能說明:TelSocketSessionUtils
  • 作者:liuxing(2014-12-26 02:32) */ public class TelSocketSessionUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(TelSocketSessionUtils.class);

    private static Map<String, WebSocketSession> clients = new ConcurrentHashMap<>();

    /**

    • 保存一個連接
    • @param inquiryId
    • @param empNo
    • @param session */ public static void add(String inquiryId, int empNo, WebSocketSession session){ clients.put(getKey(inquiryId, empNo), session); }

      /**

    • 獲取一個連接
    • @param inquiryId
    • @param empNo
    • @return */ public static WebSocketSession get(String inquiryId, int empNo){ return clients.get(getKey(inquiryId, empNo)); }

      /**

    • 移除一個連接
    • @param inquiryId
    • @param empNo */ public static void remove(String inquiryId, int empNo) throws IOException { clients.remove(getKey(inquiryId, empNo)); }

      /**

    • 組裝sessionId
    • @param inquiryId
    • @param empNo
    • @return */ public static String getKey(String inquiryId, int empNo) { return inquiryId + "_" + empNo; }

      /**

    • 判斷是否有效連接
    • 判斷是否存在
    • 判斷連接是否開啟
    • 無效的進行清除
    • @param inquiryId
    • @param empNo
    • @return */ public static boolean hasConnection(String inquiryId, int empNo) { String key = getKey(inquiryId, empNo); if (clients.containsKey(key)) {

       return true;
      

      }

      return false; }

      /**

    • 獲取連接數的數量
    • @return */ public static int getSize() { return clients.size(); }

      /**

    • 發送消息到客戶端
    • @param inquiryId
    • @param empNo
    • @param message
    • @throws Exception */ public static void sendMessage(String inquiryId, int empNo, String message) throws Exception { if (!hasConnection(inquiryId, empNo)) {

       throw new NullPointerException(getKey(inquiryId, empNo) + " connection does not exist");
      

      }

      WebSocketSession session = get(inquiryId, empNo); try {

       session.sendMessage(new TextMessage(message));
      

      } catch (IOException e) {

       LOGGER.error("websocket sendMessage exception: " + getKey(inquiryId, empNo));
       LOGGER.error(e.getMessage(), e);
       clients.remove(getKey(inquiryId, empNo));
      

      } }

}</pre>

初始化配置

<!--websocket配置-->
<bean id="telWebSocketHandler" class="包.websocket.handler.TelWebSocketHandler"/>

<websocket:handlers allowed-origins="*"> <websocket:mapping path="webSocketStatus" handler="telWebSocketHandler"/> <websocket:handshake-interceptors> <bean class="包.websocket.interceptor.TelWebSocketHandshakeInterceptor"/> </websocket:handshake-interceptors> </websocket:handlers>

<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean"> <property name="maxTextMessageBufferSize" value="8192"/> <property name="maxBinaryMessageBufferSize" value="8192"/> <property name="maxSessionIdleTimeout" value="900000"/> <property name="asyncSendTimeout" value="5000"/> </bean></pre>
spring官方文檔已經寫得很齊全了,更多場景和說明請參閱下文大笑
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#websocket

來自:http://liuxing.info/2015/04/21/%E4%BD%BF%E7%94%A8spring4%E7%9A%84websocket%E6%94%AF%E6%8C%81

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!