使用Vert.x實現一個簡單的websocket聊天室

使用Vert.x實現一個簡單的websocket聊天室

小菜一枚,公司業務使用了基於netty的websocket,奈何不會netty,索性之前瞭解到一個基於netty的toolkit,也就是Vert.x。
Vert.x是一個基於事件和異步,依託於全異步Java服務器Netty,並擴展了很多其他特性,以其輕量、高性能、支持多語言開發而備受開發者青睞的工具集(注意,不是說的框架,而是工具集)。點擊進入Vert.x官網。目前Vert.x以更新到了3.5.0
它支持的語言:Java、JavaScript、Groovy、Ruby、Ceylon、Kotlin、Scala……未來也許會增加更多的語言支持。
言歸正傳,這個小東西代碼不多,僅作爲個人學習Vert.x使用,預期實現目標如下:
- 使用Maven搭建Vert.x程序框架
- 使用Vert.x的WebSocket實現一個簡易的局域網聊天室(僅支持文本消息)

Step1 開發環境

Vert.x3.5.0因爲使用了大量的Java8的特性,比如lambda表達式,所以要求JDK版本爲JDK8+
Maven我使用的3.3.9
IDE使用的Intellij IDEA 2017.2

Step2 項目搭建

新建一個Maven項目,名稱什麼的隨便
pom.xml文件中引入Vert.x 3.5.0版本的依賴

    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-web</artifactId>
      <version>3.5.0</version>
    </dependency>

引入了vertx-web自動引入了vertx-core,所以不用手動添加core的依賴

Step3 編寫代碼

  • 創建WebSocketVerticle.java
import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.ServerWebSocket;
import io.vertx.ext.web.Router;

import java.util.HashMap;
import java.util.Map;

public class WebSocketVerticle extends AbstractVerticle {
    // 保存每一個連接到服務器的通道
    private Map<String, ServerWebSocket> connectionMap = new HashMap<>(16);

    @Override
    public void start() throws Exception {

        HttpServer server = vertx.createHttpServer();

        Router router = Router.router(vertx);

        router.route("/").handler(routingContext -> {
            routingContext.response().sendFile("html/ws.html");
        });
        websocketMethod(server);
        server.requestHandler(router::accept).listen(8080);
    }

    public void websocketMethod(HttpServer server) {
        server.websocketHandler(webSocket -> {
            // 獲取每一個鏈接的ID
            String id = webSocket.binaryHandlerID();
            // 判斷當前連接的ID是否存在於map集合中,如果不存在則添加進map集合中
            if (!checkID(id)) {
                connectionMap.put(id, webSocket);
            }

            // WebSocket 連接
            webSocket.frameHandler(handler -> {
                String textData = handler.textData();
                String currID = webSocket.binaryHandlerID();
                //給非當前連接到服務器的每一個WebSocket連接發送消息
                for (Map.Entry<String, ServerWebSocket> entry : connectionMap.entrySet()) {
                    if (currID.equals(entry.getKey())) {
                        continue;
                    }
                    /* 發送文本消息
                    文本信息似乎不支持圖片等二進制消息
                    若要發送二進制消息,可用writeBinaryMessage方法
                    */
                    entry.getValue().writeTextMessage(textData);
                }
            });

            // 客戶端WebSocket 關閉時,將當前ID從map中移除
            webSocket.closeHandler(handler -> connectionMap.remove(id) );
        });
    }
    // 檢查當前ID是否已經存在與map中
    public boolean checkID(String id) {
        return connectionMap.containsKey(id);
    }

整個websocket的服務器端代碼就這麼點。沒有用過其它的框架實現過websocket聊天室,不知道代碼量如何。但就Vert.x的實現方式來說,個人覺得還是很方便的。

  • 部署Verticle
    public class Main {
    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(WebSocketVerticle.class.getName());
    }
}
  • 最後HTML文件放置在resources/html下
    ws.html
    <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocketTest</title>
    <script type="text/javascript" src="http://www.w3school.com.cn/jquery/jquery-1.11.1.min.js"></script>
</head>
<body>
<script>
    var socket;
    if(window.WebSocket){
        socket = new WebSocket("ws://localhost:8080/");
        // websocket收到消息
        socket.onmessage = function(event){
            // 如果服務端是寫的二進制數據,則此處的blob也是一個二進制對象,提取數據時需要Blob類和FileReader類配合使用
            var blob = event.data;
            var content = $("#content").html();
            blob += content;
            $("#content").html(blob);
        };

        // websocket連接打開
        socket.onopen = function (event) {
            console.log("websocket 連接打開");
        };

        // websocket連接關閉
        socket.onclose = function (event) {
            console.log("websocket 連接關閉");
        };
    }else{
        alert("你的瀏覽器不支持websocket");
    }

    function send(message) {
        if(!window.WebSocket){
            return;
        }
        if(socket.readyState == WebSocket.OPEN){
            socket.send(message);
        }else{
            alert("websocket連接未打開,請檢查網絡設置");
        }
    }
</script>
<form onsubmit="return false;">
    <input type="text" name="message">
    <input type="button" value="提交" onclick="send(this.form.message.value)">
    <div id="content"></div>
</form>
</body>
</html>

羣推薦:如果對Vert.x技術感興趣,可以加QQ羣: 515203212
轉載請註明出處:http://blog.csdn.net/zhhactj/article/details/78728899

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章