Anotación de @ServerEndpoint: uso compartido más reciente de 2023, websocket liviano en springboot

@ServerEndpoint:

Define principalmente la clase actual como un servidor websocket, y el valor de la anotación se usará para monitorear la dirección URL de acceso al terminal de la conexión del usuario, y el cliente puede conectarse al servidor WebSocket a través de esta URL

Descripción: Este proyecto es un websocket integrado con springboot.
Mi proyecto usa gradel para importar dependencias. Las dependencias de maven se adjuntan a continuación. La versión es consistente con springboot.

build.gradle
    compile group:  'org.springframework.boot', name: 'spring-boot-starter-websocket', version: '2.0.4.RELEASE'

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

Este artículo adopta la programación de anotaciones y el desarrollo rápido es el siguiente:
procesador central MyWebSocketServer.java


@ServerEndpoint(value = "/mysocket", encoders = AnswerEncoder.class)
@Component
@Slf4j
public class MyWebSocketServer {
    
    

    /**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;

    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
    private static final CopyOnWriteArraySet<ScreenWebSocketServer> WEB_SOCKET_SET = new CopyOnWriteArraySet<ScreenWebSocketServer>();

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

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
    
    
        this.session = session;
        // 将当前连接加入到set中
        WEB_SOCKET_SET.add(this);
        // 连接数+1
        addOnlineCount();
        log.info("MyWebSocketServer 加入新的连接,当前连接数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
    
    
        // 将当前连接从set中移除
        WEB_SOCKET_SET.remove(this);
        // 连接数-1
        subOnlineCount();
        log.info("MyWebSocketServer 有一连接关闭!当前连接数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    
    
        log.info("MyWebSocketServer 收到来自窗口" + session.getId() + "的信息:" + message);
    }

    /**
     * @param session 连接session
     * @param error   措施信息
     */
    @OnError
    public void onError(Session session, Throwable error) {
    
    
        log.error("MyWebSocketServer 连接发生错误");
        error.printStackTrace();
    }


    /**
     * <p>@Description:給session连接推送消息</p>
     * <p>@param [message]</p>
     * <p>@return void</p>
     * <p>@throws </p>
     */
    private void sendMessage(Object message) throws IOException {
    
    
        try {
    
    
            this.session.getBasicRemote().sendObject(message);
        } catch (EncodeException e) {
    
    
            e.printStackTrace();
            log.error("MyWebSocketServer 向客户端推送数据发生错误");
        }
    }

    /**
     * <p>@Description:向所有连接群发消息</p>
     * <p>@param [message]</p>
     * <p>@return void</p>
     * <p>@throws </p>
     */
    public static void sendMessageToAll(Object message){
    
    
        for (ScreenWebSocketServer item : WEB_SOCKET_SET) {
    
    
            try {
    
    
                item.sendMessage(message);
            } catch (IOException e) {
    
    
                log.error("MyWebSocketServer 向客户端推送数据发生错误");
            }
        }
    }

    public static synchronized int getOnlineCount() {
    
    
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
    
    
        ScreenWebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
    
    
        ScreenWebSocketServer.onlineCount--;
    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) {
    
    
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
    
    
            return false;
        }
        ScreenWebSocketServer that = (ScreenWebSocketServer) o;
        return Objects.equals(session, that.session);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(session);
    }
}

El codificador que envía el mensaje AnswerEncoder.java

public class AnswerEncoder implements Encoder.Text<Answer> {
    
    
    @Override
    public void destroy() {
    
    
        // TODO Auto-generated method stub
    }

    @Override
    public void init(EndpointConfig arg0) {
    
    
        // TODO Auto-generated method stub
    }

    @Override
    public String encode(Answer answer) throws EncodeException {
    
    
        return JSONUtil.toJsonStr(answer);
    }
}

El paso más crítico: exponer ServerEndpointExporter a la administración de contenedores Spring, nos ayudará a inyectar el procesador websocket marcado con la anotación @ServerEndpoint; de lo contrario, la configuración anterior no tendrá efecto.

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

/**
 * File Name: WebsocketConfiguration
 * Description: Websocket 相关配置类
 */
@Configuration
public class WebSocketConfiguration {
    
    

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

}

Hasta ahora, nuestro websocket está configurado, entonces, ¿cómo llamarlo, cómo enviar activamente el mensaje del servidor al cliente? Consulte el siguiente código de ejemplo:


@RequestMapping("socketPushTest")
@RestController
public class MyWebSocketPushTest {
    
    

    @ApiOperation("给已连接的所有session进行群发")
    @PostMapping("/sendMessageToAll")
    public void push(@RequestBody Object data) {
    
    
        // 给前端群发数据变更消息
        Answer success = Answer.success("群发的消息-----啦啦啦");
        MyWebSocketServer.sendMessageToAll(success);
    }
}

El código principal es MyWebSocketServer.sendMessageToAll(success);
Bueno, ahora nuestro websocket incrustado de springboot está configurado y podemos conectarnos a este servicio a través de url

Permítanme publicar una imagen de mi prueba a continuación.Explicación
: el puerto de inicio de mi proyecto springboot (es decir, el servidor.puerto del archivo yml) es 9090
ws://127.0.0.1:9090/mysocket
Paso 1. Simular usuario de solicitud ws 1
inserte la descripción de la imagen aquí
Simule el usuario de solicitud de ws 2
inserte la descripción de la imagen aquí
Verifique el registro de impresión de la consola de ideas
inserte la descripción de la imagen aquí
En este punto, la conexión ws se creó con éxito, llame a la interfaz ws push para realizar el envío grupal y luego verifique si el usuario 1 y el usuario 2 pueden recibir
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Preguntas y respuestas: después de la configuración, el proyecto springboot comienza a informar un error. El ámbito de uso de este blog es springboot+tomcat. Si se informa un error al inicio, excluya spring-boot-starter-tomcat
cuando dependa de maven o gradle se introducen La configuración es la siguiente:

build.gradle
compile("org.springframework.boot:spring-boot-starter-web:2.1.4.RELEASE") {
    
    
        exclude module: "spring-boot-starter-tomcat"
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
pom.xml
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-websocket</artifactId>
		<exclusions>
			<exclusion>
				<groupId>org.springframework.boot</groupId>
				<artifactId>tomcat-embed-websocket</artifactId>
			</exclusion>
		</exclusions>
	</dependency>


Si su servidor de publicación de proyectos es embarcadero, puede salir y girar a la izquierda, este blog no es aplicable. El código escrito en este blog es para publicar websocket con tomcat, que está integrado con su propio springboot, ¡y no se habilita ningún puerto adicional! ! ! !

Supongo que te gusta

Origin blog.csdn.net/lzq2357639195/article/details/130746392
Recomendado
Clasificación