使用springboot实现websocket有多种方式,其中最简单的一种就是使用@ServerEndpoint
注解来实现。
首先需要引入websocket的依赖:
pom.xml(最主要的依赖)
<!--ws-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
不需要指定版本,版本会根据你引入的创建的springboot版本对应。
然后需要在springboot项目的配置类中注册一个ServerEndpointExporter
的bean
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();
}
}
再编写一个WsServerEndpoint类,这个类主要编写websocket连接以及连接之后的操作
package com.sixteen.modules.app.ws;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
//访问时的路径
//假设你的springboot项目以8080端口启动
//那么ws的url就是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...");
}
//返回值可以是void,String,ByteBuffer(nio包下的),byte[]
//如果有返回值,那么当你的ws客户端发送一条消息过来,服务端就会响应回去这个返回值
@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...");
}
}
这四个注解对于了解过websocket的人来说十分熟悉的,那么这四个注解对应的方法的参数与返回值应该填写什么呢?是不是我这里写的就一定是对的呢?
我们可以使用idea追查源码的方式来确定:
首先查看这四个注解在哪个依赖的jar包中,很多人认为肯定在上面的websocket依赖中,但这是错误的,这种ws的实现其实是tomcat实现的:
在idea搜索注解会发现注解对应的位置在tomcat包内(这里有两个版本的tomcat jar应该是我的依赖有重复的)
然后找到这个jar包,并且在javax.websocket包下找到Endpoint这个类,你会发现与注解名字相同的方法:
这里的方法就是注解对应的方法的参数与返回值,但是这里却少了一个onMessage方法,这个方法在MessageHandle接口中:
也许你会发现onMessage这个方法不是void返回值吗?
这个onMessage其实与@OnMessage下的方法是区别的,经过debug之后发现:
在该jar包中的tomcat编写的websocket包中有个PojoMessageHandlerPartialBase
类,这个类继承并重写了上面的那个onMessage方法:
processResult(result);对应的源码在PojoMessageHandlerBase
中
如果返回值为null就不向对应客户端写回数据了,虽然这里的if判断中有最后的else可以直接把result以Object写回,但是当你在@OnMessage注解下的方法返回的不是void,String,ByteBuffer,byte[]时,就会爆红说返回值错误。
对于这里我的见解是,如果要测试ws服务是否有效可以直接返回String,这样只需要一个客户端就可以测试了,找个在线的ws工具网站即可,而如果已经确定服务有效,并且用于业务中,返回值写void即可。
这样就算是把websocket的四个回调函数的参数与返回值弄清楚了。