Implementation of springboot websokcet tomcat

There are many ways to implement websocket with springboot, and the simplest one is to implement it with @ ServerEndpoint annotation.

First, we need to introduce the dependency of websocket:
pom. XML (the most important dependency)

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

There is no need to specify the version. The version will correspond to the springboot version you created.

Then you need to register a ServerEndpointExporter bean in the configuration class of the springboot project

package com.sixteen.modules.app.config;

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

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

Then write a WsServerEndpoint class, which mainly writes the websocket connection and the operation after the connection

package com.sixteen.modules.app.ws;


import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

//Path when accessing
//Suppose your spring boot project starts on port 8080
//Then the url of ws is ws://localhost:8080/app/im
@ServerEndpoint("/app/im")
@Component
public class WsServerEndpoint{

    @OnOpen
    public void onOpen(Session session, EndpointConfig config){
        System.out.println(session.getId() + "open...");
    }

	//The return values can be void, string, ByteBuffer (under NiO package), byte []
	//If there is a return value, when your ws client sends a message, the server will respond back to the return value
    @OnMessage
    public String onMessage(String message, boolean last){
        return "server:" + message;
    }

    @OnError
    public void onError(Session session,Throwable throwable){

    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason){
        System.out.println(session.getId() + "close...");
    }

}

These four annotations are very familiar to those who know websocket. What should be filled in for the parameters and return values of the methods corresponding to these four annotations? Is it true that what I write here must be right?

We can use idea to trace the source code to determine:
First, check which jar package these four annotations depend on. Many people think they must be in the websocket dependency above, but this is wrong. This ws implementation is actually implemented by tomcat:

Search the annotation in the idea and find that the corresponding position of the annotation is in the tomcat package (there are two versions of tomcat jar, which should be my dependency and duplicate)

Then find the jar package and install it in javax Find the Endpoint class under the websocket package, and you will find the same method as the annotation Name:

The method here is to annotate the parameters and return values of the corresponding method, but there is a missing onMessage method in the MessageHandle interface:

Maybe you will find that the onMessage method is not a void return value?

This OnMessage is actually different from the method under @ OnMessage. After debug ging, it is found that:
In the websocket package written by tomcat in the jar package, there is a PojoMessageHandlerPartialBase class, which inherits and rewrites the onMessage method above:

processResult(result); The corresponding source code is in PojoMessageHandlerBase

If the return value is null, the data will not be written back to the corresponding client. Although there is the last else in the if judgment here, you can directly write back the result as Object, when the method under the @ OnMessage annotation does not return void,String,ByteBuffer,byte [], it will pop up and say that the return value is wrong.

My opinion here is that if you want to test whether the ws service is valid, you can directly return String, so you only need one client to test. Just find an online ws tool website. If you have determined that the service is valid and used in business, you can write void as the return value.

In this way, the parameters and return values of the four callback functions of websocket are clarified.

Keywords: Spring Boot Tomcat websocket

Added by garmann on Wed, 29 Dec 2021 13:50:09 +0200