1、引入 maven 依赖
<dependency>
<groupId>org.t-io</groupId>
<artifactId>tio-websocket-server</artifactId>
<version>3.5.9.v20200214-RELEASE</version>
</dependency>
注意:我这里用的是 3.5.9.v20200214-RELEASE 版本,各个版本之间存在差异,请查看官方文档
2、websocket 配置类
方式一(配置类启动):
import com.asurplus.tio.websocket.handle.MyWsMsgHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.tio.server.ServerTioConfig;
import org.tio.websocket.server.WsServerStarter;
import java.io.IOException;
/**
* websocket 配置类
*/
@Configuration
public class WebSocketConfig {
/**
* 注入消息处理器
*/
@Autowired
private MyWsMsgHandler myWsMsgHandler;
/**
* 启动类配置
*
* @return
* @throws IOException
*/
@Bean
public WsServerStarter wsServerStarter() throws IOException {
// 设置处理器
WsServerStarter wsServerStarter = new WsServerStarter(6789, myWsMsgHandler);
// 获取到ServerTioConfig
ServerTioConfig serverTioConfig = wsServerStarter.getServerTioConfig();
// 设置心跳超时时间,默认:1000 * 120
serverTioConfig.setHeartbeatTimeout(1000 * 120);
// 启动
wsServerStarter.start();
return wsServerStarter;
}
}
这里我们注入了 WsServerStarter 的 bean,这样在 SpringBoot 启动的时候,就能启动咱们的 websocket 服务
• 注明了 websocket 的服务端口为:6789
• 消息处理类为:myWsMsgHandler,在下一步我们将会去实现这个类
• 设置了心跳的超时时间为:120秒,默认值,可以不设置
方式二(配置文件):
在application.yml配置文件中配置端口、心跳等
tio:
websocket:
server:
port: 6789
heartbeat-timeout: 60000
#是否支持集群,集群开启需要redis
cluster:
enabled: true
redis:
ip: 127.0.0.1
port: 6379
password: redis
3、消息处理类
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.server.handler.IWsMsgHandler;
/**
* 消息处理类
*/
@Component
public class MyWsMsgHandler implements IWsMsgHandler {
/**
* <li>对httpResponse参数进行补充并返回,如果返回null表示不想和对方建立连接,框架会断开连接,如果返回非null,框架会把这个对象发送给对方</li>
* <li>注:请不要在这个方法中向对方发送任何消息,因为这个时候握手还没完成,发消息会导致协议交互失败。</li>
* <li>对于大部分业务,该方法只需要一行代码:return httpResponse;</li>
*
* @param httpRequest
* @param httpResponse
* @param channelContext
* @return
* @throws Exception
* @author tanyaowu
*/
@Override
public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
// 可以在此做一些业务逻辑,返回null表示不想连接
return httpResponse;
}
/**
* 握手成功后触发该方法
*
* @param httpRequest
* @param httpResponse
* @param channelContext
* @throws Exception
* @author tanyaowu
*/
@Override
public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
// 拿到用户id
String id = httpRequest.getParam("id");
// 绑定用户
Tio.bindUser(channelContext, id);
// 绑定业务类型(根据业务类型判定处理相关业务)
String bsId = httpRequest.getParam("bsId");
if (StringUtils.isNotBlank(bsId)){
Tio.bindBsId(channelContext, bsId);
}
// 给用户发送消息
WsResponse wsResponse = WsResponse.fromText("如果您看到此消息,表示您已成功连接 WebSocket 服务器", "UTF-8");
Tio.sendToUser(channelContext.tioConfig, id, wsResponse);
}
/**
* <li>当收到Opcode.BINARY消息时,执行该方法。也就是说如何你的ws是基于BINARY传输的,就会走到这个方法</li>
*
* @param wsRequest
* @param bytes
* @param channelContext
* @return 可以是WsResponse、byte[]、ByteBuffer、String或null,如果是null,框架不会回消息
* @throws Exception
* @author tanyaowu
*/
@Override
public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
return null;
}
/**
* 当收到Opcode.CLOSE时,执行该方法,业务层在该方法中一般不需要写什么逻辑,空着就好
*
* @param wsRequest
* @param bytes
* @param channelContext
* @return 可以是WsResponse、byte[]、ByteBuffer、String或null,如果是null,框架不会回消息
* @throws Exception
* @author tanyaowu
*/
@Override
public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
// 关闭连接
Tio.remove(channelContext, "WebSocket Close");
return null;
}
/**
* <li>当收到Opcode.TEXT消息时,执行该方法。也就是说如何你的ws是基于TEXT传输的,就会走到这个方法</li>
*
* @param wsRequest
* @param text
* @param channelContext
* @return 可以是WsResponse、byte[]、ByteBuffer、String或null,如果是null,框架不会回消息
* @throws Exception
* @author tanyaowu
*/
@Override
public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
WsResponse wsResponse = WsResponse.fromText("服务器已收到消息:" + text, "UTF-8");
Tio.sendToUser(channelContext.tioConfig, channelContext.userid, wsResponse);
return null;
}
}
我们实现了 IWsMsgHandler 接口,并重写了该接口的 5 个方法,这 5 个方法依次为从发送握手包,到消息收发,到断开连接等一系列过程
4、启动服务
启动成功后,可以看出 tio 的打印结果,我们可以看出服务端口为我们设置的 6789,我们便可以连接测试了
5、连接测试
• 在线测试地址
http://coolaf.com/tool/chattest
• 连接地址:
ws://127.0.0.1:6789/?id=1
• 连接成功
可以看出我们已经成功连接上了 websocket 服务器
• 发送消息
成功发送消息
注:如需根据业务处理相关消息内容可绑定bsId参数:
ws://127.0.0.1:6789/?id=1&bsId=business
根据bsId设计相关业务处理