Jfinal整合t-io-websocket
一、简介
如何做一个简单的聊天功能
二、插件实现
首先引入pom文件
<tio-core.version>3.7.4.v20210808-RELEASE</tio-core.version>
<dependency>
<groupId>org.t-io</groupId>
<artifactId>tio-core</artifactId>
<version>${tio-core.version}</version>
</dependency>
<dependency>
<groupId>org.t-io</groupId>
<artifactId>tio-websocket-server</artifactId>
<version>${tio-core.version}</version>
</dependency>
我们新建一个ImWsServerStarter,通过jfinal Prop读取配置文件中的相关参数
@Data
public class ImWsServerStarter {
public static WsServerStarter wsServerStarter;
public static ServerTioConfig serverTioConfig;
private static Prop p;
static void loadConfig() {
if (p == null) {
p = PropKit.useFirstFound("tio-pro.txt", "tio-pro.txt");
}
}
/**
* 初始化
*
* @param port 端口号
* @throws Exception
*/
public static void init(int port) throws Exception {
long heartbeatTimeout = p.getLong("tio.server.heartbeatTimeout");
String name = p.get("tio.server.name");
wsServerStarter = new WsServerStarter(port, ImWsMsgHandler.me);
serverTioConfig = wsServerStarter.getServerTioConfig();
serverTioConfig.setName(name);
serverTioConfig.setServerAioListener(ImServerListener.me);
serverTioConfig.debug = p.getBoolean("tio.server.debug");
boolean statEnable = p.getBoolean("tio.server.stat-enable");
if (statEnable) {
serverTioConfig.setIpStatListener(ImWsIpStatListener.me);
serverTioConfig.ipStats.addDurations(IpStatDuration.IPSTAT_DURATIONS);
}
serverTioConfig.setHeartbeatTimeout(heartbeatTimeout);
wsServerStarter.start();
}
public static void start() throws Exception {
loadConfig();
int port = p.getInt("tio.server.port");
init(port);
}
}
新建ImWsMsgHandler处理器
public class ImWsMsgHandler implements IWsMsgHandler {
public static final ImWsMsgHandler me = new ImWsMsgHandler();
private static final Log log = Log.getLog(ImWsMsgHandler.class);
/**
* 握手时走这个方法,业务可以在这里获取cookie,request参数等
*
* @param request
* @param httpResponse
* @param channelContext
* @return
* @throws Exception
*/
@Override
public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
String userId = request.getParam("user_id");
return httpResponse;
}
/**
* 握手完成后
*
* @param httpRequest
* @param httpResponse
* @param channelContext
* @throws Exception
*/
@Override
public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
//校验用户
String userId = httpRequest.getParam("user_id");
// TUserInfo one = userService.getUserById(userId);
// if (one != null) {
// Tio.bindUser(channelContext, one.getUserId());
// log.info("绑定用户: {}", one);
// } else {
// JSONObject object = new JSONObject();
// object.put("code", 404);
// object.put("msg", "用户不存在");
// WsResponse wsResponse = WsResponse.fromText(JSON.toJSONString(object), "utf-8");
// Tio.sendToUser(channelContext.tioConfig, httpRequest.getParam("user_id"), wsResponse);
// Tio.remove(channelContext, "用户不存在");
// }
}
/**
* 字节消息(binaryType = arraybuffer)过来后会走这个方法
*/
@Override
public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
return null;
}
/**
* 链接关闭方法
*
* @param wsRequest
* @param bytes
* @param channelContext
* @return
* @throws Exception
*/
@Override
public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
Tio.remove(channelContext, "receive close flag");
return null;
}
/**
* 接受字符类型消息
*
* @param wsRequest
* @param text
* @param channelContext
* @return
* @throws Exception
*/
@Override
public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
WsSessionContext wsSessionContext = (WsSessionContext) channelContext.get();
//获取websocket握手包
HttpRequest httpRequest = wsSessionContext.getHandshakeRequest();
//处理消息
System.out.println("收到消息:" + text);
return null;
}
}
新建IpStatDuration(可选)
public interface IpStatDuration {
Long DURATION_1 = Time.MINUTE_1 * 5;
Long[] IPSTAT_DURATIONS = new Long[]{DURATION_1};
}
新建 ImWsIpStatListener
public class ImWsIpStatListener implements IpStatListener {
public static final ImWsIpStatListener me = new ImWsIpStatListener();
@Override
public void onExpired(TioConfig tioConfig, IpStat ipStat) {
//在这里把统计数据入库中或日志
}
@Override
public void onAfterConnected(ChannelContext channelContext, boolean b, boolean b1, IpStat ipStat) throws Exception {
}
@Override
public void onDecodeError(ChannelContext channelContext, IpStat ipStat) {
}
@Override
public void onAfterSent(ChannelContext channelContext, Packet packet, boolean b, IpStat ipStat) throws Exception {
}
@Override
public void onAfterDecoded(ChannelContext channelContext, Packet packet, int i, IpStat ipStat) throws Exception {
}
@Override
public void onAfterReceivedBytes(ChannelContext channelContext, int i, IpStat ipStat) throws Exception {
}
@Override
public void onAfterHandled(ChannelContext channelContext, Packet packet, IpStat ipStat, long l) throws Exception {
}
}
新建 ImServerListener 服务端监听器
public class ImServerListener extends WsServerAioListener {
public static final ImServerListener me = new ImServerListener();
private static final Log log = Log.getLog(ImServerListener.class);
@Override
public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect) throws Exception {
super.onAfterConnected(channelContext, isConnected, isReconnect);
if (log.isInfoEnabled()) {
log.info("onAfterConnected\r\n{}", channelContext);
} //绑定到群组,后面会有群发
}
@Override
public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess) throws Exception {
super.onAfterSent(channelContext, packet, isSentSuccess);
if (log.isInfoEnabled()) {
log.info("onAfterSent\r\n{}\r\n{}", packet.logstr(), channelContext);
}
}
@Override
public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) throws Exception {
super.onBeforeClose(channelContext, throwable, remark, isRemove);
if (log.isInfoEnabled()) {
log.info("onBeforeClose\r\n{}", channelContext);
}
}
@Override
public void onAfterDecoded(ChannelContext channelContext, Packet packet, int packetSize) throws Exception {
super.onAfterDecoded(channelContext, packet, packetSize);
if (log.isInfoEnabled()) {
log.info("onAfterDecoded\r\n{}\r\n{}", packet.logstr(), channelContext);
}
}
@Override
public void onAfterReceivedBytes(ChannelContext channelContext, int receivedBytes) throws Exception {
super.onAfterReceivedBytes(channelContext, receivedBytes);
if (log.isInfoEnabled()) {
log.info("onAfterReceivedBytes\r\n{}", channelContext);
}
}
@Override
public void onAfterHandled(ChannelContext channelContext, Packet packet, long cost) throws Exception {
super.onAfterHandled(channelContext, packet, cost);
if (log.isInfoEnabled()) {
log.info("onAfterHandled\r\n{}\r\n{}", packet.logstr(), channelContext);
}
}
}
新建SocketPlugin实现IPlugin的方法,我们将ImWsServerStarter启动
public class SocketPlugin implements IPlugin {
@Override
public boolean start() {
try {
ImWsServerStarter.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
}
@Override
public boolean stop() {
return false;
}
}
在Jfinal配置中加入此插件
public void configPlugin(Plugins me) {
me.add(new SocketPlugin());
}
启动项目后看到启动成功
|----------------------------------------------------------------------------------------|
| t-io site | https://www.tiocloud.com |
| t-io on gitee | https://gitee.com/tywo45/t-io |
| t-io on github | https://github.com/tywo45/t-io |
| t-io version | 3.7.4.v20210808-RELEASE |
| ---------------------------------------------------------------------------------------|
| TioConfig name | webrtc-server |
| Started at | 2022-10-24 22:44:25 |
| Listen on | 0.0.0.0:9321 |
| Main Class | com.weirdor.App |
| Jvm start time | 1785ms |
| Tio start time | 47ms |
| Pid | 7175 |
|----------------------------------------------------------------------------------------|
至此一个简单的消息处理已经完成了,接下来我们可以测试一下
这里我们用websocket连接来测试,可以看到已经连接成功了,我们还发了一个消息
服务端会收到这个消息
服务端主动推送消息。
ServerTioConfig serverTioConfig = ImWsServerStarter.serverTioConfig;
WsResponse wsResponse = WsResponse.fromText(message, "utf-8");
System.out.println(serverTioConfig);
Tio.sendToAll(serverTioConfig, wsResponse);
我们可以看到服务端主动推送的消息已经收到了
至此我们tio集成Jfinal就简单实现了,大家可以看看tio的官网 Tio官网
-----by天桥底下说书的