Jfinal整合t-io-websocket

392 阅读3分钟

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在线测试地址

这里我们用websocket连接来测试,可以看到已经连接成功了,我们还发了一个消息

image.png 服务端会收到这个消息

image.png

服务端主动推送消息。

ServerTioConfig serverTioConfig = ImWsServerStarter.serverTioConfig;
WsResponse wsResponse = WsResponse.fromText(message, "utf-8");
System.out.println(serverTioConfig);
Tio.sendToAll(serverTioConfig, wsResponse);

image.png 我们可以看到服务端主动推送的消息已经收到了

至此我们tio集成Jfinal就简单实现了,大家可以看看tio的官网 Tio官网

-----by天桥底下说书的