溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringMVC中怎么開(kāi)放WebSocket接口

發(fā)布時(shí)間:2021-06-22 14:57:41 來(lái)源:億速云 閱讀:307 作者:Leah 欄目:大數(shù)據(jù)

這篇文章給大家介紹SpringMVC中怎么開(kāi)放WebSocket接口,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

     1、配置WebSocket接口信息。

        1)首先創(chuàng)建websocket專屬的package(規(guī)范問(wèn)題,實(shí)現(xiàn)某一功能的源碼應(yīng)放到統(tǒng)一路徑下)。

        2)創(chuàng)建WebSocketConfig類,繼承WebMvcConfigurationSupport類,實(shí)現(xiàn)WebSocketConfigurer接口并實(shí)現(xiàn)其定義的方法。添加類注解

        @Configuration
        @EnableWebMvc
        @EnableWebSocket

        3)實(shí)現(xiàn)的registerWebSocketHandlers方法中,使用參數(shù)WebSocketHandlerRegistry的對(duì)象開(kāi)放WebSocket接口。

        registry.addHandler(websocket消息處理實(shí)現(xiàn)類實(shí)例,websocket地址).setAllowedOrigins("*").addInterceptors(攔截器實(shí)例);

        其中setAllowedOrigins為設(shè)置訪問(wèn)權(quán)限,通常不限制訪問(wèn)時(shí)使用“*”;addInterceptors為添加攔截器,如果不需要攔截器則可不調(diào)用此方法。

        通常開(kāi)放WebSocket接口開(kāi)放兩個(gè),因?yàn)g覽器支持的問(wèn)題,前端只能使用SockJS插件實(shí)現(xiàn)WebSocket連接,所以我們還要開(kāi)放一個(gè)專為SockJS服務(wù)的WebSocket接口,只需調(diào)用withSockJS接口即可。

        registry.addHandler(websocket消息處理實(shí)現(xiàn)類實(shí)例,websocket地址).setAllowedOrigins("*").addInterceptors(攔截器實(shí)例).withSockJS();

        至此,第一步,配置WebSocket信息已完成。

    2、自定義WebSocket消息處理實(shí)現(xiàn)。

      1)創(chuàng)建WebSocket消息處理接口,繼承WebSocketHandler接口(為開(kāi)放操作接口給其他服務(wù)調(diào)用,一般與業(yè)務(wù)相關(guān),服務(wù)端希望推送消息時(shí)調(diào)用此接口,同樣關(guān)乎規(guī)范,亦可使用其他方式實(shí)現(xiàn))。

      2)創(chuàng)建WebSocket消息處理實(shí)現(xiàn)類,實(shí)現(xiàn)第一步創(chuàng)建的接口。其中,業(yè)務(wù)接口請(qǐng)自行實(shí)現(xiàn),從WebSocketHandler繼承實(shí)現(xiàn)的接口有:

        afterConnectionEstablished:建立WebSocket連接成功時(shí)觸發(fā)。

        handleMessage:收到客戶端發(fā)送的消息時(shí)觸發(fā)。

        handleTransportError:發(fā)生異常時(shí)觸發(fā)。

        afterConnectionClosed:與客戶端斷開(kāi)連接時(shí)觸發(fā)。

        supportsPartialMessages:是否支持部分消息處理(一般返回false,此標(biāo)志一般用來(lái)拆分大型或未知大小的WebSocket消息,當(dāng)支持部分消息時(shí),一個(gè)消息會(huì)拆分成多個(gè)消息調(diào)用handleMessage,可以利用WebSocketMessage的isLast方法判斷是否最后一次消息)。

    3、自定義WebSocket消息攔截器(可選)

    1)創(chuàng)建WebSocket攔截器,實(shí)現(xiàn)HandshakeInterceptor接口。實(shí)現(xiàn)方法有:

    beforeHandshake:消息處理前。

    afterHandshake:消息處理后。

    4、將WebSocket配置實(shí)例裝入Spring容器

    此處使用配置掃描包的形式,在配置文件中添加<context:component-scan base-package="com.???.???.???.websocket" />

    其中base-package可以根據(jù)自己項(xiàng)目的實(shí)際包路徑配置。

    下面就是實(shí)例代碼,細(xì)節(jié)處可根據(jù)實(shí)際項(xiàng)目修改:

  •     WebSocket配置信息

package com.???.???.???.websocket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 * websocket配置類
 * 
 * @author Heller.Zhang
 * @since 2018年11月8日 上午10:23:04
 */
@Configuration
@EnableWebMvc
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurationSupport implements WebSocketConfigurer {

    private Logger logger = LoggerFactory.getLogger(MyWebSocketConfig.class);

    /* (non-Javadoc)
     * @see org.springframework.web.socket.config.annotation.WebSocketConfigurer#registerWebSocketHandlers(org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry)
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        logger.debug("----------開(kāi)始注冊(cè)MyWebSocketConfig----------");
        logger.debug("----------注冊(cè)普通websocket----------");
        registry.addHandler(msgSocketHandle(), "/websocket/myWebSocketServer").setAllowedOrigins("*");

        logger.debug("----------注冊(cè)sockjs/websocket----------");
        registry.addHandler(msgSocketHandle(), "/websocket/sockjs/myWebSocketServer").setAllowedOrigins("*").withSockJS();

    }

    @Bean(name = "myMsgScoketHandle", autowire = Autowire.BY_NAME)
    public MyMsgScoketHandle msgSocketHandle() {
        return new MyMsgScoketHandleImpl();
    }

}
  •     自定義WebSocket消息處理接口

package com.???.???.???.websocket;

import org.springframework.web.socket.WebSocketHandler;

/**
 * websocket消息處理器
 * 
 * @author Heller.Zhang
 * @since 2018年11月13日 下午5:13:20
 */
public interface MyMsgScoketHandle extends WebSocketHandler {

    public void sendMessage(Long userId, Integer num);
}
  • 自定義WebSocket消息處理接口實(shí)現(xiàn)

package com.???.???.???.websocket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
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.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import com.hzsparrow.framework.common.exception.ServiceException;
import com.hzsparrow.framework.utils.JsonUtils;
import com.hzsparrow.framework.utils.NumberUtils;

/**
 * websocket消息處理類
 * 
 * @author Heller.Zhang
 * @since 2018年11月8日 上午11:15:22
 */
public class MyMsgScoketHandleImpl implements MyMsgScoketHandle {

    private Logger logger = LoggerFactory.getLogger(MyMsgScoketHandleImpl.class);

    private ConcurrentMap<String, List<WebSocketSession>> webSocketMap = new ConcurrentHashMap<>();

    public MyMsgScoketHandleImpl() {
        logger.debug("--------init MyMsgScoketHandle-----------");
    }

    /* (non-Javadoc)
     * @see org.springframework.web.socket.WebSocketHandler#afterConnectionEstablished(org.springframework.web.socket.WebSocketSession)
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        logger.debug("-----------建立websocket連接---------");
    }

    /* (non-Javadoc)
     * @see org.springframework.web.socket.WebSocketHandler#handleMessage(org.springframework.web.socket.WebSocketSession, org.springframework.web.socket.WebSocketMessage)
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        logger.debug("-----------處理消息---------");
        TextMessage msg = (TextMessage) message;

        //建立連接發(fā)送的用戶id
        String msgStr= msg.getPayload();
        logger.debug("----------msg:" + msgStr);
        if (StringUtils.equals(msgStr, "heartbeat")) {
            // 心跳消息,不予處理
            return;
        }
        session.getAttributes().put("mykey", msgStr + "|" + UUID.randomUUID().toString());
        //通過(guò)用戶id獲取session集合
        List<WebSocketSession> list = webSocketMap.get(msgStr);
        //判斷集合是否為空
        if (CollectionUtils.isNotEmpty(list)) {
            list.add(session);
        } else {
            list = new ArrayList<WebSocketSession>();
            list.add(session);
        }

        //將用戶id和session集合綁定到map
        webSocketMap.put(msgStr, list);
        logger.debug("消息處理完畢");

    }

    /* (non-Javadoc)
     * @see org.springframework.web.socket.WebSocketHandler#handleTransportError(org.springframework.web.socket.WebSocketSession, java.lang.Throwable)
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        logger.debug("-----------處理異常---------");
    }

    /* (non-Javadoc)
     * @see org.springframework.web.socket.WebSocketHandler#afterConnectionClosed(org.springframework.web.socket.WebSocketSession, org.springframework.web.socket.CloseStatus)
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        logger.debug("-----------斷開(kāi)連接---------");
        String myKey = session.getAttributes().get("mykey").toString();
        String userId = myKey.split("|")[0];
        List<WebSocketSession> list = webSocketMap.get(userId);
        WebSocketSession delSession = null;
        if (CollectionUtils.isNotEmpty(list)) {
            for (WebSocketSession webSocketSession : list) {
                String delKey = webSocketSession.getAttributes().get("mykey").toString();
                if (StringUtils.equals(myKey, delKey)) {
                    delSession = webSocketSession;
                    break;
                }
            }
        }
        if (delSession != null) {
            list.remove(delSession);
        }

    }

    /* (non-Javadoc)
     * @see org.springframework.web.socket.WebSocketHandler#supportsPartialMessages()
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 給單個(gè)用戶發(fā)送消息
     * 
     * @param session
     * @param type
     * @param data
     * @throws IOException
     * @author Heller.Zhang
     * @since 2018年11月8日 下午2:05:32
     */
    public void sendMessage(WebSocketSession session, Object data) throws IOException {
        if (session.isOpen()) {
            String json = JsonUtils.serialize(data);
            TextMessage outMsg = new TextMessage(json);
            session.sendMessage(outMsg);
        }
    }

    /**
     * 發(fā)送鏈接成功消息
     * 
     * @param session
     * @throws IOException
     * @author Heller.Zhang
     * @since 2018年11月10日 下午3:16:35
     */
    public void sendSuccessMsg(WebSocketSession session, Integer type) throws IOException {
        logger.debug("---------發(fā)送鏈接成功消息-----------");
        TextMessage outMsg = new TextMessage("");
        session.sendMessage(outMsg);
    }

    @Override
    public void sendMessage(Long userId, Integer num) {
        //獲取用戶下的session集合
        List<WebSocketSession> list = webSocketMap.get(NumberUtils.num2Str(userId));
        //向每一條session中發(fā)送數(shù)據(jù)
        if (CollectionUtils.isNotEmpty(list)) {
            for (WebSocketSession webSocketSession : list) {
                try {
                    sendMessage(webSocketSession, num);
                } catch (IOException e) {
                    throw new ServiceException("發(fā)送消息失敗");
                }
            }
        }

    }

}
  • 攔截器

package com.???.???.???.websocket;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

/**
 * websocket攔截器
 * 
 * @author Heller.Zhang
 * @since 2018年11月8日 上午10:40:51
 */
public class MyWebSocketHandshakeInterceptor implements HandshakeInterceptor {

    private Logger logger = LoggerFactory.getLogger(MyWebSocketHandshakeInterceptor.class);

    /* (non-Javadoc)
     * @see org.springframework.web.socket.server.HandshakeInterceptor#beforeHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.util.Map)
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        logger.debug("---------websocket 攔截器  握手前------------");
        return true;
    }

    /* (non-Javadoc)
     * @see org.springframework.web.socket.server.HandshakeInterceptor#afterHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.lang.Exception)
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception exception) {
        logger.debug("---------websocket 攔截器  握手后------------");
    }

}
  • 掃描包配置

<?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:context="http://www.springframework.org/schema/context" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <context:component-scan base-package="com.???.???.???.websocket" />
    
</beans>

關(guān)于SpringMVC中怎么開(kāi)放WebSocket接口就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI