История WebSocket (6) — В Springboot реализация более гибкого WebSocket

задняя часть Spring WebSocket Tomcat

Обзор

Серию рассказов о WebSocket планируется разделить на пять глав и шесть глав, чтобы представить WebSocket и узнать, как быстро создавать и использовать возможности, предоставляемые WebSocket в Springboot. В эту серию планов входят следующие статьи:

Часть 1, что такое WebSocket и для чего он используется
Вторая статья, как использовать STOMP для быстрой сборки режима широковещательных сообщений WebSocket в Spring
Третья статья в Springboot о том, как использовать WebSocket и STOMP для быстрого создания режима двухточечных сообщений (1)
Четвертая часть, в Springboot, как использовать WebSocket и STOMP для быстрого создания режима сообщений точка-точка (2)
Пятая статья в Springboot реализует собственный агент сообщений WebSocket для веб-чатов.
Шестая статья в Springboot реализует более гибкий WebSocket.

Основная линия этой статьи

Это последняя статья в этой серии, и в ней будет представлен еще один способ реализации WebSocket. Простой чат по-прежнему будет использоваться в качестве примера. До сих пор мы также можем выбирать различные методы реализации в зависимости от конкретной ситуации.

Соответствующие читатели этой статьи

Целеустремленные молодые люди, которые хотят знать, как настраивать и реализовывать более сложную логику продукта WebSocket в Springboot.

Используйте поддержку WebSocket, предоставляемую Tomcat

ужеJava EE 7, он был опубликованJSR356Спецификация. Начиная с Tomcat7.0.47, он также поддерживает унифицированныеWebSocketинтерфейс. в настоящее время используетSpringbootтакже можно легко использоватьTomcatпредоставляемые этими API. Сегодня мы испытаемTomcatосуществленныйWebSocket.

1. Введите зависимости

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

Springboot имеет встроенный tomcat, мы можем напрямую представить этот расширенный компонент Spring. Кстати, расширенные компоненты Springboot будут автоматически ссылаться на базовые компоненты, такие какspring-boot-starter-websocketпредставилspring-boot-starter-webиspring-boot-starter, поэтому не вводите его повторно.

2. Создайте конечную точку WebSocket, используя @ServerEndpoint

ввести сначалаServerEndpointExporter, этот bean-компонент будет автоматически зарегистрирован и использован@ServerEndpointКонечная точка WebSocket, объявленная аннотацией.

package com.draw.wsdraw.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

Затем мы начинаем реализовывать класс реализации службы WebSocket, вотWebSocketServer, не забудьте использовать@ServerEndpintи@Componentпод заявлением. Несмотря на то что@ComponentПо умолчанию используется одноэлементный режим, но Springboot по-прежнему будет инициализировать его для каждого соединения WebSocket.Bean, поэтому его можно сохранить со статической картой. Другими словами, каждый раз, когда пользователь устанавливает соединение с сервером,WebSocketServerобъект, нажмите этот объектroomIdСохранить какHashMap, что удобно для последующего использования.

При создании ServerEndpoint нужно соответствовать нескольким функциональным методам, необходимым для его реализации:OnOpen、OnMessage、OnClose、OnError.

  • @OnOpen: когда клиент инициирует установление соединения с сервером, сервер вызывает, и параметры, которые могут быть переданы, — это Session (сеанс WebSocket) и EndpointConfig. Кроме того, можно добавить параметры, аннотированные с помощью @PathParam. Параметр, который мы аннотировали здесь, — это roomId, то есть параметр адреса запроса, передаваемый при установлении соединения, который имеет ту же функцию, что и {INFO}, представленный в нашей предыдущей статье.
  • @OnMessage: Вызывается при поступлении сообщения клиента, включая сеанс, в соответствии с формой сообщения, если это текстовое сообщение, передать параметр типа String или Reader, если это двоичное сообщение, передать тип byte[] параметр или InputStream.
  • @OnClose: вызывается при разрыве соединения и закрытии WebSocket.
  • @OnError: вызывается при возникновении ошибки, передавая сеанс исключения и сообщение об ошибке.

Переписав описанный выше метод, можно реализовать бизнес-логику WebSocket на стороне сервера.

@ServerEndpoint("/webSocket/{roomId}")
@Component
public class WebSocketServer {
    private static ConcurrentHashMap<String, List<WebSocketServer>> webSocketMap =
            new ConcurrentHashMap<>(3);

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //接收roomId
    private String roomId = "";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config, @PathParam("roomId") String roomId) {
        if (roomId == null || roomId.isEmpty()) return;
        this.session = session;
        this.roomId = roomId;
        addSocketServer2Map(this);
        try {
            sendMessage("连接成功", true);
        } catch (IOException e) {
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        List<WebSocketServer> wssList = webSocketMap.get(roomId);
        if (wssList != null) {
            for (WebSocketServer item : wssList) {
                if (item.session.getId().equals(session.getId())) {
                    wssList.remove(item);
                    if (wssList.isEmpty()) {
                        webSocketMap.remove(roomId);
                    }
                    break;
                }
            }
        }
    }
    
    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        //群发消息
        String msg = filterMessage(message);
        if (msg != null) {
            sendInfo(msg, roomId, session);
        }
    }

    /**
     * 发生错误时,调用的方法
     */
    @OnError
    public void onError(Session session, Throwable error) {
    }

Таким образом, код на стороне сервера завершен, здесь размещена только часть исходного кода, а адрес исходного кода проекта будет указан далее в статье.

3. Реализовать клиентскую страницу

<script type="text/javascript">
    var ws;
    
    function setConnected(connected){
        document.getElementById('connect').disabled = connected;
        document.getElementById('disconnect').disabled = !connected;
        document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
        $("#response").html();
    }

    function connect(){
        var roomId = $('#roomId').val();
        ws = new WebSocket('ws://localhost:8080/webSocket/' + roomId);
        ws.onopen = WSonOpen;
        ws.onmessage = WSonMessage;
        ws.onclose = WSonClose;
        ws.onerror = WSonError;
    }

    function WSonOpen() {
        var message = {
            name:'Server',
            chatContent:'成功连接'
        }
        setConnected(true);
        showResponse(message)
    };

    function WSonMessage(event) {
        var message = {
            name:'Server',
            chatContent:event.data
        }
        showResponse(message)
    };

    function WSonClose() {
        var message = {
            name:'Server',
            chatContent:'已断开'
        }
        showResponse(message)
    };

    function WSonError() {
        var message = {
            name:'Server',
            chatContent:'连接错误!'
        }
        showResponse(message)
    };

    function disconnect(){
        ws.close()
        setConnected(false);
        console.log("Disconnected");
    }

    function sendMessage(){
        var chatContent = $("#chatContent").val();
        var roomId = $('#roomId').val();
        ws.send(JSON.stringify({'roomId':roomId,'chatContent':chatContent}))
    }

    function showResponse(message){
         var response = $("#response").val();
         $("#response").val(response+message.name+': '+message.chatContent+'\n');
    }
</script>

Страница клиента реализует простые функции подключения, отключения и отправки сообщений. Эта часть подробно не описана.

4. Скриншот демо

Адрес источника

Адрес источника этой статьи:

Другой способ реализации WebSocket

Суммировать

В этой статье напрямую используется WebSocket, предоставленный Tomcat, который также является относительно гибкой реализацией.Его нужно реализовать только в соответствии с описанными выше шагами. Сосредоточьтесь на написании кода бизнес-логики.

Во всей серии мы представили несколько способов реализации WebSocket, некоторые из которых являются высокоинтегрированными, а некоторые относительно гибкими. Вы можете выбрать подходящий метод в соответствии с фактическими потребностями бизнеса. На этом серия закончилась. Спасибо всем за чтение.

Произведено Сяомином, это должен быть бутик

Добро пожаловать на технический форум xNPE, ежедневно появляется все больше оригинальных галантерейных товаров.