一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring boot項目整合WebSocket方法

Spring boot項目整合WebSocket方法

2022-01-07 12:50灡亾 Java教程

這篇文章主要介紹了WebSocket使用Spring boot整合方法,需要繼承webSocketHandler類,重寫幾個方法就可以了,具體實例代碼跟隨小編一起看看吧

WebSocket是一種在單個TCP連接上進行全雙工通信的協議。WebSocket通信協議于2011年被IETF定為標準RFC 6455,并由RFC7936補充規范。WebSocket API也被W3C定為標準。WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并進行雙向數據傳輸。

springboot對websocket支持很友好,只需要繼承webSocketHandler類,重寫幾個方法就可以了

這個類是對消息的一些處理,比如是發給一個人,還是發給所有人,并且前端連接時觸發的一些動作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/**
 * 創建一個WebSocket server
 *
 * @ClassName: CustomWebSocketHandler
 * @Description: TODO
 * @author OnlyMate
 * @Date 2018年8月16日 下午3:17:34
 *
 */
@Service
public class CustomWebSocketHandler extends TextWebSocketHandler implements WebSocketHandler {
    private Logger logger = LoggerFactory.getLogger(CustomWebSocketHandler.class);
    // 在線用戶列表
    private static final Map<String, WebSocketSession> users;
    // 用戶標識
    private static final aString CLIENT_ID = "mchNo";
 
    static {
        users = new HashMap<>();
    }
 
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        logger.info("成功建立websocket-spring連接");
        String mchNo = getMchNo(session);
        if (StringUtils.isNotEmpty(mchNo)) {
            users.put(mchNo, session);
            session.sendMessage(new TextMessage("成功建立websocket-spring連接"));
            logger.info("用戶標識:{},Session:{}", mchNo, session.toString());
        }
    }
 
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        logger.info("收到客戶端消息:{}", message.getPayload());
        JSONObject msgJson = JSONObject.parseObject(message.getPayload());
        String to = msgJson.getString("to");
        String msg = msgJson.getString("msg");
        WebSocketMessage<?> webSocketMessageServer = new TextMessage("server:" +message);
        try {
            session.sendMessage(webSocketMessageServer);
            if("all".equals(to.toLowerCase())) {
                sendMessageToAllUsers(new TextMessage(getMchNo(session) + ":" +msg));
            }else {
                sendMessageToUser(to, new TextMessage(getMchNo(session) + ":" +msg));
            }
        } catch (IOException e) {
            logger.info("handleTextMessage method error:{}", e);
        }
    }
 
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        logger.info("連接出錯");
        users.remove(getMchNo(session));
    }
 
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        logger.info("連接已關閉:" + status);
        users.remove(getMchNo(session));
    }
 
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
 
    public void sendMessage(String jsonData) {
        logger.info("收到客戶端消息sendMessage:{}", jsonData);
        JSONObject msgJson = JSONObject.parseObject(jsonData);
        String mchNo = StringUtils.isEmpty(msgJson.getString(CLIENT_ID)) ? "陌生人" : msgJson.getString(CLIENT_ID);
        String to = msgJson.getString("to");
        String msg = msgJson.getString("msg");
        if("all".equals(to.toLowerCase())) {
            sendMessageToAllUsers(new TextMessage(mchNo + ":" +msg));
        }else {
            sendMessageToUser(to, new TextMessage(mchNo + ":" +msg));
        }
    }
    
    /**
     * 發送信息給指定用戶
     * @Title: sendMessageToUser
     * @Description: TODO
     * @Date 2018年8月21日 上午11:01:08
     * @author OnlyMate
     * @param mchNo
     * @param message
     * @return
     */
    public boolean sendMessageToUser(String mchNo, TextMessage message) {
        if (users.get(mchNo) == null)
            return false;
        WebSocketSession session = users.get(mchNo);
        logger.info("sendMessage:{} ,msg:{}", session, message.getPayload());
        if (!session.isOpen()) {
            logger.info("客戶端:{},已斷開連接,發送消息失敗", mchNo);
            return false;
        }
        try {
            session.sendMessage(message);
        } catch (IOException e) {
            logger.info("sendMessageToUser method error:{}", e);
            return false;
        }
        return true;
    }
 
    /**
     * 廣播信息
     * @Title: sendMessageToAllUsers
     * @Description: TODO
     * @Date 2018年8月21日 上午11:01:14
     * @author OnlyMate
     * @param message
     * @return
     */
    public boolean sendMessageToAllUsers(TextMessage message) {
        boolean allSendSuccess = true;
        Set<String> mchNos = users.keySet();
        WebSocketSession session = null;
        for (String mchNo : mchNos) {
            try {
                session = users.get(mchNo);
                if (session.isOpen()) {
                    session.sendMessage(message);
                }else {
                    logger.info("客戶端:{},已斷開連接,發送消息失敗", mchNo);
                }
            } catch (IOException e) {
                logger.info("sendMessageToAllUsers method error:{}", e);
                allSendSuccess = false;
            }
        }
 
        return allSendSuccess;
    }
    
    /**
     * 獲取用戶標識
     * @Title: getMchNo
     * @Description: TODO
     * @Date 2018年8月21日 上午11:01:01
     * @author OnlyMate
     * @param session
     * @return
     */
    private String getMchNo(WebSocketSession session) {
        try {
            String mchNo = session.getAttributes().get(CLIENT_ID).toString();
            return mchNo;
        } catch (Exception e) {
            return null;
        }
    }
}

這個類的作用就是在連接成功前和成功后增加一些額外的功能

我們希望能夠把websocketSession和httpsession對應起來,這樣就能根據當前不同的session,定向對websocketSession進行數據返回;在查詢資料之后,發現spring中有一個攔截器接口,HandshakeInterceptor,可以實現這個接口,來攔截握手過程,向其中添加屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * WebSocket握手時的攔截器
 * @ClassName: CustomWebSocketInterceptor
 * @Description: TODO
 * @author OnlyMate
 * @Date 2018年8月16日 下午3:17:04 
 *
 */
public class CustomWebSocketInterceptor implements HandshakeInterceptor {
    private Logger logger = LoggerFactory.getLogger(CustomWebSocketInterceptor.class);
    /**
     * 關聯HeepSession和WebSocketSession,
     * beforeHandShake方法中的Map參數 就是對應websocketSession里的屬性
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            logger.info("*****beforeHandshake******");
            HttpServletRequest httpServletRequest = ((ServletServerHttpRequest) request).getServletRequest();
            HttpSession session = httpServletRequest.getSession(true);
            
            logger.info("mchNo:{}", httpServletRequest.getParameter("mchNo"));
            if (session != null) {
                
                map.put("sessionId",session.getId());
                map.put("mchNo", httpServletRequest.getParameter("mchNo"));
            }
        }
        return true;
    }
 
    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
        logger.info("******afterHandshake******");
    }
}

這個類是配置類向Spring中注入handler

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * websocket的配置類
 * @ClassName: CustomWebSocketConfig
 * @Description: TODO
 * @author OnlyMate
 * @Date 2018年8月16日 下午3:17:26 
 *
 */
@Configuration
@EnableWebSocket
public class CustomWebSocketConfig implements WebSocketConfigurer {
 
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(customWebSocketHandler(), "/webSocketBySpring/customWebSocketHandler").addInterceptors(new CustomWebSocketInterceptor()).setAllowedOrigins("*");
        registry.addHandler(customWebSocketHandler(), "/sockjs/webSocketBySpring/customWebSocketHandler").addInterceptors(new CustomWebSocketInterceptor()).setAllowedOrigins("*").withSockJS();
    }
 
    @Bean
    public WebSocketHandler customWebSocketHandler() {
        return new CustomWebSocketHandler();
    }
}

補充說明:

setAllowedOrigins("*")一定要加上,不然只有訪問localhost,其他的不予許訪問

setAllowedOrigins(String[] domains),允許指定的域名或IP(含端口號)建立長連接,如果只允許自家域名訪問,這里輕松設置。如果不限時使用"*"號,如果指定了域名,則必須要以http或https開頭

經查閱官方文檔springwebsocket 4.1.5版本前默認支持跨域訪問,之后的版本默認不支持跨域,需要設置

使用withSockJS()的原因:

  一些瀏覽器中缺少對WebSocket的支持,因此,回退選項是必要的,而Spring框架提供了基于SockJS協議的透明的回退選項。

SockJS的一大好處在于提供了瀏覽器兼容性。優先使用原生WebSocket,如果在不支持websocket的瀏覽器中,會自動降為輪詢的方式。
除此之外,spring也對socketJS提供了支持。

如果代碼中添加了withSockJS()如下,服務器也會自動降級為輪詢。

registry.addEndpoint("/coordination").withSockJS();

SockJS的目標是讓應用程序使用WebSocket API,但在運行時需要在必要時返回到非WebSocket替代,即無需更改應用程序代碼。

客戶端與JAVA WebSocket建立連接

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<c:set var="ctxpath"
    value="${pageContext.request.scheme}${'://'}${pageContext.request.serverName}${':'}${pageContext.request.serverPort}${pageContext.request.contextPath}" />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset=UTF-8">
<title>登錄測試</title>
</head>
<body>
    <h2>Hello World! Web Socket by Spring</h2>
    <div>
        <span>sessionId:</span>
        <%
            HttpSession s= request.getSession();
            out.println(s.getId());
        %>
    </div>
    
    <input id="sessionId" type="hidden" value="<%=session.getId() %>" />
    <input id="text" type="text" />
    <button onclick="send()">發送消息</button>
    <hr />
    <button onclick="closeWebSocket()">關閉WebSocket連接</button>
    <hr />
    <div id="message"></div>
</body>
<script type="text/javascript" src="http://localhost:8088/static/js/sockjs-0.3.min.js"></script>
<script type="text/javascript"
        var websocket = null
        //判斷當前瀏覽器是否支持WebSocket 
        //判斷當前瀏覽器是否支持WebSocket 
        if('WebSocket' in window) {
            websocket = new WebSocket("ws://localhost:8088/websocket/webSocketBySpring/customWebSocketHandler?mchNo="+ 123); 
        } else if('MozWebSocket' in window) {
            websocket = new MozWebSocket("ws://localhost:8088/websocket/webSocketBySpring/customWebSocketHandler?mchNo="+ 123);
        } else {
            websocket = new SockJS("http://localhost:8088/websocket/sockjs/webSocketBySpring/customWebSocketHandler?mchNo="+ 123);
        }
        //連接發生錯誤的回調方法 
        websocket.onerror = function () { 
            setMessageInnerHTML("WebSocket連接發生錯誤"); 
        }; 
      
        //連接成功建立的回調方法 
        websocket.onopen = function () { 
            setMessageInnerHTML("WebSocket連接成功"); 
        
      
        //接收到消息的回調方法 
        websocket.onmessage = function (event) { 
            setMessageInnerHTML(event.data); 
        
      
        //連接關閉的回調方法 
        websocket.onclose = function () { 
            setMessageInnerHTML("WebSocket連接關閉"); 
        
      
        //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 
        window.onbeforeunload = function () { 
            closeWebSocket(); 
        
      
        //將消息顯示在網頁上 
        function setMessageInnerHTML(innerHTML) { 
            document.getElementById('message').innerHTML += innerHTML + '<br/>'
        
      
        //關閉WebSocket連接 
        function closeWebSocket() { 
            websocket.close(); 
        
      
        //發送消息 
        function send() { 
            var message = document.getElementById('text').value; 
            websocket.send(message); 
        
    </script>
</html>

到此這篇關于WebSocket使用Spring boot整合方法的文章就介紹到這了,更多相關Spring boot整合WebSocket內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/haozhiweizhi/p/15303675.html

延伸 · 閱讀

精彩推薦
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
主站蜘蛛池模板: 色婷婷久久综合中文久久一本` | 精品国产区一区二区三区在线观看 | 国产图片综合区 | 欧美激烈精交gif动态图18p | 丝袜兔女郎被啪在线观看91 | 亚洲成人免费 | 99热热99| 特黄特黄一级片 | 青青草原国产一区二区 | 99久久精品免费看国产一区 | 手机看片福利盒子久久 | julia ann多人乱战| 激情三级做爰在线观看激情 | 草莓视频在线免费观看 | 国产麻豆传媒在线观看 | 射逼视频 | 美女扒开奶罩让男人吃奶 | 免费看美女被靠到爽的视频 | 日韩欧美推理片免费看完整版 | 公交车强校花系列小说 | 91麻豆精东果冻天美传媒老狼 | 九色PORNY真实丨国产免费 | 我与么公激情性完整视频 | 无人区乱码区1卡2卡三卡在线 | 华人亚洲欧美精品国产 | 婷婷伊人综合亚洲综合网 | 激情乱文 | 强漂亮白丝女教师小说 | 亚洲不卡视频 | 天堂在线国产 | 久久国产热视频99rev6 | 久久精视频 | 全黄毛片 | piss美女厕所小便 | 青草视频网址 | 2022av小四郎的最新地址 | 四虎最新免费观看网址 | 久久精品亚洲国产AV涩情 | 91porn最新地址 | 国产视频一区在线观看 | 色老板视频在线观看 |