1. 程式人生 > >使用webSocket+springboot實現通訊(二)

使用webSocket+springboot實現通訊(二)

步驟一:導包

    <dependencies>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

步驟二:編寫類 class WebSocketConfig implements WebSocketConfigurer

package com.qf.websocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    /**
     * 註冊websock  處理器,其實就是誰最後來處理請求
     *
     * @param webSocketHandlerRegistry
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
//註冊websock的地址為/websocket/* 並添加了一個攔截器, 攔截器中會將請求地址中的最後一部分放入到map中傳遞到我們的handler中,.我們要求了最後一部分就是標記
        webSocketHandlerRegistry.addHandler(new ChatMessageHandler(), "/websocket/*").addInterceptors(new ChatInterceptors());

    }
}

步驟三:編寫類 ChatInterceptors extends HttpSessionHandshakeInterceptor

package com.qf.websocket;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.Map;

public class ChatInterceptors extends HttpSessionHandshakeInterceptor {


    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        //我們可以在這裡向屬性中新增一個值,這個值我們可以用作標記,map的key我們可以隨意,只要能保證唯一性以及記住就行
        //獲取請求地址,我們要求  最後一個/後面是標記
        String s = request.getURI().toString();
        String substring = s.substring(s.lastIndexOf("/") + 1);
        attributes.put("name",substring);
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

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

步驟四:編寫類 ChatMessageHandler extends TextWebSocketHandler

package com.qf.websocket;

import com.google.gson.Gson;
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.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 這個物件是單例的,
 * 當前類是一個訊息的處理類
 * @author dongbo
 * @date 2018/11/9 20:44
 */
public class ChatMessageHandler  extends TextWebSocketHandler {

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

    /**
     * 當連結建立的時候,相當於onOpen
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //攔截器中的map存放著我們的name
        Map<String, Object> attributes = session.getAttributes();
        //將連結存入map集合中
        allClient.put(((String) attributes.get("name")),session);
        super.afterConnectionEstablished(session);
    }

    /**
     * 相當於onMessage
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

        byte[] bytes = message.asBytes();
        String content = new String(bytes);
        //將收到的資訊存放在map中
        Map map = new Gson().fromJson(content, Map.class);
        //獲取訊息的接受者
        String to = (String) map.get("to");
        //獲取傳送的訊息
        String content1 = (String) map.get("content");
        //獲取接受者的連結
        WebSocketSession session1 = allClient.get(to);
        //獲取傳送者
        String from = (String) session.getAttributes().get("name");
        if(session1!=null&&session1.isOpen()){
            //傳送訊息
            session1.sendMessage(new TextMessage("收到"+from+"傳送的訊息,內容是:====>"+content1));
        }
        //群發
        Set<Map.Entry<String, WebSocketSession>> entries = allClient.entrySet();
        for (Map.Entry<String, WebSocketSession> entry : entries) {
            if(entry.getValue()!=null&&entry.getValue().isOpen()){
                entry.getValue().sendMessage(new TextMessage("收到"+from+"傳送的訊息,內容是:====>"+content1));
            }
        }

        super.handleTextMessage(session, message);
    }

    /**
     * 相當於onClose
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
    }
}

步驟五:前端介面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script type="text/javascript">

        var websocket = null;

        function abc() {
            var name = document.getElementById("name").value;
            if("WebSocket" in window){
                websocket = new WebSocket("ws://"+document.location.host+"/websocket/"+name);

                websocket.onopen = function () {
                    setMessage("連結成功");
                }

                websocket.onmessage = function (message) {
                    setMessage(message.data);
                }

                websocket.onerror = function (){
                    setMessage("連結出錯");
                }

                websocket.onclose = function () {
                    setMessage("關閉連結");
                }
            }else {
                alert("瀏覽器太垃圾了");
            }
        }

        function setMessage(data) {
            var message = document.getElementById("xianshi");
            message.innerHTML = data;
        }

        function sendMessage() {
            var to = document.getElementById("to").value;
            var mes = document.getElementById("content").value;
            if(websocket!=null){
                var message = '{"to":"'+to+'","content":"'+mes+'"}';
                websocket.send(message);
            }

        }

        function  close() {
            if(websocket!=null){
                websocket.clone();
            }
        }

        window.onbeforeunload = function () {
            close();
        }
    </script>

</head>
<body>
   使用者名稱 <input id="name"> <input type="button" onclick="abc()" value="連結"><br>
   接受者 <input id="to"><br>
    傳送內容<input id="content"> <input type="button" onclick="sendMessage()" value="傳送"><br>

<br>
   <br>
   <br>
   <br>
   <br>
   <br>
   <br>
   <br>
   <span id="xianshi"></span>>
</body>
</html>

步驟六:啟動類

package com.qf.websocket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author dongbo
 * @date 2018/11/9 20:52
 */
@SpringBootApplication
public class StartApp {
    public static void main(String[] args) {
        SpringApplication.run(StartApp.class,args);
    }
}