本文首发于本博客 猫叔的博客,转载请申明出处
2019年1月3号-InChat发布V1.1.2版本
一个轻量级、高效率的支持多端(应用与硬件Iot)的异步网络应用通讯框架
v1.1.2版本使用说明
更新说明
- 捕获未注册链接断开异常,完善异常处理
- 修改项目启动流程,仿Selector启动模式
- 添加HTTP接口三个:
发送通知消息
,获取在线用户数
,获取在线用户列表
,暂不支持用户自定义HTTP接口(对于传统web API我们希望用户用自己的框架与流程) - 服务端发送通知接口改为
enum
处理 - 如果有生产需要或者个别需求,发现BUG,欢迎留言,项目会更新新的API
关于InChat的Maven依赖
- fastjson 》 1.2.53
- gson 》 2.8.5
- netty 》 4.1.32.Final
- commons-lang 》 3.5
- slf4j-log4j12 》 1.7.25
创建项目
创建一个空的Maven项目,并引入InChatMaven包,(注意,请不要使用与本项目相同的包目录)。
可能你只需要这样的Maven依赖即可
<dependencies>
<dependency>
<groupId>com.github.UncleCatMySelf</groupId>
<artifactId>InChat</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
对接InChat的接口与实现
InChat启动参数可以自配置
你只需要继承InChat的默认配置类InitNetty
即可,如下
public class MyInit extends InitNetty {
/** 自定义启动监听端口 */
@Override
public int getWebport() {
return 8090;
}
}
获取聊天消息数据
此接口与原先一样,仅修改了方法名
public class DataBaseServiceImpl implements InChatToDataBaseService {
@Override
public Boolean writeMessage(InChatMessage message) {
System.out.println(message.toString());
return true;
}
}
登录校验与群聊消息
此接口没有做过多的修改
public class VerifyServiceImpl implements InChatVerifyService {
@Override
public boolean verifyToken(String token) {
return true;
}
@Override
public JSONArray getArrayByGroupId(String groupId) {
JSONArray jsonArray = JSONArray.parseArray("[\"1111\",\"2222\",\"3333\"]");
return jsonArray;
}
}
服务端发送通知消息枚举类
此接口具有Demo模板,用户需要继承InChat框架的FromServerService
接口,同时该接口注释也有实例demo,我们需要实现一个自定义的枚举,你可以这样写:
public enum FromServerServiceImpl implements FromServerService {
//你可以自定义自己的系统消息,请以Integer-String的形式
TYPE1(1,"【系统通知】您的账号存在异常,请注意安全保密信息。"),
TYPE2(2,"【系统通知】恭喜您连续登录超过5天,奖励5积分。");
private Integer code;
private String message;
FromServerServiceImpl(Integer code, String message){
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
//实现接口的方法,遍历本枚举的code,获取对应的消息,作为系统消息发送
public String findByCode(Object code) {
Integer codes = (Integer)code;
for (FromServerServiceImpl item: FromServerServiceImpl.values()) {
if (item.code == codes){
return item.message;
}
}
return null;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
启动项目
1.1.2版本的启动项目变得异常的简单,你只需要配置启动的配置工厂即可。
public class application {
public static void main(String[] args) {
//配置你的自定义配置
ConfigFactory.initNetty = new MyInit();
//配置校验类
ConfigFactory.inChatVerifyService = new VerifyServiceImpl();
//配置消息接收处理类
ConfigFactory.inChatToDataBaseService = new DataBaseServiceImpl();
//配置服务端系统消息枚举,这里的值无所谓 TYPE1或者TYPE2或者TYPEN均可以
ConfigFactory.fromServerService = FromServerServiceImpl.TYPE1;
//启动InChat
InitServer.open();
}
}
项目效果
启动成功
DEBUG - -Dio.netty.threadLocalDirectBufferSize: 0
DEBUG - -Dio.netty.maxThreadLocalCharBufferSize: 16384
INFO - 服务端启动成功【192.168.56.1:8090】
当聊天连接未注册情况下,客户端自动断开后,服务会自动包对应的异常
INFO - [Handler:channelInactive]/192.168.56.1:8090关闭成功
ERROR - [捕获异常:NotFindLoginChannlException]-[Handler:channelInactive] 关闭未正常注册链接!
原先的
自我发送
,点对点发送
,群聊
均与原来一样
原先的接口说明可以看上一版本: v1.1.0-alpha版本使用说明
新功能添加 HTTP
新增HTTP接口三个,在你启动Inchat的时候,默认启动,对于你的其他web API并无任何影响,它是一个IM的辅助作用。本版本不支持用户自定义相关的InChat HTTP接口
获取在线用户数
- 地址:
[ip:端口]/get_size
GET - 返回值
{
"code": 200,
"data": {
"online": 1,//当前在线数
"time": "Jan 3, 2019 10:06:45 PM"//查询时间
}
}
获取在线用户标识
- 地址:
[ip:端口]/get_list
GET - 返回值
{
"code": 200,
"data": {
//返回在线用户列表
"tokens": [
"1111"
]
}
}
根据用户标签,发送系统指定消息
- 地址:
[ip:端口]/send_from_server
POST - 参数:
token
(你可以从get_list
中得到在线用户标签)、value
(你在系统中添加枚举的code
值,这里不接受字符串) - 返回值
{
"code": 400,
"data": {
"message": "通知发送成功"
}
}
(有个小BUG,返回值code应该是200)
前端相关
这里你可以来到InChat的Front-End-Testing文档夹中的chat.html。
你可以直接使用,你进需要修改对应的对接IP即可。
关于前端的js暂时还是模板
关于登录
你会看到chat.html中的登录按钮对应的js
function send(value) {
if (!window.WebSocket) {
return;
}
if (socket.readyState == WebSocket.OPEN) {
var message = {
type: "login", //与InChat对应的 不可修改
token: "1111"
}
socket.send(JSON.stringify(message));
} else {
alert("连接没有开启.");
}
}
本demo,默认登录的Token是“1111”,关于用户校验则直接返回true即可。
登录成功,返回以下内容。(不需要显示给用户看)
{"success":"true","type":"login"}
InChat不会有登录记录
发送给自己
你会看到chat.html中的登录按钮对应的js
function sendToMe(value) {
if (!window.WebSocket) {
return;
}
if (socket.readyState == WebSocket.OPEN) {
var message = {
type: "sendMe", //与InChat对应的 不可修改
value: value, //发送的内容
token: "1111" //发送用户的token
}
socket.send(JSON.stringify(message));
} else {
alert("连接没有开启.");
}
}
发送成功,InChat返回内容.(你仅需将value显示到前端即可)
{"type":"sendMe","value":"发送给自己的内容"}
InChat消息记录,你将在异步消息中接受到InChat传递给你的用户通讯消息,你可以进行对应的入库操作
{"time":"2018-12-14 10:56:24","type":"sendMe","value":"发送给自己的内容","token":"1111"}
发送给某人
你会看到chat.html中的登录按钮对应的js
function sendToOne(value) {
if (!window.WebSocket) {
return;
}
if (socket.readyState == WebSocket.OPEN) {
var message = {
type : "sendTo", //与InChat对应的 不可修改
token : "1111", //发送用户Token
value: value, //发送内容
one: "2222", //接受用户Token(唯一标识)
}
socket.send(JSON.stringify(message));
} else {
alert("连接没有开启.");
}
}
发送成功,接受的用户是否登录,你都能接受到返回信息。(value应用于自己界面展示)
{"one":"2222","type":"sendTo","value":"发送给朋友的内容"}
但是用户那边就不一样了。
登录正常在线。
{"from":"1111","type":"sendTo","value":"发送给朋友的内容"}
离线接受不到信息
InChat异步消息推送,你可以看到两种
在线: {"one":"2222","time":"2018-12-14 11:01:36","type":"sendTo","value":"发送给朋友的内容","token":"1111"}
离线: {"one":"2222","time":"2018-12-14 10:59:04","on_online":"2222","type":"sendTo","value":"发送给朋友的内容","token":"1111"}
如果出现用户发送给用户的状态是离线的,则会在消息多出on_online的字段,该字段的内容就是离线用户的Token,你可以针对性的数据入库,并在用户上线的时候,读写信息的时候,有一个未读消息的状态。
发送群聊
你会看到chat.html中的登录按钮对应的js
function sendGroup(value) {
if (!window.WebSocket) {
return;
}
if (socket.readyState == WebSocket.OPEN) {
var message = {
type: "sendGroup", //与InChat对应的 不可修改
groupId: "2", //群聊ID
token: "1111", //发送用户的Token
value: value //发送的消息
}
socket.send(JSON.stringify(message));
} else {
alert("连接没有开启.");
}
}
发送成功,本人将接受到消息
{"groupId":"2","from":"1111","type":"sendGroup","value":"大家明天一起去唱K吧"}
群组中有些人在线接受、离线不接受
在线:{"groupId":"2","from":"1111","type":"sendGroup","value":"大家明天一起去唱K吧"}
InChat异步消息入库,群组只会异步给你一个消息,你可以看到on_online中,3333用户是没有接受到信息的,所以你可以在他上线发送未读消息。
{"groupId":"2","time":"2018-12-14 11:09:17","on_online":["3333"],"type":"sendGroup","value":"大家明天一起去唱K吧","token":"1111"}
关于数据库设计
当前一版不会固定大家的数据库设计,大家可以自己自由设计,同时搭上自己的项目,构建一个附带IM的自项目。
公众号:Java猫说
现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不定期干货。