diff --git a/jim-client/pom.xml b/jim-client/pom.xml index 89bdb91..657683b 100644 --- a/jim-client/pom.xml +++ b/jim-client/pom.xml @@ -6,7 +6,7 @@ org.j-im jim-parent - 2.6.0.v20190114-RELEASE + 3.0.0.v20200101-RELEASE ../jim-parent/pom.xml diff --git a/jim-client/src/main/java/org/jim/client/HelloClientAioHandler.java b/jim-client/src/main/java/org/jim/client/HelloClientAioHandler.java index 046a4dd..d4483ff 100644 --- a/jim-client/src/main/java/org/jim/client/HelloClientAioHandler.java +++ b/jim-client/src/main/java/org/jim/client/HelloClientAioHandler.java @@ -3,11 +3,10 @@ package org.jim.client; import java.nio.ByteBuffer; import org.jim.common.ImConst; -import org.jim.common.Protocol; import org.tio.client.intf.ClientAioHandler; import org.tio.core.ChannelContext; import org.tio.core.GroupContext; -import org.tio.core.exception.AioDecodeException; +import org.tio.core.exception.ImDecodeException; import org.tio.core.intf.AioHandler; import org.tio.core.intf.Packet; import org.jim.common.packets.Command; @@ -52,7 +51,7 @@ public class HelloClientAioHandler implements AioHandler,ClientAioHandler } @Override - public TcpPacket decode(ByteBuffer buffer,int limit, int position, int readableLength,ChannelContext channelContext) throws AioDecodeException { + public TcpPacket decode(ByteBuffer buffer,int limit, int position, int readableLength,ChannelContext channelContext) throws ImDecodeException { TcpPacket tcpPacket = TcpServerDecoder.decode(buffer, channelContext); return tcpPacket; } diff --git a/jim-client/src/main/java/org/jim/client/HelloClientStarter.java b/jim-client/src/main/java/org/jim/client/HelloClientStarter.java index 06e082b..e7d79fb 100644 --- a/jim-client/src/main/java/org/jim/client/HelloClientStarter.java +++ b/jim-client/src/main/java/org/jim/client/HelloClientStarter.java @@ -1,7 +1,7 @@ package org.jim.client; import org.jim.common.ImConst; -import org.jim.common.ImAio; +import org.jim.common.Jim; import org.jim.common.packets.ChatBody; import org.jim.common.packets.Command; import org.jim.common.packets.LoginReqBody; @@ -63,7 +63,7 @@ public class HelloClientStarter { byte[] loginBody = new LoginReqBody("hello_client","123").toByte(); TcpPacket loginPacket = new TcpPacket(Command.COMMAND_LOGIN_REQ,loginBody); //先登录; - ImAio.send(clientChannelContext, loginPacket); + Jim.send(clientChannelContext, loginPacket); ChatBody chatBody = ChatBody.newBuilder() .setFrom("hello_client") .setTo("admin") @@ -72,6 +72,6 @@ public class HelloClientStarter { .setGroup_id("100") .setContent("Socket普通客户端消息测试!").build(); TcpPacket chatPacket = new TcpPacket(Command.COMMAND_CHAT_REQ,chatBody.toByte()); - ImAio.send(clientChannelContext, chatPacket); + Jim.send(clientChannelContext, chatPacket); } } diff --git a/jim-client/src/main/java/org/jim/client/ImClientConfig.java b/jim-client/src/main/java/org/jim/client/ImClientConfig.java new file mode 100644 index 0000000..64e1fcf --- /dev/null +++ b/jim-client/src/main/java/org/jim/client/ImClientConfig.java @@ -0,0 +1,25 @@ +package org.jim.client; + +import org.jim.common.ImHandler; +import org.jim.common.config.ImConfig; +import org.jim.common.listener.ImListener; + +/** + * @ClassName ImClientConfig + * @Description TODO + * @Author WChao + * @Date 2020/1/4 10:42 + * @Version 1.0 + **/ +public class ImClientConfig extends ImConfig { + + @Override + public ImHandler getImHandler() { + return null; + } + + @Override + public ImListener getImListener() { + return null; + } +} diff --git a/jim-common/pom.xml b/jim-common/pom.xml index 76a9eeb..5a32358 100644 --- a/jim-common/pom.xml +++ b/jim-common/pom.xml @@ -7,7 +7,7 @@ org.j-im jim-parent - 2.6.0.v20190114-RELEASE + 3.0.0.v20200101-RELEASE ../jim-parent/pom.xml @@ -76,6 +76,18 @@ net.oschina.j2cache j2cache-core + + cn.hutool + hutool-all + + + org.apache.commons + commons-collections4 + + + com.google.guava + guava + diff --git a/jim-common/src/main/java/org/jim/common/ImAio.java b/jim-common/src/main/java/org/jim/common/ImAio.java deleted file mode 100644 index 72fdbd6..0000000 --- a/jim-common/src/main/java/org/jim/common/ImAio.java +++ /dev/null @@ -1,478 +0,0 @@ -package org.jim.common; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.jim.common.cluster.ImCluster; -import org.jim.common.config.DefaultImConfigBuilder; -import org.jim.common.listener.ImBindListener; -import org.jim.common.packets.Client; -import org.jim.common.packets.User; -import org.jim.common.utils.ImKit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.tio.core.Aio; -import org.tio.core.ChannelContext; -import org.tio.core.ChannelContextFilter; -import org.tio.core.GroupContext; -import org.tio.utils.lock.SetWithLock; - -import java.util.*; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; -/** - * 版本: [1.0] - * 功能说明: - * @author : WChao 创建时间: 2017年9月22日 上午9:07:18 - */ -public class ImAio { - - public static ImConfig imConfig = null; - - private static Logger log = LoggerFactory.getLogger(ImAio.class); - /** - * 功能描述:[根据用户ID获取当前用户] - * @author:WChao 创建时间: 2017年9月18日 下午4:34:39 - * @param userId - * @return - */ - public static User getUser(String userId){ - SetWithLock userChannelContexts = ImAio.getChannelContextsByUserId(userId); - if(Objects.isNull(userChannelContexts)) { - return null; - } - ReadLock readLock = userChannelContexts.getLock().readLock(); - readLock.lock(); - try{ - Set userChannels = userChannelContexts.getObj(); - if(CollectionUtils.isEmpty(userChannels)) { - return null; - } - User user = null; - for(ChannelContext channelContext : userChannels){ - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - Client client = imSessionContext.getClient(); - user = client.getUser(); - if(user != null){ - return user; - } - } - return user; - }finally { - readLock.unlock(); - } - } - /** - * 功能描述:[根据用户ID获取当前用户所在通道集合] - * @author:WChao 创建时间: 2017年9月18日 下午4:34:39 - * @param userId - * @return - */ - public static SetWithLock getChannelContextsByUserId(String userId){ - SetWithLock channelContexts = Aio.getChannelContextsByUserid(imConfig.getGroupContext(), userId); - return channelContexts; - } - /** - * 功能描述:[获取所有用户(在线+离线)] - * @author:WChao 创建时间: 2017年9月18日 下午4:31:54 - * @return - */ - public static List getAllUser(){ - List users = new ArrayList(); - SetWithLock allChannels = Aio.getAllChannelContexts(imConfig.getGroupContext()); - if(allChannels == null) { - return users; - } - ReadLock readLock = allChannels.getLock().readLock(); - readLock.lock(); - try{ - Set userChannels = allChannels.getObj(); - if(CollectionUtils.isEmpty(userChannels)) { - return users; - } - for(ChannelContext channelContext : userChannels){ - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - Client client = imSessionContext.getClient(); - if(client != null && client.getUser() != null){ - User user = ImKit.copyUserWithoutUsers(client.getUser()); - users.add(user); - } - } - }finally { - readLock.unlock(); - } - return users; - } - /** - * 功能描述:[获取所有在线用户] - * @author:WChao 创建时间: 2017年9月18日 下午4:31:42 - * @return - */ - public static List getAllOnlineUser(){ - List users = new ArrayList(); - SetWithLock onlineChannels = Aio.getAllConnectedsChannelContexts(imConfig.getGroupContext()); - if(onlineChannels == null) { - return users; - } - ReadLock readLock = onlineChannels.getLock().readLock(); - readLock.lock(); - try{ - Set userChannels = onlineChannels.getObj(); - for(ChannelContext channelContext : userChannels){ - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - if(imSessionContext != null){ - Client client = imSessionContext.getClient(); - if(client != null && client.getUser() != null){ - User user = ImKit.copyUserWithoutUsers(client.getUser()); - users.add(user); - } - } - } - }finally { - readLock.unlock(); - } - return users; - } - /** - * 根据群组获取所有用户; - * @param group - * @return - */ - public static List getAllUserByGroup(String group){ - SetWithLock withLockChannels = Aio.getChannelContextsByGroup(imConfig.getGroupContext(), group); - if(withLockChannels == null){ - return null; - } - ReadLock readLock = withLockChannels.getLock().readLock(); - readLock.lock(); - try{ - Set channels = withLockChannels.getObj(); - if(CollectionUtils.isEmpty(channels)){ - return null; - } - List users = new ArrayList(); - Map userMaps = new HashMap(); - for(ChannelContext channelContext : channels){ - String userId = channelContext.getUserid(); - User user = getUser(userId); - if(user != null && userMaps.get(userId) == null){ - userMaps.put(userId, user); - users.add(user); - } - } - userMaps = null; - return users; - }finally{ - readLock.unlock(); - } - } - /** - * 功能描述:[发送到群组(所有不同协议端)] - * @author:WChao 创建时间: 2017年9月21日 下午3:26:57 - * @param group - * @param packet - */ - public static void sendToGroup(String group, ImPacket packet){ - if(packet.getBody() == null) { - return; - } - SetWithLock withLockChannels = Aio.getChannelContextsByGroup(imConfig.getGroupContext(), group); - if(withLockChannels == null){ - ImCluster cluster = imConfig.getCluster(); - if (cluster != null && !packet.isFromCluster()) { - cluster.clusterToGroup(imConfig.getGroupContext(), group, packet); - } - return; - } - ReadLock readLock = withLockChannels.getLock().readLock(); - readLock.lock(); - try{ - Set channels = withLockChannels.getObj(); - if(CollectionUtils.isNotEmpty(channels)){ - for(ChannelContext channelContext : channels){ - send(channelContext,packet); - } - } - }finally{ - readLock.unlock(); - ImCluster cluster = imConfig.getCluster(); - if (cluster != null && !packet.isFromCluster()) { - cluster.clusterToGroup(imConfig.getGroupContext(), group, packet); - } - } - } - /** - * 发送到指定通道; - * @param channelContext - * @param packet - */ - public static boolean send(ChannelContext channelContext,ImPacket packet){ - ImPacket respPacket = initAndSetConvertPacket(channelContext , packet); - if(respPacket == null){ - return false; - } - return Aio.send(channelContext,respPacket); - } - - /** - * 阻塞发送(确认把packet发送到对端后再返回) - * @param channelContext - * @param packet - * @return - */ - public static boolean bSend(ChannelContext channelContext , ImPacket packet){ - ImPacket respPacket = initAndSetConvertPacket(channelContext , packet); - if(respPacket == null){ - return false; - } - return Aio.bSend(channelContext,respPacket); - } - /** - * 发送到指定用户; - * @param userId - * @param packet - */ - public static void sendToUser(String userId,ImPacket packet){ - if(StringUtils.isEmpty(userId)) { - return; - } - SetWithLock toChannelContexts = getChannelContextsByUserId(userId); - if(toChannelContexts == null || toChannelContexts.size() < 1){ - ImCluster cluster = imConfig.getCluster(); - if (cluster != null && !packet.isFromCluster()) { - cluster.clusterToUser(imConfig.getGroupContext(), userId, packet); - } - return; - } - ReadLock readLock = toChannelContexts.getLock().readLock(); - readLock.lock(); - try{ - Set channels = toChannelContexts.getObj(); - for(ChannelContext channelContext : channels){ - send(channelContext, packet); - } - }finally{ - readLock.unlock(); - ImCluster cluster = imConfig.getCluster(); - if (cluster != null && !packet.isFromCluster()) { - cluster.clusterToUser(imConfig.getGroupContext(), userId, packet); - } - } - } - /** - * 发送到指定ip对应的集合 - * @param groupContext - * @param ip - * @param packet - */ - public static void sendToIp(GroupContext groupContext, String ip, ImPacket packet) { - sendToIp(groupContext, ip, packet, null); - } - - public static void sendToIp(GroupContext groupContext, String ip, ImPacket packet, ChannelContextFilter channelContextFilter) { - sendToIp(groupContext, ip, packet, channelContextFilter, false); - } - - private static Boolean sendToIp(GroupContext groupContext, String ip, ImPacket packet, ChannelContextFilter channelContextFilter, boolean isBlock) { - try{ - SetWithLock setWithLock = groupContext.ips.clients(groupContext, ip); - if (setWithLock == null) { - log.info("{}, 没有ip为[{}]的对端", groupContext.getName(), ip); - return false; - } else { - Boolean ret = sendToSet(groupContext, setWithLock, packet, channelContextFilter, isBlock); - return ret; - } - }finally{ - ImCluster cluster = imConfig.getCluster(); - if (cluster != null && !packet.isFromCluster()) { - cluster.clusterToIp(groupContext, ip, packet); - } - } - } - - public static Boolean sendToSet(GroupContext groupContext, SetWithLock setWithLock, ImPacket packet, ChannelContextFilter channelContextFilter, boolean isBlock){ - Lock lock = setWithLock.getLock().readLock(); - lock.lock(); - try { - Set sets = (Set) setWithLock.getObj(); - for (ChannelContext channelContext : sets) { - SetWithLock convertSet = new SetWithLock(new HashSet()); - convertSet.add(channelContext); - ImPacket resPacket = ImKit.ConvertRespPacket(packet, packet.getCommand(), channelContext); - Aio.sendToSet(groupContext, convertSet, resPacket, channelContextFilter); - } - }finally { - lock.unlock(); - } - return true; - } - /** - * 转换协议包同时设置Packet包信息; - * @param channelContext - * @param packet - * @return - */ - private static ImPacket initAndSetConvertPacket(ChannelContext channelContext , ImPacket packet){ - if(channelContext == null) { - return null; - } - ImPacket respPacket = ImKit.ConvertRespPacket(packet,packet.getCommand(),channelContext); - if(respPacket == null){ - log.error("转换协议包为空,请检查协议!"); - return null; - } - respPacket.setSynSeq(packet.getSynSeq()); - if(imConfig == null){ - imConfig = new DefaultImConfigBuilder().setGroupContext(channelContext.getGroupContext()).build(); - } - return respPacket; - } - /** - * 绑定用户; - * @param channelContext - * @param userId - */ - public static void bindUser(ChannelContext channelContext,String userId){ - bindUser(channelContext, userId,null); - } - /** - * 绑定用户,同时可传递监听器执行回调函数 - * @param channelContext - * @param userId - * @param bindListener(绑定监听器回调) - */ - public static void bindUser(ChannelContext channelContext,String userId,ImBindListener bindListener){ - Aio.bindUser(channelContext, userId); - if(bindListener != null){ - try { - bindListener.onAfterUserBind(channelContext, userId); - } catch (Exception e) { - log.error(e.toString(),e); - } - } - } - /** - * 解绑用户 - * @param userId - */ - public static void unbindUser(String userId){ - unbindUser(userId, null); - } - /** - * 解除绑定用户,同时可传递监听器执行回调函数 - * @param userId - * @param bindListener(解绑定监听器回调) - */ - public static void unbindUser(String userId,ImBindListener bindListener){ - Aio.unbindUser(imConfig.getGroupContext(), userId); - if(bindListener != null){ - try { - SetWithLock userChannelContexts = ImAio.getChannelContextsByUserId(userId); - if(userChannelContexts == null || userChannelContexts.size() == 0) { - return; - } - ReadLock readLock = userChannelContexts.getLock().readLock(); - readLock.lock(); - try{ - Set channels = userChannelContexts.getObj(); - for(ChannelContext channelContext : channels){ - bindListener.onAfterUserBind(channelContext, userId); - } - }finally{ - readLock.unlock(); - } - } catch (Exception e) { - log.error(e.toString(),e); - } - } - } - /** - * 绑定群组; - * @param channelContext - * @param group - */ - public static void bindGroup(ChannelContext channelContext,String group){ - bindGroup(channelContext, group,null); - } - /** - * 绑定群组,同时可传递监听器执行回调函数 - * @param channelContext - * @param group - * @param bindListener(绑定监听器回调) - */ - public static void bindGroup(ChannelContext channelContext,String group,ImBindListener bindListener){ - Aio.bindGroup(channelContext, group); - if(bindListener != null){ - try { - bindListener.onAfterGroupBind(channelContext, group); - } catch (Exception e) { - log.error(e.toString(),e); - } - } - } - /** - * 与指定群组解除绑定 - * @param userId - * @param group - */ - public static void unbindGroup(String userId,String group){ - unbindGroup(userId, group, null); - } - /** - * 与指定群组解除绑定,同时可传递监听器执行回调函数 - * @param userId - * @param group - * @param bindListener(解绑定监听器回调) - */ - public static void unbindGroup(String userId,String group,ImBindListener bindListener){ - SetWithLock userChannelContexts = ImAio.getChannelContextsByUserId(userId); - if(userChannelContexts == null || userChannelContexts.size() == 0) { - return; - } - ReadLock readLock = userChannelContexts.getLock().readLock(); - readLock.lock(); - try{ - Set channels = userChannelContexts.getObj(); - for(ChannelContext channelContext : channels){ - Aio.unbindGroup(group, channelContext); - if(bindListener != null){ - try { - bindListener.onAfterGroupUnbind(channelContext, group); - } catch (Exception e) { - log.error(e.toString(),e); - } - } - } - }finally{ - readLock.unlock(); - } - } - /** - * 移除用户, 和close方法一样,只不过不再进行重连等维护性的操作 - * @param userId - * @param remark - */ - public static void remove(String userId,String remark){ - SetWithLock userChannelContexts = getChannelContextsByUserId(userId); - if(userChannelContexts != null && userChannelContexts.size() > 0){ - ReadLock readLock = userChannelContexts.getLock().readLock(); - readLock.lock(); - try{ - Set channels = userChannelContexts.getObj(); - for(ChannelContext channelContext : channels){ - remove(channelContext, remark); - } - }finally{ - readLock.unlock(); - } - } - } - /** - * 移除指定channel, 和close方法一样,只不过不再进行重连等维护性的操作 - * @param channelContext - * @param remark - */ - public static void remove(ChannelContext channelContext,String remark){ - Aio.remove(channelContext, remark); - } -} diff --git a/jim-common/src/main/java/org/jim/common/ImChannelContext.java b/jim-common/src/main/java/org/jim/common/ImChannelContext.java new file mode 100644 index 0000000..a6b47a8 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/ImChannelContext.java @@ -0,0 +1,68 @@ +package org.jim.common; + +import org.jim.common.config.ImConfig; +import org.jim.common.protocol.IProtocol; +import org.tio.core.ChannelContext; +import org.tio.core.Node; +import org.tio.utils.prop.MapWithLockPropSupport; +import org.tio.utils.thread.pool.AbstractQueueRunnable; + +/** + * @ClassName ImChannelContext + * @Description TODO + * @Author WChao + * @Date 2020/1/5 23:40 + * @Version 1.0 + **/ +public abstract class ImChannelContext extends MapWithLockPropSupport implements ImConst{ + + protected ImConfig imConfig; + + protected ChannelContext tioChannelContext; + + public ImChannelContext(ImConfig imConfig, ChannelContext tioChannelContext) { + this.imConfig = imConfig; + this.tioChannelContext = tioChannelContext; + } + + public ImConfig getImConfig() { + return imConfig; + } + + public void setImConfig(ImConfig imConfig) { + this.imConfig = imConfig; + } + + public void setSessionContext(ImSessionContext imSessionContext){ + this.setAttribute(Key.IM_CHANNEL_SESSION_CONTEXT_KEY, imSessionContext); + } + + public ImSessionContext getSessionContext(){ + return (ImSessionContext)this.getAttribute(Key.IM_CHANNEL_SESSION_CONTEXT_KEY); + } + + public String getId() { + return tioChannelContext.getId(); + } + + public Node getClientNode(){ + return tioChannelContext.getClientNode(); + } + + public void setPacketNeededLength(Integer packetNeededLength) { + this.tioChannelContext.setPacketNeededLength(packetNeededLength); + } + + public String getUserId(){ + return tioChannelContext.userid; + } + + public void setUserId(String userId){ + tioChannelContext.setUserid(userId); + } + + public ChannelContext getTioChannelContext() { + return tioChannelContext; + } + +} diff --git a/jim-common/src/main/java/org/jim/common/ImClientGroupContext.java b/jim-common/src/main/java/org/jim/common/ImClientGroupContext.java deleted file mode 100644 index 0a17fa2..0000000 --- a/jim-common/src/main/java/org/jim/common/ImClientGroupContext.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * - */ -package org.jim.common; - -import java.util.concurrent.ThreadPoolExecutor; - -import org.tio.client.ClientGroupContext; -import org.tio.client.ReconnConf; -import org.tio.client.intf.ClientAioHandler; -import org.tio.client.intf.ClientAioListener; -import org.tio.utils.thread.pool.SynThreadPoolExecutor; - -/** - * @author WChao - * - */ -public class ImClientGroupContext extends ClientGroupContext{ - - public ImClientGroupContext(ClientAioHandler aioHandler,ClientAioListener aioListener) { - super(aioHandler, aioListener); - } - - public ImClientGroupContext(ClientAioHandler aioHandler,ClientAioListener aioListener, ReconnConf reconnConf,SynThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) { - super(aioHandler, aioListener, reconnConf, tioExecutor, groupExecutor); - } - - public ImClientGroupContext(ClientAioHandler aioHandler,ClientAioListener aioListener, ReconnConf reconnConf) { - super(aioHandler, aioListener, reconnConf); - } - -} diff --git a/jim-common/src/main/java/org/jim/common/ImConfig.java b/jim-common/src/main/java/org/jim/common/ImConfig.java deleted file mode 100644 index 4a5b593..0000000 --- a/jim-common/src/main/java/org/jim/common/ImConfig.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * - */ -package org.jim.common; - -import org.jim.common.config.Config; -import org.jim.common.http.HttpConfig; -import org.jim.common.ws.WsServerConfig; -/** - * @author WChao - * - */ -public class ImConfig extends Config{ - - /** - * http相关配置; - */ - private HttpConfig httpConfig; - /** - * WebSocket相关配置; - */ - private WsServerConfig wsServerConfig; - - public ImConfig() { - this.httpConfig = new HttpConfig(); - this.wsServerConfig = new WsServerConfig(); - } - - public ImConfig(String bindIp,Integer bindPort){ - this.bindIp = bindIp; - this.bindPort = bindPort; - this.httpConfig = new HttpConfig(); - this.wsServerConfig = new WsServerConfig(); - } - - public HttpConfig getHttpConfig() { - return httpConfig; - } - - public void setHttpConfig(HttpConfig httpConfig) { - this.httpConfig = httpConfig; - } - - public WsServerConfig getWsServerConfig() { - return wsServerConfig; - } - - public void setWsServerConfig(WsServerConfig wsServerConfig) { - this.wsServerConfig = wsServerConfig; - } - -} diff --git a/jim-common/src/main/java/org/jim/common/ImConst.java b/jim-common/src/main/java/org/jim/common/ImConst.java index b37c3fa..7af33b8 100644 --- a/jim-common/src/main/java/org/jim/common/ImConst.java +++ b/jim-common/src/main/java/org/jim/common/ImConst.java @@ -7,52 +7,296 @@ package org.jim.common; */ public interface ImConst { - public static final String AUTH_KEY = "authKey"; - - public static final int SERVER_PORT = 8888; - - public static final String CHARSET = "utf-8"; - - public static final String TO = "to"; - - public static final String CHANNEL = "channel"; - - public static final String PACKET = "packet"; - - public static final String STATUS = "status"; - - public static final String HTTP_REQUEST = "httpRequest"; - public static final String CHAT_QUEUE = "chat_queue"; - - public static final String STORE = "store"; - - public static final String PUSH = "push"; - - public static final String CHAT = "chat"; - - public static final String GROUP = "group"; - - public static final String USER = "user"; - - public static final String TERMINAL = "terminal"; - - public static final String INFO = "info"; - - public static final String FRIENDS = "friends"; - - public static final String ONLINE = "online"; - - public static final String OFFLINE = "offline"; - - public static final String ON = "on"; - - public static final String OFF = "off"; - - public static final String JIM = "JIM"; - - public static final String CONVERTER = "converter"; + interface Key{ + String IM_CHANNEL_CONTEXT_KEY = "im_channel_context_key"; + String IM_CHANNEL_SESSION_CONTEXT_KEY = "im_channel_session_context_key"; + /** + * 存放HttpConfig + */ + String HTTP_SERVER_CONFIG = "JIM_HTTP_SERVER_CONFIG"; + } - public static final String BASE_ASYNC_CHAT_MESSAGE_PROCESSOR = "base_async_chat_message_processor"; + interface Topic{ + String REDIS_CLUSTER_TOPIC_SUFFIX = "REDIS_"; + String JIM_CLUSTER_TOPIC = "JIM_CLUSTER"; + } + + interface Protocol{ + /** + * 心跳字节 + */ + byte HEARTBEAT_BYTE = -128; + + /** + * 握手字节 + */ + byte HANDSHAKE_BYTE = -127; + + /** + * 协议版本号 + */ + byte VERSION = 0x01; + + String WEB_SOCKET = "ws"; + + String HTTP = "http"; + + String TCP = "tcp"; + + String COOKIE_NAME_FOR_SESSION = "jim-s"; + /** + * 消息体最多为多少,只支持多少M数据 + */ + int MAX_LENGTH_OF_BODY = (int) (1024 * 1024 * 2.1); + + /** + * 消息头最少为多少个字节,1+1+2+(2+4) + */ + int LEAST_HEADER_LENGTH = 4; + + /** + * 加密标识位mask,1为加密,否则不加密 + */ + byte FIRST_BYTE_MASK_ENCRYPT = -128; + + /** + * 压缩标识位mask,1为压缩,否则不压缩 + */ + byte FIRST_BYTE_MASK_COMPRESS = 0B01000000; + + /** + * 是否有同步序列号标识位mask,如果有同步序列号,则消息头会带有同步序列号,否则不带 + */ + byte FIRST_BYTE_MASK_HAS_SYNSEQ = 0B00100000; + + /** + * 是否是用4字节来表示消息体的长度 + */ + byte FIRST_BYTE_MASK_4_BYTE_LENGTH = 0B00010000; + + /** + * 版本号mask + */ + byte FIRST_BYTE_MASK_VERSION = 0B00001111; + } + + interface Http{ + /** + * 请求体的格式 + * @author wchao + * 2017年6月28日 上午10:03:12 + */ + enum RequestBodyFormat { + URLENCODED, MULTIPART, TEXT + } + + /** + *Accept-Language : zh-CN,zh;q=0.8 + Sec-WebSocket-Version : 13 + Sec-WebSocket-Extensions : permessage-deflate; client_max_window_bits + Upgrade : websocket + Host : t-io.org:9321 + Accept-Encoding : gzip, deflate, sdch + User-Agent : Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 + Origin : http://www.t-io.org:9292 + Sec-WebSocket-Key : kmCL2C7q9vtNSMyHpft7lw== + Connection : Upgrade + Cache-Control : no-cache + Pragma : no-cache + * @author wchao + * 2017年5月27日 下午2:11:57 + */ + interface RequestHeaderKey { + String Cookie = "Cookie".toLowerCase();//Cookie: $Version=1; Skin=new; + String Origin = "Origin".toLowerCase(); //http://127.0.0.1 + String Sec_WebSocket_Key = "Sec-WebSocket-Key".toLowerCase(); //2GFwqJ1Z37glm62YKKLUeA== + String Cache_Control = "Cache-Control".toLowerCase(); //no-cache + String Connection = "Connection".toLowerCase(); //Upgrade, keep-alive + String User_Agent = "User-Agent".toLowerCase(); //Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3088.3 Safari/537.36 + String Sec_WebSocket_Version = "Sec-WebSocket-Version".toLowerCase(); //13 + String Host = "Host".toLowerCase(); //127.0.0.1:9321 + String Pragma = "Pragma".toLowerCase(); //no-cache + String Accept_Encoding = "Accept-Encoding".toLowerCase(); //gzip, deflate, br + String Accept_Language = "Accept-Language".toLowerCase(); //zh-CN,zh;q=0.8,en;q=0.6 + String Upgrade = "Upgrade".toLowerCase(); //websocket + String Sec_WebSocket_Extensions = "Sec-WebSocket-Extensions".toLowerCase(); //permessage-deflate; client_max_window_bits + String Content_Length = "Content-Length".toLowerCase(); //65 + String Content_Type = "Content-Type".toLowerCase();// : 【application/x-www-form-urlencoded】【application/x-www-form-urlencoded; charset=UTF-8】【multipart/form-data; boundary=----WebKitFormBoundaryuwYcfA2AIgxqIxA0 】 + String If_Modified_Since = "If-Modified-Since".toLowerCase(); //与Last-Modified配合 + /** + * 值为XMLHttpRequest则为Ajax + */ + String X_Requested_With = "X-Requested-With".toLowerCase();//XMLHttpRequest + } + + /** + * + * @author wchao + * 2017年6月27日 下午8:23:58 + */ + interface RequestHeaderValue { + interface Connection { + String keep_alive = "keep-alive".toLowerCase(); + String Upgrade = "Upgrade".toLowerCase(); + String close = "close".toLowerCase(); + } + + //application/x-www-form-urlencoded、multipart/form-data、text/plain + interface Content_Type { + /** + * 普通文本,一般会是json或是xml + */ + String text_plain = "text/plain".toLowerCase(); + /** + * 文件上传 + */ + String multipart_form_data = "multipart/form-data".toLowerCase(); + /** + * 普通的key-value + */ + String application_x_www_form_urlencoded = "application/x-www-form-urlencoded".toLowerCase(); + } + } + + interface ResponseHeaderKey { + String Set_Cookie = "Set-Cookie".toLowerCase(); //Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 + String Content_Length = "Content-Length".toLowerCase(); //65 + + String Connection = "Connection".toLowerCase(); //Upgrade, keep-alive + String Keep_Alive = "Keep-Alive".toLowerCase(); //Keep-Alive:timeout=20 + String Sec_WebSocket_Accept = "Sec-WebSocket-Accept".toLowerCase(); + String Upgrade = "Upgrade".toLowerCase(); + + /** + * Content-Disposition: attachment;filename=FileName.txt + * 文件下载 + */ + String Content_disposition = "Content-disposition".toLowerCase(); + /** + * 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。 + * 利用gzip压缩文档能够显著地减少HTML文档的下载时间。 + * Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。 + * 因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip, + * 为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。 + */ + String Content_Encoding = "Content-Encoding".toLowerCase(); + /** + * 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。 + * 由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。 + */ + String Content_Type = "Content-Type".toLowerCase(); + /** + * 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。 + */ + String Date = "Date".toLowerCase(); + /** + * 应该在什么时候认为文档已经过期,从而不再缓存它? + */ + String Expires = "Expires".toLowerCase(); + /** + * 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET, + * 只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。 + */ + String Last_Modified = "Last-Modified".toLowerCase(); + /** + * 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。 + */ + String Location = "Location".toLowerCase(); + /** + * 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 + 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。 + + 注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。 + + 注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。 + */ + String Refresh = "Refresh".toLowerCase(); + /** + * 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。 + */ + String Server = "Server".toLowerCase(); + + /** + * + */ + String Access_Control_Allow_Origin = "Access-Control-Allow-Origin".toLowerCase(); //value: * + + /** + * + */ + String Access_Control_Allow_Headers = "Access-Control-Allow-Headers".toLowerCase(); //value: x-requested-with,content-type + + /** + * 是否是从缓存中获取的数据,tio-httpserver特有的头部信息 + */ + String tio_from_cache = "tio-from-cache"; + } + + /** + * + * @author wchao + * 2017年6月27日 下午8:24:02 + */ + interface ResponseHeaderValue { + interface Connection { + String keep_alive = "keep-alive".toLowerCase(); + String Upgrade = "Upgrade".toLowerCase(); + String close = "close".toLowerCase(); + } + } + + /** + * + */ + String SERVER_INFO = "jim-http-server/0.0.1"; + + /** + * 默认规定连接到本服务器的客户端统一用utf-8 + */ + String CHARSET_NAME = "utf-8"; + } + + String AUTH_KEY = "authKey"; + + int SERVER_PORT = 8888; + + String CHARSET = "utf-8"; + + String TO = "to"; + + String CHANNEL = "channel"; + + String PACKET = "packet"; + + String STATUS = "status"; + + String HTTP_REQUEST = "httpRequest"; + + String STORE = "store"; + + String PUSH = "push"; + + String CHAT = "chat"; + + String GROUP = "group"; + + String USER = "user"; + + String TERMINAL = "terminal"; + + String INFO = "info"; + + String FRIENDS = "friends"; + + String ONLINE = "online"; + + String OFFLINE = "offline"; + + String JIM = "JIM"; + + String CONVERTER = "converter"; + + String BASE_ASYNC_CHAT_MESSAGE_PROCESSOR = "base_async_chat_message_processor"; } diff --git a/jim-common/src/main/java/org/jim/common/ImDecoder.java b/jim-common/src/main/java/org/jim/common/ImDecoder.java index 78a018d..46d5a27 100644 --- a/jim-common/src/main/java/org/jim/common/ImDecoder.java +++ b/jim-common/src/main/java/org/jim/common/ImDecoder.java @@ -5,10 +5,8 @@ package org.jim.common; import java.nio.ByteBuffer; +import org.jim.common.exception.ImDecodeException; import org.tio.core.ChannelContext; -import org.tio.core.exception.AioDecodeException; - - /** * 版本: [1.0] * 功能说明: @@ -16,5 +14,5 @@ import org.tio.core.exception.AioDecodeException; */ public interface ImDecoder { - public ImPacket decode(ByteBuffer buffer, ChannelContext channelContext) throws AioDecodeException; + public ImPacket decode(ByteBuffer buffer, ChannelContext channelContext) throws ImDecodeException; } diff --git a/jim-common/src/main/java/org/jim/common/ImHandler.java b/jim-common/src/main/java/org/jim/common/ImHandler.java new file mode 100644 index 0000000..4698b55 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/ImHandler.java @@ -0,0 +1,47 @@ +package org.jim.common; + +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImDecodeException; +import org.jim.common.exception.ImException; +import java.nio.ByteBuffer; + +/** + * @ClassName ImHandler + * @Description TODO + * @Author WChao + * @Date 2020/1/6 2:09 + * @Version 1.0 + **/ +public interface ImHandler { + /** + * 根据ByteBuffer解码成业务需要的Packet对象. + * 如果收到的数据不全,导致解码失败,请返回null,在下次消息来时框架层会自动续上前面的收到的数据 + * @param buffer 参与本次希望解码的ByteBuffer + * @param limit ByteBuffer的limit + * @param position ByteBuffer的position,不一定是0哦 + * @param readableLength ByteBuffer参与本次解码的有效数据(= limit - position) + * @param imChannelContext + * @return + * @throws ImDecodeException + */ + ImPacket decode(ByteBuffer buffer, int limit, int position, int readableLength, ImChannelContext imChannelContext) throws ImDecodeException; + + /** + * 编码 + * @param imPacket + * @param imConfig + * @param imChannelContext + * @return + * @author: WChao + */ + ByteBuffer encode(ImPacket imPacket, ImConfig imConfig, ImChannelContext imChannelContext); + + /** + * 处理消息包 + * @param imPacket + * @param imChannelContext + * @throws ImException + * @author: WChao + */ + void handler(ImPacket imPacket, ImChannelContext imChannelContext) throws ImException; +} diff --git a/jim-common/src/main/java/org/jim/common/ImPacket.java b/jim-common/src/main/java/org/jim/common/ImPacket.java index 66a2234..b6d3792 100644 --- a/jim-common/src/main/java/org/jim/common/ImPacket.java +++ b/jim-common/src/main/java/org/jim/common/ImPacket.java @@ -1,5 +1,6 @@ package org.jim.common; +import org.tio.core.ChannelContext; import org.tio.core.intf.Packet; import org.jim.common.packets.Command; @@ -8,7 +9,7 @@ import org.jim.common.packets.Command; * @author WChao * */ -public class ImPacket extends Packet +public class ImPacket extends Packet implements ImConst { private static final long serialVersionUID = 2000118564569232098L; /** @@ -23,6 +24,8 @@ public class ImPacket extends Packet * 消息命令; */ private Command command; + + protected ImChannelContext imChannelContext; public ImPacket(){} @@ -109,7 +112,7 @@ public class ImPacket extends Packet */ public int calcHeaderLength(boolean is4byteLength) { - int ret = Protocol.LEAST_HEADER_LENGHT; + int ret = Protocol.LEAST_HEADER_LENGTH; if (is4byteLength) { ret += 2; @@ -165,4 +168,11 @@ public class ImPacket extends Packet this.status = status; } + public ImChannelContext getImChannelContext() { + return imChannelContext; + } + + public void setImChannelContext(ImChannelContext imChannelContext) { + this.imChannelContext = imChannelContext; + } } diff --git a/jim-common/src/main/java/org/jim/common/ImSessionContext.java b/jim-common/src/main/java/org/jim/common/ImSessionContext.java index 3ea9e03..435a1d1 100644 --- a/jim-common/src/main/java/org/jim/common/ImSessionContext.java +++ b/jim-common/src/main/java/org/jim/common/ImSessionContext.java @@ -2,15 +2,13 @@ package org.jim.common; import org.jim.common.packets.Client; import org.tio.monitor.RateLimiterWrap; -import org.tio.server.intf.ServerAioHandler; /** * * @author wchao * */ -public class ImSessionContext extends SessionContext -{ +public class ImSessionContext { /** * 消息请求频率控制器 */ @@ -19,21 +17,19 @@ public class ImSessionContext extends SessionContext protected Client client = null; protected String token = null; + + protected ImChannelContext imChannelContext; + + protected String id; + /** - * 通道所属协议处理器; - */ - private ServerAioHandler protocolHandler; - - /** - * - * - * @author: wchao + * @author: WChao * 2017年2月21日 上午10:27:54 - * */ - public ImSessionContext() - { - + public ImSessionContext(){} + + public ImSessionContext(ImChannelContext imChannelContext){ + this.imChannelContext = imChannelContext; } /** * @return the client @@ -81,12 +77,19 @@ public class ImSessionContext extends SessionContext this.requestRateLimiter = requestRateLimiter; } - public ServerAioHandler getProtocolHandler() { - return protocolHandler; + public ImChannelContext getImChannelContext() { + return imChannelContext; } - public ImSessionContext setProtocolHandler(ServerAioHandler protocolHandler) { - this.protocolHandler = protocolHandler; - return this; + public void setImChannelContext(ImChannelContext imChannelContext) { + this.imChannelContext = imChannelContext; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; } } diff --git a/jim-common/src/main/java/org/jim/common/ImStatus.java b/jim-common/src/main/java/org/jim/common/ImStatus.java index b818564..bb0802a 100644 --- a/jim-common/src/main/java/org/jim/common/ImStatus.java +++ b/jim-common/src/main/java/org/jim/common/ImStatus.java @@ -39,7 +39,7 @@ public enum ImStatus implements Status{ private String text; - private ImStatus(int status, String description, String text) { + ImStatus(int status, String description, String text) { this.status = status; this.description = description; this.text = text; diff --git a/jim-common/src/main/java/org/jim/common/Jim.java b/jim-common/src/main/java/org/jim/common/Jim.java new file mode 100644 index 0000000..2016ab6 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/Jim.java @@ -0,0 +1,200 @@ +package org.jim.common; + +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImException; +import org.jim.common.listener.ImUserListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.tio.core.Tio; +import org.tio.core.ChannelContext; +import org.tio.core.ChannelContextFilter; +import org.tio.core.TioConfig; +import org.tio.utils.lock.SetWithLock; +import java.util.Set; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +/** + * 版本: [1.0] + * 功能说明: + * @author : WChao 创建时间: 2017年9月22日 上午9:07:18 + */ +public class Jim { + + public static ImConfig imConfig = ImConfig.Global.get(); + + private static Logger log = LoggerFactory.getLogger(Jim.class); + + /** + * 功能描述:[发送到群组(所有不同协议端)] + * @author:WChao 创建时间: 2017年9月21日 下午3:26:57 + * @param group + * @param packet + */ + public static void sendToGroup(String group, ImPacket packet){ + Tio.sendToGroup(imConfig.getTioConfig(), group, packet); + } + /** + * 发送到指定通道; + * @param channelContext + * @param imPacket + */ + public static boolean send(ImChannelContext channelContext, ImPacket imPacket){ + if(channelContext == null){ + return false; + } + return Tio.send(channelContext.getTioChannelContext(),imPacket); + } + + /** + * 阻塞发送(确认把packet发送到对端后再返回) + * @param channelContext + * @param packet + * @return + */ + public static boolean bSend(ImChannelContext channelContext , ImPacket packet){ + if(channelContext == null){ + return false; + } + return Tio.bSend(channelContext.getTioChannelContext(), packet); + } + /** + * 发送到指定用户; + * @param userId + * @param packet + */ + public static void sendToUser(String userId,ImPacket packet){ + Tio.sendToUser(imConfig.getTioConfig(), userId, packet); + } + /** + * 发送到指定ip对应的集合 + * @param ip + * @param packet + */ + public static void sendToIp( String ip, ImPacket packet) { + sendToIp(ip, packet, null); + } + + public static void sendToIp(String ip, ImPacket packet, ChannelContextFilter channelContextFilter) { + Tio.sendToIp(imConfig.getTioConfig(), ip, packet, channelContextFilter); + } + + public static void sendToSet(SetWithLock setWithLock, ImPacket packet, ChannelContextFilter channelContextFilter, boolean isBlock){ + Tio.sendToSet(imConfig.getTioConfig(),setWithLock,packet,channelContextFilter); + } + /** + * 绑定用户 + * @param imChannelContext + * @param userId + */ + public static void bindUser(ImChannelContext imChannelContext,String userId){ + Tio.bindUser(imChannelContext.getTioChannelContext(), userId); + ImUserListener imUserListener = imConfig.getImUserListener(); + if(imUserListener != null){ + try { + imUserListener.onAfterBind(imChannelContext, userId); + }catch (ImException e){ + log.error(e.toString(),e); + } + } + } + /** + * 解除userId的绑定。一般用于多地登录,踢掉前面登录的场景 + * @param userId + * @author: WChao + */ + public static void unbindUser(String userId){ + TioConfig tioConfig = imConfig.getTioConfig(); + Tio.unbindUser(tioConfig, userId); + ImUserListener imUserListener = imConfig.getImUserListener(); + if(imUserListener == null){ + return; + } + SetWithLock userChannels = Tio.getByUserid(tioConfig, userId); + Set channelContexts = userChannels.getObj(); + if(!channelContexts.isEmpty()){ + ReadLock readLock = userChannels.getLock().readLock(); + try{ + readLock.lock(); + for (ChannelContext channelContext : channelContexts){ + ImChannelContext imChannelContext = (ImChannelContext)channelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY); + imUserListener.onAfterUnbind(imChannelContext, userId); + } + } catch (ImException e) { + log.error(e.toString(), e); + }finally { + readLock.unlock(); + } + } + } + /** + * 绑定群组 + * @param imChannelContext + * @param group + */ + public static void bindGroup(ImChannelContext imChannelContext, String group){ + Tio.bindGroup(imChannelContext.getTioChannelContext(), group); + } + /** + * 与指定组解除绑定关系 + * @param groupId + * @param imChannelContext + * @author WChao + */ + public static void unbindGroup(String groupId, ImChannelContext imChannelContext){ + Tio.unbindGroup(groupId, imChannelContext.getTioChannelContext()); + } + /** + * 与所有组解除解绑关系 + * @param imChannelContext + * @author WChao + */ + public static void unbindGroup(ImChannelContext imChannelContext){ + Tio.unbindGroup(imChannelContext.getTioChannelContext()); + } + /** + * 将制定用户从指定群组解除绑定 + * @param userId + * @param group + */ + public static void unbindGroup(String userId,String group){ + Tio.unbindGroup(imConfig.getTioConfig(),userId,group); + } + /** + * 移除用户, 和close方法一样,只不过不再进行重连等维护性的操作 + * @param userId + * @param remark + */ + public static void remove(String userId,String remark){ + SetWithLock userChannelContexts = Tio.getByUserid(imConfig.getTioConfig(), userId); + Set channels = userChannelContexts.getObj(); + if(channels.isEmpty()){ + return; + } + ReadLock readLock = userChannelContexts.getLock().readLock(); + try{ + readLock.lock(); + for(ChannelContext channelContext : channels){ + ImChannelContext imChannelContext = (ImChannelContext)channelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY); + remove(imChannelContext, remark); + } + }finally{ + readLock.unlock(); + } + } + /** + * 移除指定channel, 和close方法一样,只不过不再进行重连等维护性的操作 + * @param imChannelContext + * @param remark + */ + public static void remove(ImChannelContext imChannelContext, String remark){ + Tio.remove(imChannelContext.getTioChannelContext(), remark); + } + /** + * 关闭连接 + * @param imChannelContext + * @param remark + */ + public static void close(ImChannelContext imChannelContext, String remark){ + Tio.close(imChannelContext.getTioChannelContext(), remark); + } + +} diff --git a/jim-common/src/main/java/org/jim/common/Protocol.java b/jim-common/src/main/java/org/jim/common/Protocol.java deleted file mode 100644 index 7590e11..0000000 --- a/jim-common/src/main/java/org/jim/common/Protocol.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.jim.common; - -public interface Protocol { - /** - * 心跳字节 - */ - public static final byte HEARTBEAT_BYTE = -128; - - /** - * 握手字节 - */ - public static final byte HANDSHAKE_BYTE = -127; - - /** - * 协议版本号 - */ - public final static byte VERSION = 0x01; - - public final static String WEBSOCKET = "ws"; - - public final static String HTTP = "http"; - - public final static String TCP = "tcp"; - - public static final String COOKIE_NAME_FOR_SESSION = "jim-s"; - /** - * 消息体最多为多少 - */ - public static final int MAX_LENGTH_OF_BODY = (int) (1024 * 1024 * 2.1); //只支持多少M数据 - - /** - * 消息头最少为多少个字节 - */ - public static final int LEAST_HEADER_LENGHT = 4;//1+1+2 + (2+4) - - /** - * 加密标识位mask,1为加密,否则不加密 - */ - public static final byte FIRST_BYTE_MASK_ENCRYPT = -128; - - /** - * 压缩标识位mask,1为压缩,否则不压缩 - */ - public static final byte FIRST_BYTE_MASK_COMPRESS = 0B01000000; - - /** - * 是否有同步序列号标识位mask,如果有同步序列号,则消息头会带有同步序列号,否则不带 - */ - public static final byte FIRST_BYTE_MASK_HAS_SYNSEQ = 0B00100000; - - /** - * 是否是用4字节来表示消息体的长度 - */ - public static final byte FIRST_BYTE_MASK_4_BYTE_LENGTH = 0B00010000; - - /** - * 版本号mask - */ - public static final byte FIRST_BYTE_MASK_VERSION = 0B00001111; -} \ No newline at end of file diff --git a/jim-common/src/main/java/org/jim/common/SessionContext.java b/jim-common/src/main/java/org/jim/common/SessionContext.java deleted file mode 100644 index 0eaa9d0..0000000 --- a/jim-common/src/main/java/org/jim/common/SessionContext.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - */ -package org.jim.common; - -/** - * 版本: [1.0] - * 功能说明: - * 作者: WChao 创建时间: 2017年8月3日 上午9:15:37 - */ -public class SessionContext { - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/jim-common/src/main/java/org/jim/common/Status.java b/jim-common/src/main/java/org/jim/common/Status.java index 5d083d1..40277ba 100644 --- a/jim-common/src/main/java/org/jim/common/Status.java +++ b/jim-common/src/main/java/org/jim/common/Status.java @@ -10,7 +10,7 @@ package org.jim.common; */ public interface Status { - public int getCode(); + int getCode(); - public String getMsg(); + String getMsg(); } diff --git a/jim-common/src/main/java/org/jim/common/cache/redis/RedisConfigurationFactory.java b/jim-common/src/main/java/org/jim/common/cache/redis/RedisConfigurationFactory.java index 15932e4..74632b8 100644 --- a/jim-common/src/main/java/org/jim/common/cache/redis/RedisConfigurationFactory.java +++ b/jim-common/src/main/java/org/jim/common/cache/redis/RedisConfigurationFactory.java @@ -8,7 +8,7 @@ import java.io.InputStream; import java.net.URL; import java.util.Properties; -import org.jim.common.ImAio; +import org.jim.common.Jim; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** @@ -87,7 +87,7 @@ public class RedisConfigurationFactory { url = standardClassloader.getResource(DEFAULT_CLASSPATH_CONFIGURATION_FILE); } if (url == null) { - url = ImAio.class.getResource(DEFAULT_CLASSPATH_CONFIGURATION_FILE); + url = Jim.class.getResource(DEFAULT_CLASSPATH_CONFIGURATION_FILE); } if (url != null) { LOG.debug("Configuring redis from jim.properties found in the classpath: " + url); diff --git a/jim-common/src/main/java/org/jim/common/cluster/ICluster.java b/jim-common/src/main/java/org/jim/common/cluster/ICluster.java index 9ea3971..0ddc738 100644 --- a/jim-common/src/main/java/org/jim/common/cluster/ICluster.java +++ b/jim-common/src/main/java/org/jim/common/cluster/ICluster.java @@ -4,7 +4,6 @@ package org.jim.common.cluster; import org.jim.common.ImPacket; -import org.tio.core.GroupContext; /** * @@ -12,8 +11,8 @@ import org.tio.core.GroupContext; * */ public interface ICluster { - public void clusterToUser(GroupContext groupContext, String userid,ImPacket packet); - public void clusterToGroup(GroupContext groupContext, String group,ImPacket packet); - public void clusterToIp(GroupContext groupContext, String ip,ImPacket packet); - public void clusterToChannelId(GroupContext groupContext, String channelId,ImPacket packet); + public void clusterToUser(String userId,ImPacket packet); + public void clusterToGroup(String group,ImPacket packet); + public void clusterToIp(String ip,ImPacket packet); + public void clusterToChannelId(String channelId,ImPacket packet); } diff --git a/jim-common/src/main/java/org/jim/common/cluster/ImClusterConfig.java b/jim-common/src/main/java/org/jim/common/cluster/ImClusterConfig.java index e23f883..9ef1d87 100644 --- a/jim-common/src/main/java/org/jim/common/cluster/ImClusterConfig.java +++ b/jim-common/src/main/java/org/jim/common/cluster/ImClusterConfig.java @@ -1,7 +1,5 @@ package org.jim.common.cluster; -import org.tio.core.GroupContext; - /** * * @author WChao @@ -30,7 +28,7 @@ public abstract class ImClusterConfig { */ private boolean cluster4all = true; - protected GroupContext groupContext = null; + //protected GroupContext groupContext = null; public abstract void send(ImClusterVo imClusterVo); public abstract void sendAsyn(ImClusterVo imClusterVo); diff --git a/jim-common/src/main/java/org/jim/common/cluster/redis/RedisCluster.java b/jim-common/src/main/java/org/jim/common/cluster/redis/RedisCluster.java index 995493a..1cf8369 100644 --- a/jim-common/src/main/java/org/jim/common/cluster/redis/RedisCluster.java +++ b/jim-common/src/main/java/org/jim/common/cluster/redis/RedisCluster.java @@ -6,7 +6,6 @@ package org.jim.common.cluster.redis; import org.jim.common.ImPacket; import org.jim.common.cluster.ImCluster; import org.jim.common.cluster.ImClusterVo; -import org.tio.core.GroupContext; /** * @author WChao * @@ -18,7 +17,7 @@ public class RedisCluster extends ImCluster{ } @Override - public void clusterToUser(GroupContext groupContext, String userid,ImPacket packet) { + public void clusterToUser( String userid,ImPacket packet) { if (clusterConfig.isCluster4user()) { ImClusterVo imClusterVo = new ImClusterVo(packet); imClusterVo.setUserid(userid); @@ -27,7 +26,7 @@ public class RedisCluster extends ImCluster{ } @Override - public void clusterToGroup(GroupContext groupContext, String group,ImPacket packet) { + public void clusterToGroup(String group,ImPacket packet) { if(clusterConfig.isCluster4group()){ ImClusterVo imClusterVo = new ImClusterVo(packet); imClusterVo.setGroup(group); @@ -36,7 +35,7 @@ public class RedisCluster extends ImCluster{ } @Override - public void clusterToIp(GroupContext groupContext, String ip,ImPacket packet) { + public void clusterToIp(String ip,ImPacket packet) { if(clusterConfig.isCluster4ip()){ ImClusterVo imClusterVo = new ImClusterVo(packet); imClusterVo.setIp(ip); @@ -45,7 +44,7 @@ public class RedisCluster extends ImCluster{ } @Override - public void clusterToChannelId(GroupContext groupContext, String channelId,ImPacket packet) { + public void clusterToChannelId(String channelId,ImPacket packet) { if(clusterConfig.isCluster4channelId()){ ImClusterVo imClusterVo = new ImClusterVo(packet); imClusterVo.setChannelId(channelId); diff --git a/jim-common/src/main/java/org/jim/common/cluster/redis/RedisClusterConfig.java b/jim-common/src/main/java/org/jim/common/cluster/redis/RedisClusterConfig.java index 1cbd966..16e4bfb 100644 --- a/jim-common/src/main/java/org/jim/common/cluster/redis/RedisClusterConfig.java +++ b/jim-common/src/main/java/org/jim/common/cluster/redis/RedisClusterConfig.java @@ -7,7 +7,8 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImAio; +import org.jim.common.ImConst; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.cluster.ImClusterConfig; import org.jim.common.cluster.ImClusterVo; @@ -16,8 +17,7 @@ import org.redisson.api.RedissonClient; import org.redisson.api.listener.MessageListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.Aio; -import org.tio.core.GroupContext; +import org.tio.core.Tio; import org.tio.utils.json.Json; /** @@ -25,12 +25,10 @@ import org.tio.utils.json.Json; * @author WChao * */ -public class RedisClusterConfig extends ImClusterConfig { +public class RedisClusterConfig extends ImClusterConfig implements ImConst { private static Logger log = LoggerFactory.getLogger(RedisClusterConfig.class); - public static final String IM_CLUSTER_TOPIC = "JIM_CLUSTER"; - private String topicSuffix; private String topic; @@ -48,19 +46,15 @@ public class RedisClusterConfig extends ImClusterConfig { * J-IM内置的集群是用redis的topic来实现的,所以不同groupContext就要有一个不同的topicSuffix * @param topicSuffix 不同类型的groupContext就要有一个不同的topicSuffix * @param redisson - * @param groupContext * @return * @author: WChao */ - public static RedisClusterConfig newInstance(String topicSuffix, RedissonClient redisson, GroupContext groupContext) { + public static RedisClusterConfig newInstance(String topicSuffix, RedissonClient redisson) { if (redisson == null) { throw new RuntimeException(RedissonClient.class.getSimpleName() + "不允许为空"); } - if (groupContext == null) { - throw new RuntimeException("GroupContext不允许为空"); - } - RedisClusterConfig me = new RedisClusterConfig(topicSuffix, redisson, groupContext); + RedisClusterConfig me = new RedisClusterConfig(topicSuffix, redisson); me.rtopic = redisson.getTopic(me.topic); me.rtopic.addListener(new MessageListener() { @Override @@ -86,53 +80,40 @@ public class RedisClusterConfig extends ImClusterConfig { //发送给所有 boolean isToAll = imClusterVo.isToAll(); if (isToAll) { - // for (GroupContext groupContext : me.groupContext) { - Aio.sendToAll(groupContext, packet); - // } - //return; + Tio.sendToAll(null, packet); } //发送给指定组 String group = imClusterVo.getGroup(); if (StringUtils.isNotBlank(group)) { - ImAio.sendToGroup(group, packet); - //return; + Jim.sendToGroup(group, packet); } //发送给指定用户 String userid = imClusterVo.getUserid(); if (StringUtils.isNotBlank(userid)) { - // for (GroupContext groupContext : me.groupContext) { - ImAio.sendToUser(userid, packet); - // } - //return; + Jim.sendToUser(userid, packet); } //发送给指定token String token = imClusterVo.getToken(); if (StringUtils.isNotBlank(token)) { - // for (GroupContext groupContext : me.groupContext) { - Aio.sendToToken(me.groupContext, token, packet); - // } - //return; + //Tio.sendToToken(me.groupContext, token, packet); } //发送给指定ip String ip = imClusterVo.getIp(); if (StringUtils.isNotBlank(ip)) { - // for (GroupContext groupContext : me.groupContext) { - ImAio.sendToIp(me.groupContext, ip, packet); - // } - //return; + //Jim.sendToIp(me.groupContext, ip, packet); } } }); return me; } - private RedisClusterConfig(String topicSuffix, RedissonClient redisson, GroupContext groupContext) { + private RedisClusterConfig(String topicSuffix, RedissonClient redisson) { this.setTopicSuffix(topicSuffix); this.setRedisson(redisson); - this.groupContext = groupContext; + //this.groupContext = groupContext; } public String getTopicSuffix() { return topicSuffix; @@ -140,8 +121,7 @@ public class RedisClusterConfig extends ImClusterConfig { public void setTopicSuffix(String topicSuffix) { this.topicSuffix = topicSuffix; - this.topic = topicSuffix + IM_CLUSTER_TOPIC; - + this.topic = topicSuffix + Topic.JIM_CLUSTER_TOPIC; } public String getTopic() { diff --git a/jim-common/src/main/java/org/jim/common/config/Config.java b/jim-common/src/main/java/org/jim/common/config/Config.java deleted file mode 100644 index 829c6f0..0000000 --- a/jim-common/src/main/java/org/jim/common/config/Config.java +++ /dev/null @@ -1,172 +0,0 @@ -/** - * - */ -package org.jim.common.config; - -import org.jim.common.cluster.ImCluster; -import org.jim.common.message.MessageHelper; -import org.tio.core.GroupContext; -import org.tio.core.intf.GroupListener; -import org.tio.core.ssl.SslConfig; - -/** - * @author WChao - * 2018/08/26 - */ -public class Config { - /** - * IP地址 - */ - protected String bindIp = null; - /** - * 监听端口 - */ - protected Integer bindPort = 80; - /** - * 心跳包发送时长heartbeatTimeout/2 - */ - protected long heartbeatTimeout = 0; - - /** - * 全局群组上下文; - */ - protected GroupContext groupContext; - /** - * 群组监听器; - */ - protected GroupListener imGroupListener; - /** - * 用户消息持久化助手; - */ - protected MessageHelper messageHelper; - /** - * 是否开启持久化; - */ - protected String isStore = "off"; - /** - * 是否开启集群; - */ - protected String isCluster = "off"; - /** - * 是否开启SSL加密 - */ - protected String isSSL = "off"; - /** - * SSL配置 - */ - protected SslConfig sslConfig; - /** - * 集群配置 - * 如果此值不为null,就表示要集群 - */ - protected ImCluster cluster; - /** - * 默认的接收数据的buffer size - */ - protected long readBufferSize = 1024 * 2; - - public String getBindIp() { - return bindIp; - } - - public void setBindIp(String bindIp) { - this.bindIp = bindIp; - } - - public Integer getBindPort() { - return bindPort; - } - - public void setBindPort(Integer bindPort) { - this.bindPort = bindPort; - } - - public long getHeartbeatTimeout() { - return heartbeatTimeout; - } - - public void setHeartbeatTimeout(long heartbeatTimeout) { - this.heartbeatTimeout = heartbeatTimeout; - } - - public GroupContext getGroupContext() { - return groupContext; - } - - public void setGroupContext(GroupContext groupContext) { - this.groupContext = groupContext; - } - - public GroupListener getImGroupListener() { - return imGroupListener; - } - - public void setImGroupListener(GroupListener imGroupListener) { - this.imGroupListener = imGroupListener; - } - - public MessageHelper getMessageHelper() { - return messageHelper; - } - - public void setMessageHelper(MessageHelper messageHelper) { - this.messageHelper = messageHelper; - } - - public String getIsStore() { - return isStore; - } - - public void setIsStore(String isStore) { - this.isStore = isStore; - } - - public String getIsCluster() { - return isCluster; - } - - public void setIsCluster(String isCluster) { - this.isCluster = isCluster; - } - - public String getIsSSL() { - return isSSL; - } - - public void setIsSSL(String isSSL) { - this.isSSL = isSSL; - } - - public SslConfig getSslConfig() { - return sslConfig; - } - - public void setSslConfig(SslConfig sslConfig) { - this.sslConfig = sslConfig; - } - - public ImCluster getCluster() { - return cluster; - } - - public void setCluster(ImCluster cluster) { - this.cluster = cluster; - } - - public long getReadBufferSize() { - return readBufferSize; - } - - public void setReadBufferSize(long readBufferSize) { - this.readBufferSize = readBufferSize; - } - - public interface Builder { - /** - * 配置构建接口 - * @return - * @throws Exception - */ - Config build() throws Exception; - } -} diff --git a/jim-common/src/main/java/org/jim/common/config/DefaultImConfigBuilder.java b/jim-common/src/main/java/org/jim/common/config/DefaultImConfigBuilder.java deleted file mode 100644 index e56a0c2..0000000 --- a/jim-common/src/main/java/org/jim/common/config/DefaultImConfigBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * - */ -package org.jim.common.config; - -import org.jim.common.http.HttpConfig; -import org.jim.common.ws.WsServerConfig; - -/** - * @author WChao - * - */ -public class DefaultImConfigBuilder extends ImConfigBuilder { - - /* (non-Javadoc) - * @see org.jim.common.config.ImConfigBuilder#configHttp(org.jim.common.http.HttpConfig) - */ - @Override - public ImConfigBuilder configHttp(HttpConfig httpConfig) { - // TODO Auto-generated method stub - return this; - } - - /* (non-Javadoc) - * @see org.jim.common.config.ImConfigBuilder#configWs(org.jim.common.ws.WsServerConfig) - */ - @Override - public ImConfigBuilder configWs(WsServerConfig wsServerConfig) { - // TODO Auto-generated method stub - return this; - } - -} diff --git a/jim-common/src/main/java/org/jim/common/config/ImConfig.java b/jim-common/src/main/java/org/jim/common/config/ImConfig.java new file mode 100644 index 0000000..7d614e9 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/config/ImConfig.java @@ -0,0 +1,278 @@ +/** + * + */ +package org.jim.common.config; + +import org.jim.common.ImConst; +import org.jim.common.ImHandler; +import org.jim.common.listener.ImGroupListener; +import org.jim.common.listener.ImGroupListenerAdapter; +import org.jim.common.listener.ImListener; +import org.jim.common.listener.ImUserListener; +import org.tio.core.TioConfig; +import org.tio.utils.Threads; +import org.tio.utils.prop.MapWithLockPropSupport; +import org.tio.utils.thread.pool.DefaultThreadFactory; +import org.tio.utils.thread.pool.SynThreadPoolExecutor; + +import java.util.concurrent.LinkedBlockingQueue; + +/** + * @author WChao + * + */ +public abstract class ImConfig extends MapWithLockPropSupport implements ImConst{ + /** + * IP地址 + */ + protected String bindIp; + /** + * 监听端口 + */ + protected Integer bindPort = 80; + + /** + * 默认的接收数据的buffer size + */ + protected int readBufferSize = 1024 * 2; + /** + * 配置名称 + */ + protected String name = "j-im"; + + /** + * tio相关配置信息 + */ + protected TioConfig tioConfig; + + /** + * 心跳包发送时长heartbeatTimeout/2 + */ + protected long heartbeatTimeout = 0; + + protected SynThreadPoolExecutor jimExecutor; + /** + * 群组绑定监听器 + */ + protected ImGroupListener imGroupListener; + /** + * 用户绑定监听器 + */ + protected ImUserListener imUserListener; + + private static int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; + + public ImConfig(){ + this(null); + } + + public ImConfig(SynThreadPoolExecutor jimExecutor){ + this.jimExecutor = jimExecutor; + if (this.jimExecutor == null) { + LinkedBlockingQueue timQueue = new LinkedBlockingQueue<>(); + this.jimExecutor = new SynThreadPoolExecutor(CORE_POOL_SIZE, CORE_POOL_SIZE, Threads.KEEP_ALIVE_TIME, timQueue, + DefaultThreadFactory.getInstance(ImConst.JIM, Thread.NORM_PRIORITY), ImConst.JIM); + this.jimExecutor.prestartAllCoreThreads(); + } + } + + public static class Const{ + + public static final String ON = "on"; + + public static final String OFF = "off"; + + } + /** + * 获取ImHandler对象 + * @return + * @author: WChao + */ + public abstract ImHandler getImHandler(); + + /** + * 获取ImListener对象 + * @return + * @author: WChao + */ + public abstract ImListener getImListener(); + + public static class Global{ + + private static ImConfig global; + + public static C get(){ + return (C) global; + } + + public static C set(C c){ + global = (ImConfig) c; + return (C) global; + } + } + + public abstract static class Builder> { + + /** + * IP地址 + */ + protected String bindIp; + /** + * 监听端口 + */ + protected Integer bindPort = 80; + /** + * 配置名称 + */ + protected String name = "j-im"; + + /** + * 默认的接收数据的buffer size + */ + protected int readBufferSize = 1024 * 2; + + /** + * 心跳包发送时长heartbeatTimeout/2 + */ + protected long heartbeatTimeout = 0; + + /** + * tio相关配置信息 + */ + protected TioConfig tioConfig; + + /** + * 群组绑定监听器 + */ + protected ImGroupListener imGroupListener; + /** + * 用户绑定监听器 + */ + protected ImUserListener imUserListener; + + + private B theBuilder = this.getThis(); + + /** + * 供子类获取自身builder抽象类; + * @return + */ + protected abstract B getThis(); + + public B bindIp(String bindIp){ + this.bindIp = bindIp; + return theBuilder; + } + + public B bindPort(Integer bindPort){ + this.bindPort = bindPort; + return theBuilder; + } + + public B name(String name){ + this.name = name; + return theBuilder; + } + + public B heartbeatTimeout(long heartbeatTimeout){ + this.heartbeatTimeout = heartbeatTimeout; + return theBuilder; + } + + public B readBufferSize(int readBufferSize){ + this.readBufferSize = readBufferSize; + return theBuilder; + } + + public B tioConfig(TioConfig tioConfig){ + this.tioConfig = tioConfig; + return theBuilder; + } + public B groupListener(ImGroupListener imGroupListener){ + this.imGroupListener = imGroupListener; + return theBuilder; + } + public B userListener(ImUserListener imUserListener){ + this.imUserListener = imUserListener; + return theBuilder; + } + /** + * 配置构建接口 + * @return + * @throws Exception + */ + public abstract T build(); + } + + public String getBindIp() { + return bindIp; + } + + public void setBindIp(String bindIp) { + this.bindIp = bindIp; + } + + public Integer getBindPort() { + return bindPort; + } + + public void setBindPort(Integer bindPort) { + this.bindPort = bindPort; + } + + public int getReadBufferSize() { + return readBufferSize; + } + + public void setReadBufferSize(int readBufferSize) { + this.readBufferSize = readBufferSize; + tioConfig.setReadBufferSize(readBufferSize); + } + + public TioConfig getTioConfig() { + return tioConfig; + } + + public void setTioConfig(TioConfig tioConfig) { + this.tioConfig = tioConfig; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getHeartbeatTimeout() { + return heartbeatTimeout; + } + public void setHeartbeatTimeout(long heartbeatTimeout) { + this.heartbeatTimeout = heartbeatTimeout; + tioConfig.setHeartbeatTimeout(heartbeatTimeout); + } + + public SynThreadPoolExecutor getJimExecutor() { + return jimExecutor; + } + + public ImGroupListener getImGroupListener() { + return imGroupListener; + } + + public void setImGroupListener(ImGroupListener imGroupListener) { + this.imGroupListener = imGroupListener; + if(imGroupListener != null) { + this.tioConfig.setGroupListener(new ImGroupListenerAdapter(this.imGroupListener)); + } + } + + public ImUserListener getImUserListener() { + return imUserListener; + } + + public void setImUserListener(ImUserListener imUserListener) { + this.imUserListener = imUserListener; + } +} diff --git a/jim-common/src/main/java/org/jim/common/config/ImConfigBuilder.java b/jim-common/src/main/java/org/jim/common/config/ImConfigBuilder.java deleted file mode 100644 index d8bc69c..0000000 --- a/jim-common/src/main/java/org/jim/common/config/ImConfigBuilder.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * - */ -package org.jim.common.config; - -import org.jim.common.ImConfig; -import org.jim.common.cluster.ImCluster; -import org.jim.common.http.HttpConfig; -import org.jim.common.message.MessageHelper; -import org.jim.common.ws.WsServerConfig; -import org.tio.core.GroupContext; -import org.tio.core.intf.GroupListener; -import org.tio.core.ssl.SslConfig; - -/** - * @author WChao - * 2018/08/26 - */ -public abstract class ImConfigBuilder implements Config.Builder { - - protected ImConfig conf; - - public ImConfigBuilder() { - this.conf = new ImConfig(); - } - - public abstract ImConfigBuilder configHttp(HttpConfig httpConfig); - public abstract ImConfigBuilder configWs(WsServerConfig wsServerConfig); - - public ImConfigBuilder setBindIp(String bindIp) { - this.conf.bindIp = bindIp; - return this; - } - - public ImConfigBuilder setBindPort(Integer bindPort) { - this.conf.bindPort = bindPort; - return this; - } - - public ImConfigBuilder setHeartbeatTimeout(long heartbeatTimeout) { - this.conf.heartbeatTimeout = heartbeatTimeout; - return this; - } - - public ImConfigBuilder setGroupContext(GroupContext groupContext) { - this.conf.groupContext = groupContext; - return this; - } - - public ImConfigBuilder setImGroupListener(GroupListener imGroupListener) { - this.conf.imGroupListener = imGroupListener; - return this; - } - - public ImConfigBuilder setMessageHelper(MessageHelper messageHelper) { - this.conf.messageHelper = messageHelper; - return this; - } - - public ImConfigBuilder setIsStore(String isStore) { - this.conf.isStore = isStore; - return this; - } - - public ImConfigBuilder setIsCluster(String isCluster) { - this.conf.isCluster = isCluster; - return this; - } - - public ImConfigBuilder setIsSSL(String isSSL) { - this.conf.isSSL = isSSL; - return this; - } - - public ImConfigBuilder setSslConfig(SslConfig sslConfig) { - this.conf.sslConfig = sslConfig; - return this; - } - - public ImConfigBuilder setCluster(ImCluster cluster) { - this.conf.cluster = cluster; - return this; - } - - public ImConfigBuilder setReadBufferSize(long readBufferSize) { - this.conf.readBufferSize = readBufferSize; - return this; - } - - @Override - public ImConfig build() { - this.configHttp(conf.getHttpConfig()); - this.configWs(conf.getWsServerConfig()); - return conf; - } -} diff --git a/jim-common/src/main/java/org/jim/common/config/PropertyImConfigBuilder.java b/jim-common/src/main/java/org/jim/common/config/PropertyImConfigBuilder.java deleted file mode 100644 index 95ec322..0000000 --- a/jim-common/src/main/java/org/jim/common/config/PropertyImConfigBuilder.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * - */ -package org.jim.common.config; - -import org.jim.common.ImConfig; -import org.jim.common.http.HttpConfig; -import org.jim.common.utils.PropUtil; -import org.jim.common.ws.WsServerConfig; -/** - * @author WChao - * 2018/08/26 - */ -public class PropertyImConfigBuilder extends ImConfigBuilder { - - public PropertyImConfigBuilder(String file) { - PropUtil.use(file); - } - - @Override - public ImConfigBuilder configHttp(HttpConfig httpConfig) { - //html/css/js等的根目录,支持classpath:,也支持绝对路径 - String pageRoot = PropUtil.get("jim.http.page"); - //j-im mvc需要扫描的根目录包 - String[] scanPackages = PropUtil.get("jim.http.scan.packages").split(","); - httpConfig.setBindPort((PropUtil.getInt("jim.port"))); - //设置web访问路径; - httpConfig.setPageRoot(pageRoot); - //不缓存资源; - httpConfig.setMaxLiveTimeOfStaticRes(PropUtil.getInt("jim.http.max.live.time")); - //设置j-im mvc扫描目录; - httpConfig.setScanPackages(scanPackages); - return this; - } - - @Override - public ImConfigBuilder configWs(WsServerConfig wsServerConfig) { - - return this; - } - - @Override - public ImConfig build() { - super.build(); - this.setBindIp(PropUtil.get("jim.bind.ip")); - this.setBindPort(PropUtil.getInt("jim.port")); - this.setHeartbeatTimeout(PropUtil.getLong("jim.heartbeat.timeout")); - this.setIsStore(PropUtil.get("jim.store")); - this.setIsCluster(PropUtil.get("jim.cluster")); - return conf; - } -} diff --git a/jim-common/src/main/java/org/jim/common/exception/ImDecodeException.java b/jim-common/src/main/java/org/jim/common/exception/ImDecodeException.java new file mode 100644 index 0000000..e003647 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/exception/ImDecodeException.java @@ -0,0 +1,22 @@ +package org.jim.common.exception; + +import org.tio.core.exception.LengthOverflowException; + +/** + * @ClassName ImDecodeException + * @Description TODO + * @Author WChao + * @Date 2020/1/11 6:02 + * @Version 1.0 + **/ +public class ImDecodeException extends ImException { + + public ImDecodeException(Throwable e) { + super(e); + } + + public ImDecodeException(String message) { + super(message); + + } +} diff --git a/jim-common/src/main/java/org/jim/common/exception/ImException.java b/jim-common/src/main/java/org/jim/common/exception/ImException.java index 9b21ce0..9163b4f 100644 --- a/jim-common/src/main/java/org/jim/common/exception/ImException.java +++ b/jim-common/src/main/java/org/jim/common/exception/ImException.java @@ -12,7 +12,7 @@ public class ImException extends Exception{ /** * @Author WChao * @Description //TODO - * @param [] + * @param * @return **/ public ImException() { @@ -21,7 +21,7 @@ public class ImException extends Exception{ /** * @Author WChao * @Description //TODO - * @param [message] + * @param message * @return **/ public ImException(String message) { @@ -32,7 +32,7 @@ public class ImException extends Exception{ /** * @Author WChao * @Description //TODO - * @param [message, cause] + * @param message, cause * @return **/ public ImException(String message, Throwable cause) { @@ -43,7 +43,7 @@ public class ImException extends Exception{ /** * @Author WChao * @Description //TODO - * @param [message, cause, enableSuppression, writableStackTrace] + * @param message, cause, enableSuppression, writableStackTrace * @return **/ public ImException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { @@ -54,7 +54,7 @@ public class ImException extends Exception{ /** * @Author WChao * @Description //TODO - * @param [cause] + * @param cause * @return **/ public ImException(Throwable cause) { diff --git a/jim-common/src/main/java/org/jim/common/http/Cookie.java b/jim-common/src/main/java/org/jim/common/http/Cookie.java index d31ee14..8baccc6 100644 --- a/jim-common/src/main/java/org/jim/common/http/Cookie.java +++ b/jim-common/src/main/java/org/jim/common/http/Cookie.java @@ -9,6 +9,7 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jim.common.ImConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,7 +18,7 @@ import org.slf4j.LoggerFactory; * @author wchao * 2017年5月29日 上午7:45:58 */ -public class Cookie { +public class Cookie implements ImConst { private static Logger log = LoggerFactory.getLogger(Cookie.class); /** @@ -50,7 +51,7 @@ public class Cookie { default: cookie.setName(cookieMapItem.getKey()); try { - cookie.setValue(URLDecoder.decode(cookieMapItem.getValue(), HttpConst.CHARSET_NAME)); + cookie.setValue(URLDecoder.decode(cookieMapItem.getValue(), Http.CHARSET_NAME)); } catch (UnsupportedEncodingException e) { log.error(e.toString(), e); } diff --git a/jim-common/src/main/java/org/jim/common/http/GroupContextKey.java b/jim-common/src/main/java/org/jim/common/http/GroupContextKey.java deleted file mode 100644 index 945486f..0000000 --- a/jim-common/src/main/java/org/jim/common/http/GroupContextKey.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.jim.common.http; - -/** - * @author wchao - * 2017年8月18日 下午5:43:54 - */ -public interface GroupContextKey { - /** - * 存放HttpConfig - */ - String HTTP_SERVER_CONFIG = "TIO_HTTP_SERVER_CONFIG"; -} diff --git a/jim-common/src/main/java/org/jim/common/http/HttpConfig.java b/jim-common/src/main/java/org/jim/common/http/HttpConfig.java index ef97ccb..7f7207f 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpConfig.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpConfig.java @@ -1,6 +1,6 @@ package org.jim.common.http; -import org.jim.common.config.Config; +import org.jim.common.ImConst; import org.jim.common.http.handler.IHttpRequestHandler; import org.jim.common.http.listener.IHttpServerListener; import org.jim.common.session.id.ISessionIdGenerator; @@ -10,19 +10,24 @@ import org.tio.utils.cache.ICache; * @author wchao * 2017年8月15日 下午1:21:14 */ -public class HttpConfig extends Config{ - - // private static Logger log = LoggerFactory.getLogger(HttpConfig.class); - +public class HttpConfig implements ImConst { + /** + * IP地址 + */ + protected String bindIp; + /** + * 监听端口 + */ + protected Integer bindPort = 80; /** * 存放HttpSession对象的cacheName */ - public static final String SESSION_CACHE_NAME = "tio-h-s"; + public static final String SESSION_CACHE_NAME = "jim-h-s"; /** * 存放sessionId的cookie name */ - public static final String SESSION_COOKIE_NAME = "TwIxO"; + public static final String SESSION_COOKIE_NAME = "jimIxO"; /** * session默认的超时时间,单位:秒 @@ -32,7 +37,7 @@ public class HttpConfig extends Config{ /** * 默认的静态资源缓存时间,单位:秒 */ - public static final int MAX_LIVETIME_OF_STATICRES = 60 * 10; + public static final int MAX_LIVE_TIME_OF_STATICS = 60 * 10; /** * 文件上传时,boundary值的最大长度 @@ -49,17 +54,9 @@ public class HttpConfig extends Config{ */ public static final int MAX_LENGTH_OF_MULTI_BODY = 1024 * 1024 * 20; - /** - * @param args - * @author wchao - */ - public static void main(String[] args) { + private String serverInfo = Http.SERVER_INFO; - } - - private String serverInfo = HttpConst.SERVER_INFO; - - private String charset = HttpConst.CHARSET_NAME; + private String charset = Http.CHARSET_NAME; private ICache sessionStore = null; @@ -72,14 +69,14 @@ public class HttpConfig extends Config{ /** * session超时时间,单位:秒 */ - private long sessionTimeout = DEFAULT_SESSION_TIMEOUT; + private Long sessionTimeout = DEFAULT_SESSION_TIMEOUT; private String sessionCookieName = SESSION_COOKIE_NAME; /** * 静态资源缓存时间,如果小于等于0则不缓存,单位:秒 */ - private int maxLiveTimeOfStaticRes = MAX_LIVETIME_OF_STATICRES; + private Integer maxLiveTimeOfStaticRes = MAX_LIVE_TIME_OF_STATICS; private String page404 = "/404.html"; @@ -97,36 +94,138 @@ public class HttpConfig extends Config{ * 2、绝对路径:/page * //FileUtil.getAbsolutePath("page");//"/page"; */ - private String pageRoot = null; + private String pageRoot = "page"; /** * mvc扫描包路径; */ private String[] scanPackages = null; - - public HttpConfig() {} - - /** - * - * @author wchao - */ - public HttpConfig(Integer bindPort, Long sessionTimeout) { - this.bindPort = bindPort; - if (sessionTimeout != null) { + public HttpConfig(IHttpRequestHandler httpRequestHandler, IHttpServerListener httpServerListener){ + setHttpRequestHandler(httpRequestHandler); + setHttpServerListener(httpServerListener); + } + + public static HttpConfig.Builder newBuilder(){ + return new HttpConfig.Builder(); + } + + public static class Builder{ + + private String charset = Http.CHARSET_NAME; + + private ICache sessionStore; + + private Long sessionTimeout = DEFAULT_SESSION_TIMEOUT; + + /** + * 静态资源缓存时间,如果小于等于0则不缓存,单位:秒 + */ + private Integer maxLiveTimeOfStaticRes = MAX_LIVE_TIME_OF_STATICS; + + private String page404 = "/404.html"; + + private String page500 = "/500.html"; + + private ISessionIdGenerator sessionIdGenerator; + + private IHttpRequestHandler httpRequestHandler; + + private IHttpServerListener httpServerListener; + + private String pageRoot = "page"; + + private String[] scanPackages = null; + + public Builder charset(String charset){ + this.charset = charset; + return this; + } + + public Builder sessionStore(ICache sessionStore){ + this.sessionStore = sessionStore; + return this; + } + + public Builder sessionTimeout(Long sessionTimeout){ this.sessionTimeout = sessionTimeout; + return this; + } + + public Builder maxLiveTimeOfStaticRes(int maxLiveTimeOfStaticRes){ + this.maxLiveTimeOfStaticRes = maxLiveTimeOfStaticRes; + return this; + } + + public Builder page404(String page404){ + this.page404 = page404; + return this; + } + + public Builder page500(String page500){ + this.page500 = page500; + return this; + } + + public Builder sessionIdGenerator(ISessionIdGenerator sessionIdGenerator){ + this.sessionIdGenerator = sessionIdGenerator; + return this; + } + + public Builder httpRequestHandler(IHttpRequestHandler httpRequestHandler){ + this.httpRequestHandler = httpRequestHandler; + return this; + } + + public Builder httpServerListener(IHttpServerListener httpServerListener){ + this.httpServerListener = httpServerListener; + return this; + } + + public Builder pageRoot(String pageRoot){ + this.pageRoot = pageRoot; + return this; + } + + public Builder scanPackages(String[] scanPackages){ + this.scanPackages = scanPackages; + return this; + } + + public HttpConfig build(){ + HttpConfig httpConfig = new HttpConfig(this.httpRequestHandler, this.httpServerListener); + httpConfig.setCharset(this.charset); + httpConfig.setSessionStore(this.sessionStore); + httpConfig.setSessionTimeout(this.sessionTimeout); + httpConfig.setMaxLiveTimeOfStaticRes(maxLiveTimeOfStaticRes); + httpConfig.setPage404(page404); + httpConfig.setPage500(page500); + httpConfig.setSessionIdGenerator(sessionIdGenerator); + httpConfig.setPageRoot(pageRoot); + httpConfig.setScanPackages(scanPackages); + return httpConfig; } } - - /** - * @return the charset - */ + public String getCharset() { return charset; } - /** - * @return the maxLiveTimeOfStaticRes - */ + public void setCharset(String charset) { + this.charset = charset; + } + + public ICache getSessionStore() { + return sessionStore; + } + + public void setSessionStore(ICache sessionStore) { + this.sessionStore = sessionStore; + } + + public Long getSessionTimeout() { + return sessionTimeout; + } + public int getMaxLiveTimeOfStaticRes() { return maxLiveTimeOfStaticRes; } @@ -135,127 +234,34 @@ public class HttpConfig extends Config{ return page404; } - public String getPage500() { - return page500; - } - - /** - * @return the pageRoot - */ - public String getPageRoot() { - return pageRoot; - } - - /** - * @return the serverInfo - */ - public String getServerInfo() { - return serverInfo; - } - - /** - * @return the sessionCacheName - */ - public String getSessionCacheName() { - return sessionCacheName; - } - - public String getSessionCookieName() { - return sessionCookieName; - } - - public ISessionIdGenerator getSessionIdGenerator() { - return sessionIdGenerator; - } - - public ICache getSessionStore() { - return sessionStore; - } - - public long getSessionTimeout() { - return sessionTimeout; - } - - /** - * @param charset the charset to set - */ - public void setCharset(String charset) { - this.charset = charset; - } - - /** - * @param maxLiveTimeOfStaticRes the maxLiveTimeOfStaticRes to set - */ - public void setMaxLiveTimeOfStaticRes(int maxLiveTimeOfStaticRes) { - this.maxLiveTimeOfStaticRes = maxLiveTimeOfStaticRes; - } - public void setPage404(String page404) { this.page404 = page404; } + public String getPage500() { + return page500; + } + public void setPage500(String page500) { this.page500 = page500; } - /** - * - * @param pageRoot - * @author wchao - */ - public void setPageRoot(String pageRoot) { - this.pageRoot = pageRoot;//FileUtil.getAbsolutePath(root);//"/page";; - } - - /** - * @param serverInfo the serverInfo to set - */ - public void setServerInfo(String serverInfo) { - this.serverInfo = serverInfo; - } - - /** - * @param sessionCacheName the sessionCacheName to set - */ - public void setSessionCacheName(String sessionCacheName) { - this.sessionCacheName = sessionCacheName; - } - - public void setSessionCookieName(String sessionCookieName) { - this.sessionCookieName = sessionCookieName; + public ISessionIdGenerator getSessionIdGenerator() { + return sessionIdGenerator; } public void setSessionIdGenerator(ISessionIdGenerator sessionIdGenerator) { this.sessionIdGenerator = sessionIdGenerator; } - public void setSessionStore(ICache sessionStore) { - this.sessionStore = sessionStore; - // this.httpSessionManager = HttpSessionManager.getInstance(sessionStore); - } - - /** - * @return the httpRequestHandler - */ public IHttpRequestHandler getHttpRequestHandler() { return httpRequestHandler; } - /** - * @param httpRequestHandler the httpRequestHandler to set - */ public void setHttpRequestHandler(IHttpRequestHandler httpRequestHandler) { this.httpRequestHandler = httpRequestHandler; } - public String[] getScanPackages() { - return scanPackages; - } - - public void setScanPackages(String[] scanPackages) { - this.scanPackages = scanPackages; - } - public IHttpServerListener getHttpServerListener() { return httpServerListener; } @@ -264,4 +270,55 @@ public class HttpConfig extends Config{ this.httpServerListener = httpServerListener; } + public String getPageRoot() { + return pageRoot; + } + + public void setPageRoot(String pageRoot) { + this.pageRoot = pageRoot; + } + + public String[] getScanPackages() { + return scanPackages; + } + + public void setScanPackages(String[] scanPackages) { + this.scanPackages = scanPackages; + } + + public String getServerInfo() { + return serverInfo; + } + + public String getSessionCacheName() { + return sessionCacheName; + } + + public String getSessionCookieName() { + return sessionCookieName; + } + + public String getBindIp() { + return bindIp; + } + + public void setBindIp(String bindIp) { + this.bindIp = bindIp; + } + + public Integer getBindPort() { + return bindPort; + } + + public void setBindPort(Integer bindPort) { + this.bindPort = bindPort; + } + + public void setSessionTimeout(Long sessionTimeout) { + this.sessionTimeout = sessionTimeout; + } + + public void setMaxLiveTimeOfStaticRes(Integer maxLiveTimeOfStaticRes) { + this.maxLiveTimeOfStaticRes = maxLiveTimeOfStaticRes; + } } diff --git a/jim-common/src/main/java/org/jim/common/http/HttpConst.java b/jim-common/src/main/java/org/jim/common/http/HttpConst.java index 403a499..d61a8fd 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpConst.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpConst.java @@ -7,182 +7,5 @@ package org.jim.common.http; */ public interface HttpConst { - /** - * 请求体的格式 - * @author wchao - * 2017年6月28日 上午10:03:12 - */ - public enum RequestBodyFormat { - URLENCODED, MULTIPART, TEXT - } - /** - * Accept-Language : zh-CN,zh;q=0.8 - Sec-WebSocket-Version : 13 - Sec-WebSocket-Extensions : permessage-deflate; client_max_window_bits - Upgrade : websocket - Host : t-io.org:9321 - Accept-Encoding : gzip, deflate, sdch - User-Agent : Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 - Origin : http://www.t-io.org:9292 - Sec-WebSocket-Key : kmCL2C7q9vtNSMyHpft7lw== - Connection : Upgrade - Cache-Control : no-cache - Pragma : no-cache - * - * @author wchao - * 2017年5月27日 下午2:11:57 - */ - public interface RequestHeaderKey { - String Cookie = "Cookie".toLowerCase();//Cookie: $Version=1; Skin=new; - String Origin = "Origin".toLowerCase(); //http://127.0.0.1 - String Sec_WebSocket_Key = "Sec-WebSocket-Key".toLowerCase(); //2GFwqJ1Z37glm62YKKLUeA== - String Cache_Control = "Cache-Control".toLowerCase(); //no-cache - String Connection = "Connection".toLowerCase(); //Upgrade, keep-alive - String User_Agent = "User-Agent".toLowerCase(); //Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3088.3 Safari/537.36 - String Sec_WebSocket_Version = "Sec-WebSocket-Version".toLowerCase(); //13 - String Host = "Host".toLowerCase(); //127.0.0.1:9321 - String Pragma = "Pragma".toLowerCase(); //no-cache - String Accept_Encoding = "Accept-Encoding".toLowerCase(); //gzip, deflate, br - String Accept_Language = "Accept-Language".toLowerCase(); //zh-CN,zh;q=0.8,en;q=0.6 - String Upgrade = "Upgrade".toLowerCase(); //websocket - String Sec_WebSocket_Extensions = "Sec-WebSocket-Extensions".toLowerCase(); //permessage-deflate; client_max_window_bits - String Content_Length = "Content-Length".toLowerCase(); //65 - String Content_Type = "Content-Type".toLowerCase();// : 【application/x-www-form-urlencoded】【application/x-www-form-urlencoded; charset=UTF-8】【multipart/form-data; boundary=----WebKitFormBoundaryuwYcfA2AIgxqIxA0 】 - String If_Modified_Since = "If-Modified-Since".toLowerCase(); //与Last-Modified配合 - - /** - * 值为XMLHttpRequest则为Ajax - */ - String X_Requested_With = "X-Requested-With".toLowerCase();//XMLHttpRequest - } - - // Content-Type: text/html;charset:utf-8; - - /** - * - * @author wchao - * 2017年6月27日 下午8:23:58 - */ - public interface RequestHeaderValue { - public interface Connection { - String keep_alive = "keep-alive".toLowerCase(); - String Upgrade = "Upgrade".toLowerCase(); - String close = "close".toLowerCase(); - } - - //application/x-www-form-urlencoded、multipart/form-data、text/plain - public interface Content_Type { - /** - * 普通文本,一般会是json或是xml - */ - String text_plain = "text/plain".toLowerCase(); - /** - * 文件上传 - */ - String multipart_form_data = "multipart/form-data".toLowerCase(); - /** - * 普通的key-value - */ - String application_x_www_form_urlencoded = "application/x-www-form-urlencoded".toLowerCase(); - } - } - - public interface ResponseHeaderKey { - //Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 - String Set_Cookie = "Set-Cookie".toLowerCase(); //Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 - String Content_Length = "Content-Length".toLowerCase(); //65 - - String Connection = "Connection".toLowerCase(); //Upgrade, keep-alive - String Keep_Alive = "Keep-Alive".toLowerCase(); //Keep-Alive:timeout=20 - String Sec_WebSocket_Accept = "Sec-WebSocket-Accept".toLowerCase(); - String Upgrade = "Upgrade".toLowerCase(); - - /** - * Content-Disposition: attachment;filename=FileName.txt - * 文件下载 - */ - String Content_disposition = "Content-disposition".toLowerCase(); - /** - * 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。 - * 利用gzip压缩文档能够显著地减少HTML文档的下载时间。 - * Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。 - * 因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip, - * 为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。 - */ - String Content_Encoding = "Content-Encoding".toLowerCase(); - /** - * 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。 - * 由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。 - */ - String Content_Type = "Content-Type".toLowerCase(); - /** - * 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。 - */ - String Date = "Date".toLowerCase(); - /** - * 应该在什么时候认为文档已经过期,从而不再缓存它? - */ - String Expires = "Expires".toLowerCase(); - /** - * 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET, - * 只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。 - */ - String Last_Modified = "Last-Modified".toLowerCase(); - /** - * 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。 - */ - String Location = "Location".toLowerCase(); - /** - * 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 - 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。 - - 注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。 - - 注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。 - */ - String Refresh = "Refresh".toLowerCase(); - /** - * 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。 - */ - String Server = "Server".toLowerCase(); - - /** - * - */ - String Access_Control_Allow_Origin = "Access-Control-Allow-Origin".toLowerCase(); //value: * - - /** - * - */ - String Access_Control_Allow_Headers = "Access-Control-Allow-Headers".toLowerCase(); //value: x-requested-with,content-type - - /** - * 是否是从缓存中获取的数据,tio-httpserver特有的头部信息 - */ - String tio_from_cache = "tio-from-cache"; - } - - /** - * - * @author wchao - * 2017年6月27日 下午8:24:02 - */ - public interface ResponseHeaderValue { - public interface Connection { - String keep_alive = "keep-alive".toLowerCase(); - String Upgrade = "Upgrade".toLowerCase(); - String close = "close".toLowerCase(); - } - } - - /** - * - */ - String SERVER_INFO = "tio-httpserver/0.0.1"; - - /** - * 默认规定连接到本服务器的客户端统一用utf-8 - */ - String CHARSET_NAME = "utf-8"; } diff --git a/jim-common/src/main/java/org/jim/common/http/HttpConvertPacket.java b/jim-common/src/main/java/org/jim/common/http/HttpConvertPacket.java index c3ffbec..870dfb6 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpConvertPacket.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpConvertPacket.java @@ -3,26 +3,26 @@ */ package org.jim.common.http; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; import org.jim.common.ImPacket; +import org.jim.common.ImSessionContext; import org.jim.common.http.session.HttpSession; import org.jim.common.packets.Command; -import org.jim.common.protocol.IConvertProtocolPacket; -import org.tio.core.ChannelContext; - +import org.jim.common.protocol.IProtocolConverter; /** * HTTP协议消息转化包 * @author WChao * */ -public class HttpConvertPacket implements IConvertProtocolPacket { +public class HttpConvertPacket implements IProtocolConverter { /** * 转HTTP协议响应包; */ @Override - public ImPacket RespPacket(byte[] body, Command command,ChannelContext channelContext) { - Object sessionContext = channelContext.getAttribute(); + public ImPacket RespPacket(byte[] body, Command command, ImChannelContext channelContext) { + ImSessionContext sessionContext = channelContext.getSessionContext(); if(sessionContext instanceof HttpSession){ HttpRequest request = (HttpRequest)channelContext.getAttribute(ImConst.HTTP_REQUEST); HttpResponse response = new HttpResponse(request,request.getHttpConfig()); @@ -34,7 +34,7 @@ public class HttpConvertPacket implements IConvertProtocolPacket { } @Override - public ImPacket ReqPacket(byte[] body, Command command,ChannelContext channelContext) { + public ImPacket ReqPacket(byte[] body, Command command, ImChannelContext channelContext) { return null; } diff --git a/jim-common/src/main/java/org/jim/common/http/HttpMultiBodyDecoder.java b/jim-common/src/main/java/org/jim/common/http/HttpMultiBodyDecoder.java index 5213288..5d86658 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpMultiBodyDecoder.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpMultiBodyDecoder.java @@ -8,10 +8,10 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.jim.common.ImChannelContext; +import org.jim.common.exception.ImDecodeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.ChannelContext; -import org.tio.core.exception.AioDecodeException; import org.tio.core.exception.LengthOverflowException; import org.tio.core.utils.ByteBufferUtils; import org.jim.common.utils.HttpParseUtils; @@ -83,31 +83,20 @@ public class HttpMultiBodyDecoder { * @author wchao * 2017年7月27日 上午10:18:01 */ - public static interface MultiBodyHeaderKey { + public interface MultiBodyHeaderKey { String Content_Disposition = "Content-Disposition".toLowerCase(); String Content_Type = "Content-Type".toLowerCase(); } - public static enum Step { + public enum Step { BOUNDARY, HEADER, BODY, END } private static Logger log = LoggerFactory.getLogger(HttpMultiBodyDecoder.class); - // public static int processReadIndex(ByteBuffer buffer) - // { - // int newReaderIndex = buffer.readerIndex(); - // if (newReaderIndex < buffer.capacity()) - // { - // buffer.readerIndex(newReaderIndex + 1); - // return 1; - // } - // return 0; - // } - - public static void decode(HttpRequest request, RequestLine firstLine, byte[] bodyBytes, String initboundary, ChannelContext channelContext) throws AioDecodeException { - if (StringUtils.isBlank(initboundary)) { - throw new AioDecodeException("boundary is null"); + public static void decode(HttpRequest request, RequestLine firstLine, byte[] bodyBytes, String initBoundary, ImChannelContext channelContext) throws ImDecodeException { + if (StringUtils.isBlank(initBoundary)) { + throw new ImDecodeException("boundary is null"); } long start = SystemTimer.currentTimeMillis(); @@ -115,25 +104,21 @@ public class HttpMultiBodyDecoder { ByteBuffer buffer = ByteBuffer.wrap(bodyBytes); buffer.position(0); - String boundary = "--" + initboundary; + String boundary = "--" + initBoundary; String endBoundary = boundary + "--"; - - // int boundaryLength = boundary.getBytes().length; Step step = Step.BOUNDARY; - // int bufferLength = buffer.capacity(); try { label1: while (true) { if (step == Step.BOUNDARY) { String line = ByteBufferUtils.readLine(buffer, request.getCharset(), HttpConfig.MAX_LENGTH_OF_BOUNDARY); - // int offset = HttpMultiBodyDecoder.processReadIndex(buffer); if (boundary.equals(line)) { step = Step.HEADER; - } else if (endBoundary.equals(line)) // 结束了 + // 结束了 + } else if (endBoundary.equals(line)) { - // int ss = buffer.readerIndex() + 2 - offset; break; } else { - throw new AioDecodeException("line need:" + boundary + ", but is: " + line + ""); + throw new ImDecodeException("line need:" + boundary + ", but is: " + line + ""); } } @@ -164,7 +149,7 @@ public class HttpMultiBodyDecoder { } } catch (LengthOverflowException loe) { - throw new AioDecodeException(loe); + throw new ImDecodeException(loe); } catch (UnsupportedEncodingException e) { log.error(channelContext.toString(), e); } finally { @@ -175,37 +160,6 @@ public class HttpMultiBodyDecoder { } - /** - * 返回值不包括最后的\r\n - * @param buffer - * @param charset - * @return - * @throws UnsupportedEncodingException - */ - // public static String getLine(ByteBuffer buffer, String charset) throws UnsupportedEncodingException { - // char lastByte = 0; // 上一个字节 - // int initPosition = buffer.position(); - // - // while (buffer.hasRemaining()) { - // char b = (char) buffer.get(); - // - // if (b == '\n') { - // if (lastByte == '\r') { - // int startIndex = initPosition; - // int endIndex = buffer.position() - 2; - // int length = endIndex - startIndex; - // byte[] dst = new byte[length]; - // - // System.arraycopy(buffer.array(), startIndex, dst, 0, length); - // String line = new String(dst, charset); - // return line; - // } - // } - // lastByte = b; - // } - // return null; - // } - /** * @param args * @throws UnsupportedEncodingException @@ -234,7 +188,7 @@ public class HttpMultiBodyDecoder { * @throws LengthOverflowException * @author wchao */ - public static Step parseBody(Header header, HttpRequest request, ByteBuffer buffer, String boundary, String endBoundary, ChannelContext channelContext) + public static Step parseBody(Header header, HttpRequest request, ByteBuffer buffer, String boundary, String endBoundary, ImChannelContext channelContext) throws UnsupportedEncodingException, LengthOverflowException { int initPosition = buffer.position(); @@ -249,10 +203,11 @@ public class HttpMultiBodyDecoder { byte[] dst = new byte[length]; System.arraycopy(buffer.array(), startIndex, dst, 0, length); + //该字段类型是file String filename = header.getFilename(); - if (filename != null)//该字段类型是file + if (filename != null) { - if (!"".equals(filename)) { // + if (!"".equals(filename)) { UploadFile uploadFile = new UploadFile(); uploadFile.setName(filename); uploadFile.setData(dst); @@ -285,24 +240,22 @@ public class HttpMultiBodyDecoder { * @param header * @author wchao */ - public static void parseHeader(List lines, Header header, ChannelContext channelContext) throws AioDecodeException { + public static void parseHeader(List lines, Header header, ImChannelContext channelContext) throws ImDecodeException { if (lines == null || lines.size() == 0) { - throw new AioDecodeException("multipart_form_data 格式不对,没有头部信息"); + throw new ImDecodeException("multipart_form_data 格式不对,没有头部信息"); } - try { for (String line : lines) { - String[] keyvalue = StringUtils.split(line, ":"); - String key = StringUtils.lowerCase(StringUtils.trim(keyvalue[0]));// - String value = StringUtils.trim(keyvalue[1]); + String[] keyValue = StringUtils.split(line, ":"); + String key = StringUtils.lowerCase(StringUtils.trim(keyValue[0])); + String value = StringUtils.trim(keyValue[1]); header.map.put(key, value); } String contentDisposition = header.map.get(MultiBodyHeaderKey.Content_Disposition); String name = HttpParseUtils.getPerprotyEqualValue(header.map, MultiBodyHeaderKey.Content_Disposition, "name"); String filename = HttpParseUtils.getPerprotyEqualValue(header.map, MultiBodyHeaderKey.Content_Disposition, "filename"); - String contentType = header.map.get(MultiBodyHeaderKey.Content_Type);//.HttpParseUtils.getPerprotyEqualValue(header.map, MultiBodyHeaderKey.Content_Type, "filename"); - + String contentType = header.map.get(MultiBodyHeaderKey.Content_Type); header.setContentDisposition(contentDisposition); header.setName(name); header.setFilename(filename); @@ -310,29 +263,8 @@ public class HttpMultiBodyDecoder { } catch (Exception e) { log.error(channelContext.toString(), e); - throw new AioDecodeException(e.toString()); + throw new ImDecodeException(e.toString()); } - - // for (int i = 0; i < lines.size(); i++) { - // String line = lines.get(i); - // if (i == 0) { - // String[] mapStrings = StringUtils.split(line, ";"); - // String s = mapStrings[0];// - // - // String[] namekeyvalue = StringUtils.split(mapStrings[1], "="); - // header.setName(namekeyvalue[1].substring(1, namekeyvalue[1].length() - 1)); - // - // if (mapStrings.length == 3) { - // String[] finenamekeyvalue = StringUtils.split(mapStrings[2], "="); - // String filename = finenamekeyvalue[1].substring(1, finenamekeyvalue[1].length() - 1); - // header.setFilename(FilenameUtils.getName(filename)); - // } - // } else if (i == 1) { - // String[] map = StringUtils.split(line, ":"); - // String contentType = map[1].trim();// - // header.setContentType(contentType); - // } - // } } /** diff --git a/jim-common/src/main/java/org/jim/common/http/HttpProtocol.java b/jim-common/src/main/java/org/jim/common/http/HttpProtocol.java index c2097b7..955f281 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpProtocol.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpProtocol.java @@ -4,62 +4,58 @@ package org.jim.common.http; import java.nio.ByteBuffer; - +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.jim.common.ImSessionContext; -import org.jim.common.Protocol; +import org.jim.common.exception.ImException; import org.jim.common.http.session.HttpSession; -import org.jim.common.protocol.AbProtocol; -import org.jim.common.protocol.IConvertProtocolPacket; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.common.protocol.IProtocolConverter; import org.jim.common.utils.ImUtils; -import org.tio.core.ChannelContext; - /** * * Http协议校验器 * @author WChao * */ -public class HttpProtocol extends AbProtocol { +public class HttpProtocol extends AbstractProtocol { @Override public String name() { return Protocol.HTTP; } + public HttpProtocol(IProtocolConverter protocolConverter){ + super(protocolConverter); + } + @Override - public boolean isProtocolByBuffer(ByteBuffer buffer,ChannelContext channelContext) throws Throwable { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - if(imSessionContext != null && imSessionContext instanceof HttpSession) { + protected void init(ImChannelContext imChannelContext) { + imChannelContext.setSessionContext(new HttpSession(imChannelContext)); + ImUtils.setClient(imChannelContext); + } + + @Override + public boolean validateProtocol(ImSessionContext imSessionContext) throws ImException { + if(imSessionContext instanceof HttpSession) { return true; } - if(buffer != null){ - HttpRequest request = HttpRequestDecoder.decode(buffer, channelContext,false); - if(request.getHeaders().get(HttpConst.RequestHeaderKey.Sec_WebSocket_Key) == null) - { - channelContext.setAttribute(new HttpSession()); - ImUtils.setClient(channelContext); - return true; - } - } return false; } @Override - public IConvertProtocolPacket converter() { - return new HttpConvertPacket(); + public boolean validateProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException { + HttpRequest request = HttpRequestDecoder.decode(buffer, imChannelContext,false); + if(request.getHeaders().get(Http.RequestHeaderKey.Sec_WebSocket_Key) == null) + { + return true; + } + return false; } @Override - public boolean isProtocol(ImPacket imPacket,ChannelContext channelContext) throws Throwable { - if(imPacket == null) { - return false; - } + public boolean validateProtocol(ImPacket imPacket) throws ImException { if(imPacket instanceof HttpPacket){ - Object sessionContext = channelContext.getAttribute(); - if(sessionContext == null){ - channelContext.setAttribute(new HttpSession()); - } return true; } return false; diff --git a/jim-common/src/main/java/org/jim/common/http/HttpRequest.java b/jim-common/src/main/java/org/jim/common/http/HttpRequest.java index 93677f4..f24aee0 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpRequest.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpRequest.java @@ -7,12 +7,13 @@ import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.tio.core.ChannelContext; import org.tio.core.Node; -import org.jim.common.http.HttpConst.RequestBodyFormat; import org.jim.common.http.session.HttpSession; +import org.tio.utils.hutool.ArrayUtil; -import cn.hutool.core.util.ArrayUtil; /** * * @author wchao @@ -20,7 +21,7 @@ import cn.hutool.core.util.ArrayUtil; */ public class HttpRequest extends HttpPacket { - // private static Logger log = LoggerFactory.getLogger(HttpRequest.class); + private static Logger log = LoggerFactory.getLogger(HttpRequest.class); private static final long serialVersionUID = -3849253977016967211L; @@ -43,14 +44,12 @@ public class HttpRequest extends HttpPacket { private Map cookieMap = null; private int contentLength; private String bodyString; - private RequestBodyFormat bodyFormat; - private String charset = HttpConst.CHARSET_NAME; + private Http.RequestBodyFormat bodyFormat; + private String charset = Http.CHARSET_NAME; private Boolean isAjax = null; private Boolean isSupportGzip = null; private HttpSession httpSession; - private Node remote = null; - private ChannelContext channelContext; - + private Node remote; private HttpConfig httpConfig; /** @@ -84,7 +83,7 @@ public class HttpRequest extends HttpPacket { /** * @return the bodyFormat */ - public RequestBodyFormat getBodyFormat() { + public Http.RequestBodyFormat getBodyFormat() { return bodyFormat; } @@ -95,13 +94,6 @@ public class HttpRequest extends HttpPacket { return bodyString; } - /** - * @return the channelContext - */ - public ChannelContext getChannelContext() { - return channelContext; - } - /** * @return the charset */ @@ -156,7 +148,7 @@ public class HttpRequest extends HttpPacket { */ public Boolean getIsAjax() { if (isAjax == null) { - String X_Requested_With = this.getHeader(HttpConst.RequestHeaderKey.X_Requested_With); + String X_Requested_With = this.getHeader(Http.RequestHeaderKey.X_Requested_With); if (X_Requested_With != null && "XMLHttpRequest".equalsIgnoreCase(X_Requested_With)) { isAjax = true; } else { @@ -172,7 +164,7 @@ public class HttpRequest extends HttpPacket { */ public Boolean getIsSupportGzip() { if (isSupportGzip == null) { - String Accept_Encoding = getHeader(HttpConst.RequestHeaderKey.Accept_Encoding); + String Accept_Encoding = getHeader(Http.RequestHeaderKey.Accept_Encoding); if (StringUtils.isNoneBlank(Accept_Encoding)) { String[] ss = StringUtils.split(Accept_Encoding, ","); if (ArrayUtil.contains(ss, "gzip")) { @@ -219,7 +211,7 @@ public class HttpRequest extends HttpPacket { } public void parseCookie() { - String cookieLine = headers.get(HttpConst.RequestHeaderKey.Cookie); + String cookieLine = headers.get(Http.RequestHeaderKey.Cookie); if (StringUtils.isNotBlank(cookieLine)) { cookies = new ArrayList<>(); cookieMap = new HashMap<>(); @@ -233,7 +225,7 @@ public class HttpRequest extends HttpPacket { Cookie cookie = Cookie.buildCookie(cookieOneMap); cookies.add(cookie); cookieMap.put(cookie.getName(), cookie); - //log.error("{}, 收到cookie:{}", channelContext, cookie.toString()); + log.info("{}, 收到cookie:{}", imChannelContext, cookie.toString()); } } } @@ -241,7 +233,7 @@ public class HttpRequest extends HttpPacket { /** * @param bodyFormat the bodyFormat to set */ - public void setBodyFormat(RequestBodyFormat bodyFormat) { + public void setBodyFormat(Http.RequestBodyFormat bodyFormat) { this.bodyFormat = bodyFormat; } @@ -252,13 +244,6 @@ public class HttpRequest extends HttpPacket { this.bodyString = bodyString; } - /** - * @param channelContext the channelContext to set - */ - public void setChannelContext(ChannelContext channelContext) { - this.channelContext = channelContext; - } - /** * @param charset the charset to set */ @@ -267,7 +252,7 @@ public class HttpRequest extends HttpPacket { } /** - * @param bodyLength the bodyLength to set + * @param contentLength the bodyLength to set */ public void setContentLength(int contentLength) { this.contentLength = contentLength; @@ -290,7 +275,6 @@ public class HttpRequest extends HttpPacket { /** * 设置好header后,会把cookie等头部信息也设置好 * @param headers the headers to set - * @param channelContext */ @Override public void setHeaders(Map headers) { diff --git a/jim-common/src/main/java/org/jim/common/http/HttpRequestDecoder.java b/jim-common/src/main/java/org/jim/common/http/HttpRequestDecoder.java index d0b5262..ed5a82c 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpRequestDecoder.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpRequestDecoder.java @@ -7,24 +7,23 @@ import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; -import org.jim.common.http.HttpConst.RequestBodyFormat; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.exception.ImDecodeException; import org.jim.common.utils.HttpParseUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.ChannelContext; -import org.tio.core.exception.AioDecodeException; import org.tio.core.exception.LengthOverflowException; import org.tio.core.utils.ByteBufferUtils; - -import cn.hutool.core.util.StrUtil; +import org.tio.utils.hutool.StrUtil; /** * * @author WChao * */ -public class HttpRequestDecoder { - public static enum Step { +public class HttpRequestDecoder implements ImConst { + public enum Step { firstLine, header, body } @@ -40,7 +39,7 @@ public class HttpRequestDecoder { */ public static final int MAX_LENGTH_OF_HEADER_LINE = 2048; - public static HttpRequest decode(ByteBuffer buffer, ChannelContext channelContext,boolean isBody) throws AioDecodeException { + public static HttpRequest decode(ByteBuffer buffer, ImChannelContext channelContext, boolean isBody) throws ImDecodeException { int initPosition = buffer.position(); int readableLength = buffer.limit() - initPosition; // int count = 0; @@ -48,7 +47,7 @@ public class HttpRequestDecoder { // StringBuilder currLine = new StringBuilder(); Map headers = new HashMap<>(); int contentLength = 0; - byte[] bodyBytes = null; + byte[] bodyBytes; StringBuilder headerSb = new StringBuilder(512); RequestLine firstLine = null; @@ -57,12 +56,12 @@ public class HttpRequestDecoder { try { line = ByteBufferUtils.readLine(buffer, null, MAX_LENGTH_OF_HEADER_LINE); } catch (LengthOverflowException e) { - throw new AioDecodeException(e); + throw new ImDecodeException(e); } int newPosition = buffer.position(); if (newPosition - initPosition > MAX_LENGTH_OF_HEADER) { - throw new AioDecodeException("max http header length " + MAX_LENGTH_OF_HEADER); + throw new ImDecodeException("max http header length " + MAX_LENGTH_OF_HEADER); } if (line == null) { @@ -72,7 +71,7 @@ public class HttpRequestDecoder { headerSb.append(line).append("\r\n"); //头部解析完成了 if ("".equals(line) && isBody) { - String contentLengthStr = headers.get(HttpConst.RequestHeaderKey.Content_Length); + String contentLengthStr = headers.get(Http.RequestHeaderKey.Content_Length); if (StringUtils.isBlank(contentLengthStr)) { contentLength = 0; } else { @@ -109,13 +108,13 @@ public class HttpRequestDecoder { return null; } - if (!headers.containsKey(HttpConst.RequestHeaderKey.Host)) { - throw new AioDecodeException("there is no host header"); + if (!headers.containsKey(Http.RequestHeaderKey.Host)) { + throw new ImDecodeException("there is no host header"); } HttpRequest httpRequest = new HttpRequest(channelContext.getClientNode()); - httpRequest.setChannelContext(channelContext); - httpRequest.setHttpConfig((HttpConfig) channelContext.getGroupContext().getAttribute(GroupContextKey.HTTP_SERVER_CONFIG)); + httpRequest.setImChannelContext(channelContext); + httpRequest.setHttpConfig((HttpConfig) channelContext.getAttribute(Key.HTTP_SERVER_CONFIG)); httpRequest.setHeaderString(headerSb.toString()); httpRequest.setRequestLine(firstLine); httpRequest.setHeaders(headers); @@ -136,7 +135,7 @@ public class HttpRequestDecoder { } - public static void decodeParams(Map params, String paramsStr, String charset, ChannelContext channelContext) { + public static void decodeParams(Map params, String paramsStr, String charset, ImChannelContext channelContext) { if (StrUtil.isBlank(paramsStr)) { return; } @@ -175,18 +174,18 @@ public class HttpRequestDecoder { * @param firstLine * @param bodyBytes * @param channelContext - * @throws AioDecodeException + * @throws ImDecodeException * @author WChao */ - private static void parseBody(HttpRequest httpRequest, RequestLine firstLine, byte[] bodyBytes, ChannelContext channelContext) throws AioDecodeException { + private static void parseBody(HttpRequest httpRequest, RequestLine firstLine, byte[] bodyBytes, ImChannelContext channelContext) throws ImDecodeException { parseBodyFormat(httpRequest, httpRequest.getHeaders()); - RequestBodyFormat bodyFormat = httpRequest.getBodyFormat(); + Http.RequestBodyFormat bodyFormat = httpRequest.getBodyFormat(); httpRequest.setBody(bodyBytes); - if (bodyFormat == RequestBodyFormat.MULTIPART) { + if (bodyFormat == Http.RequestBodyFormat.MULTIPART) { if (log.isInfoEnabled()) { - String bodyString = null; + String bodyString; if (bodyBytes != null && bodyBytes.length > 0) { if (log.isDebugEnabled()) { try { @@ -200,7 +199,7 @@ public class HttpRequestDecoder { } //【multipart/form-data; boundary=----WebKitFormBoundaryuwYcfA2AIgxqIxA0】 - String initBoundary = HttpParseUtils.getPerprotyEqualValue(httpRequest.getHeaders(), HttpConst.RequestHeaderKey.Content_Type, "boundary"); + String initBoundary = HttpParseUtils.getPerprotyEqualValue(httpRequest.getHeaders(), Http.RequestHeaderKey.Content_Type, "boundary"); log.debug("{}, initBoundary:{}", channelContext, initBoundary); HttpMultiBodyDecoder.decode(httpRequest, firstLine, bodyBytes, initBoundary, channelContext); } else { @@ -217,7 +216,7 @@ public class HttpRequestDecoder { } } - if (bodyFormat == RequestBodyFormat.URLENCODED) { + if (bodyFormat == Http.RequestBodyFormat.URLENCODED) { parseUrlencoded(httpRequest, firstLine, bodyBytes, bodyString, channelContext); } } @@ -231,19 +230,19 @@ public class HttpRequestDecoder { * @author WChao */ public static void parseBodyFormat(HttpRequest httpRequest, Map headers) { - String Content_Type = StringUtils.lowerCase(headers.get(HttpConst.RequestHeaderKey.Content_Type)); - RequestBodyFormat bodyFormat = null; - if (StringUtils.contains(Content_Type, HttpConst.RequestHeaderValue.Content_Type.application_x_www_form_urlencoded)) { - bodyFormat = RequestBodyFormat.URLENCODED; - } else if (StringUtils.contains(Content_Type, HttpConst.RequestHeaderValue.Content_Type.multipart_form_data)) { - bodyFormat = RequestBodyFormat.MULTIPART; + String Content_Type = StringUtils.lowerCase(headers.get(Http.RequestHeaderKey.Content_Type)); + Http.RequestBodyFormat bodyFormat; + if (StringUtils.contains(Content_Type, Http.RequestHeaderValue.Content_Type.application_x_www_form_urlencoded)) { + bodyFormat = Http.RequestBodyFormat.URLENCODED; + } else if (StringUtils.contains(Content_Type, Http.RequestHeaderValue.Content_Type.multipart_form_data)) { + bodyFormat = Http.RequestBodyFormat.MULTIPART; } else { - bodyFormat = RequestBodyFormat.TEXT; + bodyFormat = Http.RequestBodyFormat.TEXT; } httpRequest.setBodyFormat(bodyFormat); if (StringUtils.isNotBlank(Content_Type)) { - String charset = HttpParseUtils.getPerprotyEqualValue(headers, HttpConst.RequestHeaderKey.Content_Type, "charset"); + String charset = HttpParseUtils.getPerprotyEqualValue(headers, Http.RequestHeaderKey.Content_Type, "charset"); if (StringUtils.isNotBlank(charset)) { httpRequest.setCharset(charset); } @@ -284,7 +283,7 @@ public class HttpRequestDecoder { * 2017年2月23日 下午1:37:51 * */ - public static RequestLine parseRequestLine(String line, ChannelContext channelContext) throws AioDecodeException { + public static RequestLine parseRequestLine(String line, ImChannelContext channelContext) throws ImDecodeException { try { int index1 = line.indexOf(' '); String _method = StringUtils.upperCase(line.substring(0, index1)); @@ -322,7 +321,7 @@ public class HttpRequestDecoder { return requestLine; } catch (Throwable e) { log.error(channelContext.toString(), e); - throw new AioDecodeException(e); + throw new ImDecodeException(e); } } @@ -331,7 +330,7 @@ public class HttpRequestDecoder { * 形如: 【Content-Type : application/x-www-form-urlencoded; charset=UTF-8】 * @author WChao */ - private static void parseUrlencoded(HttpRequest httpRequest, RequestLine firstLine, byte[] bodyBytes, String bodyString, ChannelContext channelContext) { + private static void parseUrlencoded(HttpRequest httpRequest, RequestLine firstLine, byte[] bodyBytes, String bodyString, ImChannelContext channelContext) { if (StringUtils.isNotBlank(bodyString)) { decodeParams(httpRequest.getParams(), bodyString, httpRequest.getCharset(), channelContext); } @@ -343,7 +342,7 @@ public class HttpRequestDecoder { * @param firstLine * @param channelContext */ - private static void parseQueryString(HttpRequest httpRequest, RequestLine firstLine, ChannelContext channelContext) { + private static void parseQueryString(HttpRequest httpRequest, RequestLine firstLine, ImChannelContext channelContext) { String paramStr = firstLine.getQuery(); if (StringUtils.isNotBlank(paramStr)) { decodeParams(httpRequest.getParams(), paramStr, httpRequest.getCharset(), channelContext); diff --git a/jim-common/src/main/java/org/jim/common/http/HttpResponse.java b/jim-common/src/main/java/org/jim/common/http/HttpResponse.java index 6d08dfc..c438582 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpResponse.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpResponse.java @@ -2,12 +2,11 @@ package org.jim.common.http; import java.util.ArrayList; import java.util.List; - import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.tio.utils.hutool.ZipUtil; -import cn.hutool.core.util.ZipUtil; /** * * @author WChao @@ -36,12 +35,11 @@ public class HttpResponse extends HttpPacket { */ private boolean isStaticRes = false; - private HttpRequest request = null; + private HttpRequest request; + private volatile List cookies = null; - // private int contentLength; - // private byte[] bodyBytes; - private String charset = HttpConst.CHARSET_NAME; + private String charset = Http.CHARSET_NAME; /** * 已经编码好的byte[] @@ -57,29 +55,29 @@ public class HttpResponse extends HttpPacket { public HttpResponse(HttpRequest request, HttpConfig httpConfig) { this.request = request; - String Connection = StringUtils.lowerCase(request.getHeader(HttpConst.RequestHeaderKey.Connection)); + String Connection = StringUtils.lowerCase(request.getHeader(Http.RequestHeaderKey.Connection)); RequestLine requestLine = request.getRequestLine(); String version = requestLine.getVersion(); if ("1.0".equals(version)) { - if (StringUtils.equals(Connection, HttpConst.RequestHeaderValue.Connection.keep_alive)) { - addHeader(HttpConst.ResponseHeaderKey.Connection, HttpConst.ResponseHeaderValue.Connection.keep_alive); - addHeader(HttpConst.ResponseHeaderKey.Keep_Alive, "timeout=10, max=20"); + if (StringUtils.equals(Connection, Http.RequestHeaderValue.Connection.keep_alive)) { + addHeader(Http.ResponseHeaderKey.Connection, Http.ResponseHeaderValue.Connection.keep_alive); + addHeader(Http.ResponseHeaderKey.Keep_Alive, "timeout=10, max=20"); } else { - addHeader(HttpConst.ResponseHeaderKey.Connection, HttpConst.ResponseHeaderValue.Connection.close); + addHeader(Http.ResponseHeaderKey.Connection, Http.ResponseHeaderValue.Connection.close); } } else { - if (StringUtils.equals(Connection, HttpConst.RequestHeaderValue.Connection.close)) { - addHeader(HttpConst.ResponseHeaderKey.Connection, HttpConst.ResponseHeaderValue.Connection.close); + if (StringUtils.equals(Connection, Http.RequestHeaderValue.Connection.close)) { + addHeader(Http.ResponseHeaderKey.Connection, Http.ResponseHeaderValue.Connection.close); } else { - addHeader(HttpConst.ResponseHeaderKey.Connection, HttpConst.ResponseHeaderValue.Connection.keep_alive); - addHeader(HttpConst.ResponseHeaderKey.Keep_Alive, "timeout=10, max=20"); + addHeader(Http.ResponseHeaderKey.Connection, Http.ResponseHeaderValue.Connection.keep_alive); + addHeader(Http.ResponseHeaderKey.Keep_Alive, "timeout=10, max=20"); } } //暂时先设置为短连接...防止服务器一直不释放资源; - addHeader(HttpConst.ResponseHeaderKey.Connection, HttpConst.ResponseHeaderValue.Connection.close); + addHeader(Http.ResponseHeaderKey.Connection, Http.ResponseHeaderValue.Connection.close); if (httpConfig != null) { - addHeader(HttpConst.ResponseHeaderKey.Server, httpConfig.getServerInfo()); + addHeader(Http.ResponseHeaderKey.Server, httpConfig.getServerInfo()); } } @@ -137,11 +135,11 @@ public class HttpResponse extends HttpPacket { byte[] bs2 = ZipUtil.gzip(bs); if (bs2.length < bs.length) { this.body = bs2; - this.addHeader(HttpConst.ResponseHeaderKey.Content_Encoding, "gzip"); + this.addHeader(Http.ResponseHeaderKey.Content_Encoding, "gzip"); } } } else { - log.info("{} 竟然不支持gzip, {}", request.getChannelContext(), request.getHeader(HttpConst.RequestHeaderKey.User_Agent)); + log.info("{} 竟然不支持gzip, {}", request.getImChannelContext(), request.getHeader(Http.RequestHeaderKey.User_Agent)); } } diff --git a/jim-common/src/main/java/org/jim/common/http/HttpResponseEncoder.java b/jim-common/src/main/java/org/jim/common/http/HttpResponseEncoder.java index e9b4337..f985b94 100644 --- a/jim-common/src/main/java/org/jim/common/http/HttpResponseEncoder.java +++ b/jim-common/src/main/java/org/jim/common/http/HttpResponseEncoder.java @@ -6,18 +6,18 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; - /** * * @author wchao * 2017年8月4日 上午9:41:12 */ -public class HttpResponseEncoder { - public static enum Step { +public class HttpResponseEncoder implements ImConst { + public enum Step { firstLine, header, body } @@ -28,13 +28,12 @@ public class HttpResponseEncoder { /** * * @param httpResponse - * @param groupContext * @param channelContext * @param skipCookie true: 忽略掉cookie部分的编码 * @return - * @author wchao + * @author WChao */ - public static ByteBuffer encode(HttpResponse httpResponse, GroupContext groupContext, ChannelContext channelContext, boolean skipCookie) { + public static ByteBuffer encode(HttpResponse httpResponse, ImChannelContext channelContext, boolean skipCookie) { byte[] encodedBytes = httpResponse.getEncodedBytes(); if (encodedBytes != null) { ByteBuffer ret = ByteBuffer.wrap(encodedBytes); @@ -56,7 +55,7 @@ public class HttpResponseEncoder { Map headers = httpResponse.getHeaders(); if (headers != null && headers.size() > 0) { - headers.put(HttpConst.ResponseHeaderKey.Content_Length, bodyLength + ""); + headers.put(Http.ResponseHeaderKey.Content_Length, bodyLength + ""); Set> set = headers.entrySet(); for (Entry entry : set) { sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n"); @@ -68,7 +67,7 @@ public class HttpResponseEncoder { List cookies = httpResponse.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { - sb.append(HttpConst.ResponseHeaderKey.Set_Cookie).append(": "); + sb.append(Http.ResponseHeaderKey.Set_Cookie).append(": "); sb.append(cookie.toString()); sb.append("\r\n"); if (log.isInfoEnabled()) { diff --git a/jim-common/src/main/java/org/jim/common/http/handler/IHttpRequestHandler.java b/jim-common/src/main/java/org/jim/common/http/handler/IHttpRequestHandler.java index 1c81351..b1455a9 100644 --- a/jim-common/src/main/java/org/jim/common/http/handler/IHttpRequestHandler.java +++ b/jim-common/src/main/java/org/jim/common/http/handler/IHttpRequestHandler.java @@ -1,5 +1,6 @@ package org.jim.common.http.handler; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpRequest; import org.jim.common.http.HttpResponse; import org.jim.common.http.RequestLine; @@ -15,16 +16,15 @@ public interface IHttpRequestHandler { * @param packet * @param requestLine * @return - * @throws Exception + * @throws ImException * @author wchao */ - public HttpResponse handler(HttpRequest packet, RequestLine requestLine) throws Exception; + public HttpResponse handler(HttpRequest packet, RequestLine requestLine) throws ImException; /** * * @param request * @param requestLine - * @param channelContext * @return * @author wchao */ diff --git a/jim-common/src/main/java/org/jim/common/http/session/HttpSession.java b/jim-common/src/main/java/org/jim/common/http/session/HttpSession.java index 680b876..b15ffe6 100644 --- a/jim-common/src/main/java/org/jim/common/http/session/HttpSession.java +++ b/jim-common/src/main/java/org/jim/common/http/session/HttpSession.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.jim.common.ImChannelContext; import org.jim.common.ImSessionContext; import org.jim.common.http.HttpConfig; @@ -18,15 +19,16 @@ public class HttpSession extends ImSessionContext implements java.io.Serializabl private Map data = new ConcurrentHashMap<>(); - private String id = null; - - public HttpSession() { + public HttpSession(String id){ + this(id, null); } - /** - * @author wchao - */ - public HttpSession(String id) { + public HttpSession(ImChannelContext imChannelContext){ + this(null, imChannelContext); + } + + public HttpSession(String id, ImChannelContext imChannelContext){ + super(imChannelContext); this.id = id; } diff --git a/jim-common/src/main/java/org/jim/common/listener/AbstractImBindListener.java b/jim-common/src/main/java/org/jim/common/listener/AbstractImBindListener.java index 410347a..81ce5eb 100644 --- a/jim-common/src/main/java/org/jim/common/listener/AbstractImBindListener.java +++ b/jim-common/src/main/java/org/jim/common/listener/AbstractImBindListener.java @@ -4,7 +4,7 @@ package org.jim.common.listener; import org.jim.common.ImConst; -import org.jim.common.ImConfig; +import org.jim.common.config.ImConfig; /** * @author WChao * 2018/08/26 diff --git a/jim-common/src/main/java/org/jim/common/listener/ImBindListener.java b/jim-common/src/main/java/org/jim/common/listener/ImBindListener.java index 17714da..c06a9e9 100644 --- a/jim-common/src/main/java/org/jim/common/listener/ImBindListener.java +++ b/jim-common/src/main/java/org/jim/common/listener/ImBindListener.java @@ -1,6 +1,7 @@ package org.jim.common.listener; -import org.tio.core.ChannelContext; +import org.jim.common.ImChannelContext; +import org.jim.common.exception.ImException; /** * IM绑定用户及群组监听器; @@ -10,39 +11,39 @@ import org.tio.core.ChannelContext; public interface ImBindListener { /** * 绑定群组后回调该方法 - * @param channelContext + * @param imChannelContext * @param group * @throws Exception */ - void onAfterGroupBind(ChannelContext channelContext, String group) throws Exception; + void onAfterGroupBind(ImChannelContext imChannelContext, String group) throws ImException; /** * 解绑群组后回调该方法 - * @param channelContext + * @param imChannelContext * @param group * @throws Exception */ - void onAfterGroupUnbind(ChannelContext channelContext, String group) throws Exception; + void onAfterGroupUnbind(ImChannelContext imChannelContext, String group) throws ImException; /** * 绑定用户后回调该方法 - * @param channelContext + * @param imChannelContext * @param userId * @throws Exception */ - void onAfterUserBind(ChannelContext channelContext, String userId) throws Exception; + void onAfterUserBind(ImChannelContext imChannelContext, String userId) throws ImException; /** * 解绑用户后回调该方法 - * @param channelContext + * @param imChannelContext * @param userId * @throws Exception */ - void onAfterUserUnbind(ChannelContext channelContext, String userId) throws Exception; + void onAfterUserUnbind(ImChannelContext imChannelContext, String userId) throws Exception; /** * 更新用户终端协议类型及在线状态; - * @param channelContext + * @param imChannelContext * @param terminal(ws、tcp、http、android、ios等) * @param status(online、offline) */ - void initUserTerminal(ChannelContext channelContext , String terminal , String status); + void initUserTerminal(ImChannelContext imChannelContext , String terminal , String status); } diff --git a/jim-common/src/main/java/org/jim/common/listener/ImGroupListener.java b/jim-common/src/main/java/org/jim/common/listener/ImGroupListener.java new file mode 100644 index 0000000..a543fcb --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/listener/ImGroupListener.java @@ -0,0 +1,32 @@ +package org.jim.common.listener; + +import org.jim.common.ImChannelContext; +import org.jim.common.exception.ImException; +import org.tio.core.ChannelContext; + +/** + * @ClassName ImGroupListener + * @Description TODO + * @Author WChao + * @Date 2020/1/12 14:17 + * @Version 1.0 + **/ +public interface ImGroupListener { + /** + * 绑定群组后回调该方法 + * @param imChannelContext + * @param group + * @throws ImException + * @author WChao + */ + void onAfterBind(ImChannelContext imChannelContext, String group) throws ImException; + + /** + * 解绑群组后回调该方法 + * @param imChannelContext + * @param group + * @throws ImException + * @author WChao + */ + void onAfterUnbind(ImChannelContext imChannelContext, String group) throws ImException; +} diff --git a/jim-common/src/main/java/org/jim/common/listener/ImGroupListenerAdapter.java b/jim-common/src/main/java/org/jim/common/listener/ImGroupListenerAdapter.java new file mode 100644 index 0000000..c4bc42d --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/listener/ImGroupListenerAdapter.java @@ -0,0 +1,34 @@ +package org.jim.common.listener; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.tio.core.ChannelContext; +import org.tio.core.intf.GroupListener; + +/** + * @ClassName ImGroupListenerAdapter + * @Description TODO + * @Author WChao + * @Date 2020/1/12 14:19 + * @Version 1.0 + **/ +public class ImGroupListenerAdapter implements GroupListener, ImConst { + + private ImGroupListener imGroupListener; + + public ImGroupListenerAdapter(ImGroupListener imGroupListener){ + this.imGroupListener = imGroupListener; + } + + @Override + public void onAfterBind(ChannelContext channelContext, String group) throws Exception { + ImChannelContext imChannelContext = (ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY); + imGroupListener.onAfterBind(imChannelContext, group); + } + + @Override + public void onAfterUnbind(ChannelContext channelContext, String group) throws Exception { + ImChannelContext imChannelContext = (ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY); + imGroupListener.onAfterBind(imChannelContext, group); + } +} diff --git a/jim-common/src/main/java/org/jim/common/listener/ImListener.java b/jim-common/src/main/java/org/jim/common/listener/ImListener.java new file mode 100644 index 0000000..2060e60 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/listener/ImListener.java @@ -0,0 +1,75 @@ +package org.jim.common.listener; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImPacket; +import org.tio.core.ChannelContext; +import org.tio.core.intf.Packet; + +/** + * @ClassName ImListener + * @Description TODO + * @Author WChao + * @Date 2020/1/4 11:09 + * @Version 1.0 + **/ +public interface ImListener { + /** + * 建链后触发本方法,注:建链不一定成功,需要关注参数isConnected + * @param imChannelContext + * @param isConnected 是否连接成功,true:表示连接成功,false:表示连接失败 + * @param isReconnect 是否是重连, true: 表示这是重新连接,false: 表示这是第一次连接 + * @throws Exception + * @author: WChao + */ + void onAfterConnected(ImChannelContext imChannelContext, boolean isConnected, boolean isReconnect) throws Exception; + + /** + * 原方法名:onAfterDecoded + * 解码成功后触发本方法 + * @param imChannelContext + * @param packet + * @param packetSize + * @throws Exception + * @author: WChao + */ + void onAfterDecoded(ImChannelContext imChannelContext, ImPacket packet, int packetSize) throws Exception; + + /** + * 接收到TCP层传过来的数据后 + * @param imChannelContext + * @param receivedBytes 本次接收了多少字节 + * @throws Exception + */ + void onAfterReceivedBytes(ImChannelContext imChannelContext, int receivedBytes) throws Exception; + + /** + * 消息包发送之后触发本方法 + * @param imChannelContext + * @param packet + * @param isSentSuccess true:发送成功,false:发送失败 + * @throws Exception + * @author WChao + */ + void onAfterSent(ImChannelContext imChannelContext, ImPacket packet, boolean isSentSuccess) throws Exception; + + /** + * 处理一个消息包后 + * @param imChannelContext + * @param packet + * @param cost 本次处理消息耗时,单位:毫秒 + * @throws Exception + */ + void onAfterHandled(ImChannelContext imChannelContext, ImPacket packet, long cost) throws Exception; + + /** + * 连接关闭前触发本方法 + * @param imChannelContext + * @param throwable the throwable 有可能为空 + * @param remark the remark 有可能为空 + * @param isRemove + * @author WChao + * @throws Exception + */ + void onBeforeClose(ImChannelContext imChannelContext, Throwable throwable, String remark, boolean isRemove) throws Exception; + +} diff --git a/jim-common/src/main/java/org/jim/common/listener/ImUserListener.java b/jim-common/src/main/java/org/jim/common/listener/ImUserListener.java new file mode 100644 index 0000000..e7699f2 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/listener/ImUserListener.java @@ -0,0 +1,31 @@ +package org.jim.common.listener; + +import org.jim.common.ImChannelContext; +import org.jim.common.exception.ImException; + +/** + * @ClassName ImUserListener + * @Description TODO + * @Author WChao + * @Date 2020/1/12 14:24 + * @Version 1.0 + **/ +public interface ImUserListener { + /** + * 绑定用户后回调该方法 + * @param imChannelContext + * @param userId + * @throws Exception + * @author WChao + */ + void onAfterBind(ImChannelContext imChannelContext, String userId) throws ImException; + + /** + * 解绑用户后回调该方法 + * @param imChannelContext + * @param userId + * @throws Exception + * @author WChao + */ + void onAfterUnbind(ImChannelContext imChannelContext, String userId) throws ImException; +} diff --git a/jim-common/src/main/java/org/jim/common/message/AbstractMessageHelper.java b/jim-common/src/main/java/org/jim/common/message/AbstractMessageHelper.java index ba0ca60..dac6022 100644 --- a/jim-common/src/main/java/org/jim/common/message/AbstractMessageHelper.java +++ b/jim-common/src/main/java/org/jim/common/message/AbstractMessageHelper.java @@ -4,7 +4,7 @@ package org.jim.common.message; import org.jim.common.ImConst; -import org.jim.common.ImConfig; +import org.jim.common.config.ImConfig; /** * @author HP diff --git a/jim-common/src/main/java/org/jim/common/packets/JoinGroupNotifyRespBody.java b/jim-common/src/main/java/org/jim/common/packets/JoinGroupNotifyRespBody.java index 5840410..55dd5a1 100644 --- a/jim-common/src/main/java/org/jim/common/packets/JoinGroupNotifyRespBody.java +++ b/jim-common/src/main/java/org/jim/common/packets/JoinGroupNotifyRespBody.java @@ -3,17 +3,23 @@ */ package org.jim.common.packets; +import org.jim.common.ImStatus; +import org.jim.common.Status; + /** * 版本: [1.0] * 功能说明: 进入群组通知消息体 * 作者: WChao 创建时间: 2017年7月26日 下午5:14:04 */ -public class JoinGroupNotifyRespBody extends Message{ +public class JoinGroupNotifyRespBody extends RespBody{ private static final long serialVersionUID = 3828976681110713803L; private User user; private String group; - + + public JoinGroupNotifyRespBody(Command command, Status status){ + super(command,status); + } public User getUser() { return user; } diff --git a/jim-common/src/main/java/org/jim/common/packets/JoinGroupRespBody.java b/jim-common/src/main/java/org/jim/common/packets/JoinGroupRespBody.java index 4ca9d0b..ddea079 100644 --- a/jim-common/src/main/java/org/jim/common/packets/JoinGroupRespBody.java +++ b/jim-common/src/main/java/org/jim/common/packets/JoinGroupRespBody.java @@ -3,6 +3,8 @@ */ package org.jim.common.packets; +import org.jim.common.Status; + /** * 版本: [1.0] * 功能说明: 加入群组响应 @@ -13,6 +15,10 @@ public class JoinGroupRespBody extends RespBody { private static final long serialVersionUID = 6635620192752369689L; public JoinGroupResult result; public String group; + + public JoinGroupRespBody(Command command , Status status){ + super(command, status); + } public JoinGroupResult getResult() { return result; } diff --git a/jim-common/src/main/java/org/jim/common/packets/RespBody.java b/jim-common/src/main/java/org/jim/common/packets/RespBody.java index 007a962..b710ac3 100644 --- a/jim-common/src/main/java/org/jim/common/packets/RespBody.java +++ b/jim-common/src/main/java/org/jim/common/packets/RespBody.java @@ -15,16 +15,23 @@ import org.jim.common.utils.JsonKit; public class RespBody implements Serializable{ private static final long serialVersionUID = 1L; + /** + * 响应状态码; + */ + private Integer code; + /** + * 响应状态信息提示; + */ + private String msg; + /** + * 响应cmd命令码; + */ + private Command command; + /** + * 响应数据; + */ + private Object data; - private Integer code;//响应状态码; - - private String msg;//响应状态信息提示; - - private Command command;//响应cmd命令码; - - private Object data;//响应数据; - - public RespBody(){} public RespBody(Command command){ this.command = command; } diff --git a/jim-common/src/main/java/org/jim/common/packets/User.java b/jim-common/src/main/java/org/jim/common/packets/User.java index 131a721..380ed60 100644 --- a/jim-common/src/main/java/org/jim/common/packets/User.java +++ b/jim-common/src/main/java/org/jim/common/packets/User.java @@ -11,7 +11,7 @@ import java.util.List; /** * 版本: [1.0] * 功能说明: - * 作者: WChao 创建时间: 2017年7月26日 下午3:13:47 + * @author : WChao 创建时间: 2017年7月26日 下午3:13:47 */ public class User implements Serializable{ diff --git a/jim-common/src/main/java/org/jim/common/protocol/AbProtocol.java b/jim-common/src/main/java/org/jim/common/protocol/AbProtocol.java deleted file mode 100644 index 798ad32..0000000 --- a/jim-common/src/main/java/org/jim/common/protocol/AbProtocol.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * - */ -package org.jim.common.protocol; - -import java.nio.ByteBuffer; - -import org.tio.core.ChannelContext; - -/** - * @author WChao - * @date 2018-09-05 23:52:00 - */ -public abstract class AbProtocol implements IProtocol { - /** - * 协议包转化器; - */ - private IConvertProtocolPacket converter; - - public AbProtocol(){ - this.converter = converter(); - } - - /** - * 根据buffer判断是否属于指定协议 - * @param buffer - * @param channelContext - * @return - * @throws Throwable - */ - public abstract boolean isProtocolByBuffer(ByteBuffer buffer,ChannelContext channelContext) throws Throwable; - - public boolean isProtocol(ByteBuffer buffer,ChannelContext channelContext) throws Throwable { - ByteBuffer copyByteBuffer = null; - if(buffer != null && channelContext.getAttribute() == null){ - copyByteBuffer = ByteBuffer.wrap(buffer.array()); - } - return isProtocolByBuffer(copyByteBuffer, channelContext); - } - public IConvertProtocolPacket getConverter() { - return converter; - } -} diff --git a/jim-common/src/main/java/org/jim/common/protocol/AbstractProtocol.java b/jim-common/src/main/java/org/jim/common/protocol/AbstractProtocol.java new file mode 100644 index 0000000..58a41f8 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/protocol/AbstractProtocol.java @@ -0,0 +1,90 @@ +/** + * + */ +package org.jim.common.protocol; + +import java.nio.ByteBuffer; +import java.util.Objects; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.ImPacket; +import org.jim.common.ImSessionContext; +import org.jim.common.exception.ImException; +/** + * @author WChao + * @date 2018-09-05 23:52:00 + */ +public abstract class AbstractProtocol implements IProtocol,ImConst { + /** + * 协议包转化器; + */ + protected IProtocolConverter converter; + + public AbstractProtocol(IProtocolConverter converter){ + this.converter = converter; + } + /** + * 协议初始化 + * @param imChannelContext + */ + protected abstract void init(ImChannelContext imChannelContext); + /** + * 根据buffer判断是否属于指定协议 + * @param buffer + * @param imChannelContext + * @return + * @throws ImException + */ + protected abstract boolean validateProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException; + + /** + * 根据SessionContext判断协议 + * @param imSessionContext + * @return + * @throws ImException + */ + protected abstract boolean validateProtocol(ImSessionContext imSessionContext) throws ImException; + + /** + * 根据imPacket判断是否属于指定协议 + * @param imPacket + * @return + * @throws ImException + */ + protected abstract boolean validateProtocol(ImPacket imPacket) throws ImException; + + @Override + public boolean isProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException { + ImSessionContext imSessionContext = imChannelContext.getSessionContext(); + if(Objects.isNull(imSessionContext) && Objects.isNull(buffer)){ + return false; + }else if(Objects.isNull(imSessionContext) && Objects.nonNull(buffer)){ + boolean isProtocol = validateProtocol(ByteBuffer.wrap(buffer.array()), imChannelContext); + if(isProtocol){ + init(imChannelContext); + } + return isProtocol; + }else{ + return validateProtocol(imSessionContext); + } + } + + @Override + public boolean isProtocol(ImPacket imPacket, ImChannelContext imChannelContext) throws ImException { + ImSessionContext sessionContext = imChannelContext.getSessionContext(); + if(Objects.isNull(imPacket)){ + return false; + } + boolean isProtocol = validateProtocol(imPacket); + if(isProtocol && Objects.isNull(sessionContext)) { + init(imChannelContext); + } + return isProtocol; + } + + public IProtocolConverter getConverter() { + return converter; + } + +} diff --git a/jim-common/src/main/java/org/jim/common/protocol/IProtocol.java b/jim-common/src/main/java/org/jim/common/protocol/IProtocol.java index 455cd35..0dc380f 100644 --- a/jim-common/src/main/java/org/jim/common/protocol/IProtocol.java +++ b/jim-common/src/main/java/org/jim/common/protocol/IProtocol.java @@ -3,8 +3,11 @@ */ package org.jim.common.protocol; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; -import org.tio.core.ChannelContext; +import org.jim.common.exception.ImException; + +import java.nio.ByteBuffer; /** * 判断协议接口 @@ -16,20 +19,23 @@ public interface IProtocol { * 协议名称 * @return 如:http、ws、tcp等 */ - public String name(); + String name(); /** - * 判断是否属于指定协议 + * 根据buffer判断是否属于指定协议 + * @param buffer + * @param imChannelContext + * @return + * @throws ImException + */ + boolean isProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException; + + /** + * 根据imPacket判断是否属于指定协议 * @param imPacket - * @param channelContext + * @param imChannelContext * @return - * @throws Throwable + * @throws ImException */ - public boolean isProtocol(ImPacket imPacket,ChannelContext channelContext)throws Throwable; - - /** - * 获取该协议包转化器 - * @return - */ - public IConvertProtocolPacket converter(); + boolean isProtocol(ImPacket imPacket, ImChannelContext imChannelContext)throws ImException; } diff --git a/jim-common/src/main/java/org/jim/common/protocol/IConvertProtocolPacket.java b/jim-common/src/main/java/org/jim/common/protocol/IProtocolConverter.java similarity index 51% rename from jim-common/src/main/java/org/jim/common/protocol/IConvertProtocolPacket.java rename to jim-common/src/main/java/org/jim/common/protocol/IProtocolConverter.java index d480dbf..cba7be5 100644 --- a/jim-common/src/main/java/org/jim/common/protocol/IConvertProtocolPacket.java +++ b/jim-common/src/main/java/org/jim/common/protocol/IProtocolConverter.java @@ -3,30 +3,29 @@ */ package org.jim.common.protocol; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.jim.common.packets.Command; -import org.tio.core.ChannelContext; - /** * 转换不同协议消息包; * @author WChao * */ -public interface IConvertProtocolPacket { +public interface IProtocolConverter { /** * 转化请求包 * @param body * @param command - * @param channelContext + * @param imChannelContext * @return */ - public ImPacket ReqPacket(byte[] body,Command command, ChannelContext channelContext); + ImPacket ReqPacket(byte[] body,Command command, ImChannelContext imChannelContext); /** * 转化响应包 * @param body * @param command - * @param channelContext + * @param imChannelContext * @return */ - public ImPacket RespPacket(byte[] body,Command command, ChannelContext channelContext); + ImPacket RespPacket(byte[] body,Command command, ImChannelContext imChannelContext); } diff --git a/jim-common/src/main/java/org/jim/common/session/id/impl/UUIDSessionIdGenerator.java b/jim-common/src/main/java/org/jim/common/session/id/impl/UUIDSessionIdGenerator.java index cd99a41..3e2c4cc 100644 --- a/jim-common/src/main/java/org/jim/common/session/id/impl/UUIDSessionIdGenerator.java +++ b/jim-common/src/main/java/org/jim/common/session/id/impl/UUIDSessionIdGenerator.java @@ -5,9 +5,10 @@ import org.slf4j.LoggerFactory; import org.jim.common.http.HttpConfig; import org.jim.common.session.id.ISessionIdGenerator; -import cn.hutool.core.util.RandomUtil; +import java.util.UUID; + /** - * @author wchao + * @author WChao * 2017年8月15日 上午10:53:39 */ public class UUIDSessionIdGenerator implements ISessionIdGenerator { @@ -39,6 +40,6 @@ public class UUIDSessionIdGenerator implements ISessionIdGenerator { */ @Override public String sessionId(HttpConfig httpConfig) { - return RandomUtil.randomUUID().replace("-", ""); + return UUID.randomUUID().toString().replace("-", ""); } } diff --git a/jim-common/src/main/java/org/jim/common/tcp/TcpConvertPacket.java b/jim-common/src/main/java/org/jim/common/tcp/TcpConvertPacket.java index b81761d..b293347 100644 --- a/jim-common/src/main/java/org/jim/common/tcp/TcpConvertPacket.java +++ b/jim-common/src/main/java/org/jim/common/tcp/TcpConvertPacket.java @@ -3,27 +3,28 @@ */ package org.jim.common.tcp; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; +import org.jim.common.ImSessionContext; import org.jim.common.packets.Command; -import org.jim.common.protocol.IConvertProtocolPacket; -import org.tio.core.ChannelContext; +import org.jim.common.protocol.IProtocolConverter; /** * TCP协议消息转化包 * @author WChao * */ -public class TcpConvertPacket implements IConvertProtocolPacket { +public class TcpConvertPacket implements IProtocolConverter { /** * 转TCP协议响应包; */ @Override - public ImPacket RespPacket(byte[] body, Command command,ChannelContext channelContext) { - Object sessionContext = channelContext.getAttribute(); - if(sessionContext instanceof TcpSessionContext){//转TCP协议响应包; + public ImPacket RespPacket(byte[] body, Command command, ImChannelContext imChannelContext) { + ImSessionContext sessionContext = imChannelContext.getSessionContext(); + if(sessionContext instanceof TcpSessionContext){ TcpPacket tcpPacket = new TcpPacket(command,body); - TcpServerEncoder.encode(tcpPacket, channelContext.getGroupContext(), channelContext); + TcpServerEncoder.encode(tcpPacket, imChannelContext.getImConfig(), imChannelContext); tcpPacket.setCommand(command); return tcpPacket; } @@ -33,11 +34,11 @@ public class TcpConvertPacket implements IConvertProtocolPacket { * 转TCP协议请求包; */ @Override - public ImPacket ReqPacket(byte[] body, Command command,ChannelContext channelContext) { - Object sessionContext = channelContext.getAttribute(); - if(sessionContext instanceof TcpSessionContext){//转TCP协议请求包; + public ImPacket ReqPacket(byte[] body, Command command, ImChannelContext channelContext) { + Object sessionContext = channelContext.getSessionContext(); + if(sessionContext instanceof TcpSessionContext){ TcpPacket tcpPacket = new TcpPacket(command,body); - TcpServerEncoder.encode(tcpPacket, channelContext.getGroupContext(), channelContext); + TcpServerEncoder.encode(tcpPacket, channelContext.getImConfig(), channelContext); tcpPacket.setCommand(command); return tcpPacket; } diff --git a/jim-common/src/main/java/org/jim/common/tcp/TcpProtocol.java b/jim-common/src/main/java/org/jim/common/tcp/TcpProtocol.java index 576b17b..54c8712 100644 --- a/jim-common/src/main/java/org/jim/common/tcp/TcpProtocol.java +++ b/jim-common/src/main/java/org/jim/common/tcp/TcpProtocol.java @@ -5,20 +5,24 @@ package org.jim.common.tcp; import java.nio.ByteBuffer; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.jim.common.ImSessionContext; -import org.jim.common.Protocol; -import org.jim.common.protocol.AbProtocol; -import org.jim.common.protocol.IConvertProtocolPacket; +import org.jim.common.exception.ImException; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.common.protocol.IProtocolConverter; import org.jim.common.utils.ImUtils; -import org.tio.core.ChannelContext; /** * Tcp协议判断器 * @author WChao * */ -public class TcpProtocol extends AbProtocol { +public class TcpProtocol extends AbstractProtocol { + + public TcpProtocol(IProtocolConverter converter){ + super(converter); + } @Override public String name() { @@ -26,39 +30,31 @@ public class TcpProtocol extends AbProtocol { } @Override - public boolean isProtocolByBuffer(ByteBuffer buffer,ChannelContext channelContext) throws Throwable { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - if(imSessionContext != null && imSessionContext instanceof TcpSessionContext) { + protected void init(ImChannelContext imChannelContext) { + imChannelContext.setSessionContext(new TcpSessionContext(imChannelContext)); + ImUtils.setClient(imChannelContext); + } + + @Override + public boolean validateProtocol(ImSessionContext imSessionContext) throws ImException { + if(imSessionContext instanceof TcpSessionContext){ return true; } - if(buffer != null){ - //获取第一个字节协议版本号; - byte version = buffer.get(); - //TCP协议; - if(version == Protocol.VERSION){ - channelContext.setAttribute(new TcpSessionContext()); - ImUtils.setClient(channelContext); - return true; - } - } return false; } @Override - public IConvertProtocolPacket converter() { - return new TcpConvertPacket(); - } - - @Override - public boolean isProtocol(ImPacket imPacket,ChannelContext channelContext) throws Throwable { - if(imPacket == null) { - return false; + public boolean validateProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException { + //获取第一个字节协议版本号,TCP协议; + if(buffer.get() == Protocol.VERSION){ + return true; } + return false; + } + + @Override + public boolean validateProtocol(ImPacket imPacket) throws ImException { if(imPacket instanceof TcpPacket){ - Object sessionContext = channelContext.getAttribute(); - if(sessionContext == null){ - channelContext.setAttribute(new TcpSessionContext()); - } return true; } return false; diff --git a/jim-common/src/main/java/org/jim/common/tcp/TcpServerDecoder.java b/jim-common/src/main/java/org/jim/common/tcp/TcpServerDecoder.java index 5344445..3a088d0 100644 --- a/jim-common/src/main/java/org/jim/common/tcp/TcpServerDecoder.java +++ b/jim-common/src/main/java/org/jim/common/tcp/TcpServerDecoder.java @@ -6,11 +6,11 @@ package org.jim.common.tcp; import java.nio.ByteBuffer; import org.apache.log4j.Logger; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; import org.jim.common.ImPacket; import org.jim.common.ImStatus; -import org.jim.common.Protocol; -import org.tio.core.ChannelContext; -import org.tio.core.exception.AioDecodeException; +import org.jim.common.exception.ImDecodeException; import org.jim.common.packets.Command; /** @@ -18,11 +18,11 @@ import org.jim.common.packets.Command; * 功能说明: * @author : WChao 创建时间: 2017年8月21日 下午3:08:04 */ -public class TcpServerDecoder { +public class TcpServerDecoder implements ImConst { private static Logger logger = Logger.getLogger(TcpServerDecoder.class); - public static TcpPacket decode(ByteBuffer buffer, ChannelContext channelContext) throws AioDecodeException{ + public static TcpPacket decode(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImDecodeException { //校验协议头 if(!isHeaderLength(buffer)) { return null; @@ -30,7 +30,7 @@ public class TcpServerDecoder { //获取第一个字节协议版本号; byte version = buffer.get(); if(version != Protocol.VERSION){ - throw new AioDecodeException(ImStatus.C10013.getText()); + throw new ImDecodeException(ImStatus.C10013.getText()); } //标志位 byte maskByte = buffer.get(); @@ -42,13 +42,13 @@ public class TcpServerDecoder { //cmd命令码 byte cmdByte = buffer.get(); if(Command.forNumber(cmdByte) == null){ - throw new AioDecodeException(ImStatus.C10014.getText()); + throw new ImDecodeException(ImStatus.C10014.getText()); } int bodyLen = buffer.getInt(); - //数据不正确,则抛出AioDecodeException异常 + //数据不正确,则抛出ImDecodeException异常 if (bodyLen < 0) { - throw new AioDecodeException("bodyLength [" + bodyLen + "] is not right, remote:" + channelContext.getClientNode()); + throw new ImDecodeException("bodyLength [" + bodyLen + "] is not right, remote:" + imChannelContext.getClientNode()); } int readableLength = buffer.limit() - buffer.position(); int validateBodyLen = readableLength - bodyLen; @@ -72,7 +72,7 @@ public class TcpServerDecoder { if(synSeq > 0){ tcpPacket.setSynSeq(synSeq); try { - channelContext.getGroupContext().getAioHandler().handler(tcpPacket, channelContext); + //channelContext.getGroupContext().getAioHandler().handler(tcpPacket, channelContext); } catch (Exception e) { logger.error("同步发送解码调用handler异常!"+e); } @@ -83,9 +83,9 @@ public class TcpServerDecoder { * 判断是否符合协议头长度 * @param buffer * @return - * @throws AioDecodeException + * @throws ImDecodeException */ - private static boolean isHeaderLength(ByteBuffer buffer) throws AioDecodeException{ + private static boolean isHeaderLength(ByteBuffer buffer) throws ImDecodeException{ int readableLength = buffer.limit() - buffer.position(); if(readableLength == 0) { return false; diff --git a/jim-common/src/main/java/org/jim/common/tcp/TcpServerEncoder.java b/jim-common/src/main/java/org/jim/common/tcp/TcpServerEncoder.java index e898cfa..e6a5f01 100644 --- a/jim-common/src/main/java/org/jim/common/tcp/TcpServerEncoder.java +++ b/jim-common/src/main/java/org/jim/common/tcp/TcpServerEncoder.java @@ -6,18 +6,18 @@ package org.jim.common.tcp; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; import org.jim.common.ImPacket; -import org.jim.common.Protocol; -import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; +import org.jim.common.config.ImConfig; /** * 版本: [1.0] * 功能说明: * @author : WChao 创建时间: 2017年8月21日 下午4:00:31 */ -public class TcpServerEncoder { +public class TcpServerEncoder implements ImConst { - public static ByteBuffer encode(TcpPacket tcpPacket, GroupContext groupContext, ChannelContext channelContext){ + public static ByteBuffer encode(TcpPacket tcpPacket, ImConfig imConfig, ImChannelContext imChannelContext){ int bodyLen = 0; byte[] body = tcpPacket.getBody(); if (body != null) @@ -53,7 +53,7 @@ public class TcpServerEncoder { allLen += 1+4+bodyLen; ByteBuffer buffer = ByteBuffer.allocate(allLen); //设置字节序 - ByteOrder byteOrder = groupContext == null ? ByteOrder.BIG_ENDIAN : groupContext.getByteOrder(); + ByteOrder byteOrder = imConfig == null ? ByteOrder.BIG_ENDIAN : imConfig.getTioConfig().getByteOrder(); buffer.order(byteOrder); buffer.put(tcpPacket.getVersion()); buffer.put(tcpPacket.getMask()); diff --git a/jim-common/src/main/java/org/jim/common/tcp/TcpSessionContext.java b/jim-common/src/main/java/org/jim/common/tcp/TcpSessionContext.java index c23f599..324322c 100644 --- a/jim-common/src/main/java/org/jim/common/tcp/TcpSessionContext.java +++ b/jim-common/src/main/java/org/jim/common/tcp/TcpSessionContext.java @@ -3,12 +3,17 @@ */ package org.jim.common.tcp; +import org.jim.common.ImChannelContext; import org.jim.common.ImSessionContext; /** * 版本: [1.0] * 功能说明: - * 作者: WChao 创建时间: 2017年9月6日 下午5:03:15 + * @author : WChao 创建时间: 2017年9月6日 下午5:03:15 */ public class TcpSessionContext extends ImSessionContext { + public TcpSessionContext(ImChannelContext imChannelContext){ + super(imChannelContext); + } + } diff --git a/jim-common/src/main/java/org/jim/common/utils/ChatKit.java b/jim-common/src/main/java/org/jim/common/utils/ChatKit.java index e04091c..d32647c 100644 --- a/jim-common/src/main/java/org/jim/common/utils/ChatKit.java +++ b/jim-common/src/main/java/org/jim/common/utils/ChatKit.java @@ -5,12 +5,9 @@ package org.jim.common.utils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; -import org.jim.common.ImConst; -import org.jim.common.ImAio; -import org.jim.common.ImPacket; -import org.jim.common.ImSessionContext; -import org.jim.common.ImStatus; -import org.jim.common.config.Config; +import org.jim.common.*; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpConst; import org.jim.common.packets.ChatBody; import org.jim.common.packets.Command; @@ -18,7 +15,7 @@ import org.jim.common.packets.RespBody; import org.jim.common.packets.User; import org.jim.common.session.id.impl.UUIDSessionIdGenerator; import org.tio.core.ChannelContext; -import org.tio.utils.lock.SetWithLock; + /** * IM聊天命令工具类 * @date 2018-09-05 23:29:30 @@ -32,19 +29,19 @@ public class ChatKit { /** * 转换为聊天消息结构; * @param body - * @param channelContext + * @param imChannelContext * @return */ - public static ChatBody toChatBody(byte[] body,ChannelContext channelContext){ + public static ChatBody toChatBody(byte[] body,ImChannelContext imChannelContext){ ChatBody chatReqBody = parseChatBody(body); if(chatReqBody != null){ if(StringUtils.isEmpty(chatReqBody.getFrom())){ - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + ImSessionContext imSessionContext = imChannelContext.getSessionContext(); User user = imSessionContext.getClient().getUser(); if(user != null){ chatReqBody.setFrom(user.getNick()); }else{ - chatReqBody.setFrom(channelContext.getId()); + chatReqBody.setFrom(imChannelContext.getId()); } } } @@ -62,7 +59,7 @@ public class ChatKit { } ChatBody chatReqBody = null; try{ - String text = new String(body,HttpConst.CHARSET_NAME); + String text = new String(body,ImConst.CHARSET); chatReqBody = JsonKit.toBean(text,ChatBody.class); if(chatReqBody != null){ if(chatReqBody.getCreateTime() == null) { @@ -89,67 +86,28 @@ public class ChatKit { return null; } try { - return parseChatBody(bodyStr.getBytes(HttpConst.CHARSET_NAME)); + return parseChatBody(bodyStr.getBytes(ImConst.CHARSET)); } catch (Exception e) { log.error(e); } return null; } - /** - * 聊天数据格式不正确响应包 - * @param channelContext - * @return imPacket - * @throws Exception - */ - public static ImPacket dataInCorrectRespPacket(ChannelContext channelContext) throws Exception{ - RespBody chatDataInCorrectRespPacket = new RespBody(Command.COMMAND_CHAT_RESP,ImStatus.C10002); - ImPacket respPacket = ImKit.ConvertRespPacket(chatDataInCorrectRespPacket, channelContext); - respPacket.setStatus(ImStatus.C10002); - return respPacket; - } - - /** - * 聊天发送成功响应包 - * @param channelContext - * @return imPacket - * @throws Exception - */ - public static ImPacket sendSuccessRespPacket(ChannelContext channelContext) throws Exception{ - RespBody chatDataInCorrectRespPacket = new RespBody(Command.COMMAND_CHAT_RESP,ImStatus.C10000); - ImPacket respPacket = ImKit.ConvertRespPacket(chatDataInCorrectRespPacket, channelContext); - respPacket.setStatus(ImStatus.C10000); - return respPacket; - } - - /** - * 聊天用户不在线响应包 - * @param channelContext - * @return - * @throws Exception - */ - public static ImPacket offlineRespPacket(ChannelContext channelContext) throws Exception{ - RespBody chatDataInCorrectRespPacket = new RespBody(Command.COMMAND_CHAT_RESP,ImStatus.C10001); - ImPacket respPacket = ImKit.ConvertRespPacket(chatDataInCorrectRespPacket, channelContext); - respPacket.setStatus(ImStatus.C10001); - return respPacket; - } - /** * 判断用户是否在线 * @param userId * @param imConfig * @return */ - public static boolean isOnline(String userId ,Config imConfig){ - boolean isStore = ImConst.ON.equals(imConfig.getIsStore()); + public static boolean isOnline(String userId , ImConfig imConfig){ + /* boolean isStore = ImConst.ON.equals(imConfig.getIsStore()); if(isStore){ return imConfig.getMessageHelper().isOnline(userId); } - SetWithLock toChannelContexts = ImAio.getChannelContextsByUserId(userId); + SetWithLock toChannelContexts = Jim.getChannelContextsByUserId(userId); if(toChannelContexts != null && toChannelContexts.size() > 0){ return true; - } + }*/ return false; } diff --git a/jim-common/src/main/java/org/jim/common/utils/ImKit.java b/jim-common/src/main/java/org/jim/common/utils/ImKit.java index cef10e6..3fd648a 100644 --- a/jim-common/src/main/java/org/jim/common/utils/ImKit.java +++ b/jim-common/src/main/java/org/jim/common/utils/ImKit.java @@ -4,23 +4,23 @@ package org.jim.common.utils; import cn.hutool.core.bean.BeanUtil; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; import org.jim.common.ImPacket; import org.jim.common.ImStatus; -import org.jim.common.http.HttpConst; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpProtocol; import org.jim.common.packets.Command; import org.jim.common.packets.Group; import org.jim.common.packets.RespBody; import org.jim.common.packets.User; -import org.jim.common.protocol.AbProtocol; -import org.jim.common.protocol.IConvertProtocolPacket; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.common.protocol.IProtocolConverter; import org.jim.common.protocol.IProtocol; import org.jim.common.tcp.TcpProtocol; import org.jim.common.ws.WsProtocol; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.ChannelContext; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -36,108 +36,7 @@ import java.util.Map.Entry; public class ImKit { private static Logger logger = LoggerFactory.getLogger(ImKit.class); - private static Map protocols = new HashMap(); - - static{ - WsProtocol wsProtocol = new WsProtocol(); - TcpProtocol tcpProtocol = new TcpProtocol(); - HttpProtocol httpProtocol = new HttpProtocol(); - protocols.put(wsProtocol.name(),wsProtocol); - protocols.put(tcpProtocol.name(),tcpProtocol); - protocols.put(httpProtocol.name(),httpProtocol); - } - /** - * 功能描述:[转换不同协议响应包] - * @author:WChao 创建时间: 2017年9月21日 下午3:21:54 - * @param respBody - * @param channelContext - * @return - * - */ - public static ImPacket ConvertRespPacket(RespBody respBody, ChannelContext channelContext){ - ImPacket respPacket = null; - if(respBody == null) { - return respPacket; - } - byte[] body; - try { - body = respBody.toString().getBytes(HttpConst.CHARSET_NAME); - respPacket = ConvertRespPacket(body,respBody.getCommand(), channelContext); - } catch (Exception e) { - logger.error(e.getMessage()); - } - return respPacket; - } - - /** - * 功能描述:[转换不同协议响应包] - * @author:WChao 创建时间: 2017年9月21日 下午3:21:54 - * @param body - * @param channelContext - * @return - * - */ - public static ImPacket ConvertRespPacket(byte[] body,Command command, ChannelContext channelContext){ - ImPacket respPacket = null; - IConvertProtocolPacket converter = (IConvertProtocolPacket)channelContext.getAttribute(ImConst.CONVERTER); - if(converter != null){ - return converter.RespPacket(body, command, channelContext); - } - for(Entry entry : protocols.entrySet()){ - AbProtocol protocol = entry.getValue(); - IConvertProtocolPacket converterObj = protocol.getConverter(); - respPacket = converterObj.RespPacket(body, command, channelContext); - if(respPacket != null){ - channelContext.setAttribute(ImConst.CONVERTER, converterObj); - return respPacket; - } - } - return respPacket; - } - - public static ImPacket ConvertRespPacket(ImPacket imPacket,Command command, ChannelContext channelContext){ - ImPacket respPacket = ConvertRespPacket(imPacket.getBody(), command, channelContext); - if(respPacket == null){ - for(Entry entry : protocols.entrySet()){ - AbProtocol protocol = entry.getValue(); - try{ - boolean isProtocol = protocol.isProtocol(imPacket,channelContext); - if(isProtocol){ - IConvertProtocolPacket converterObj = protocol.getConverter(); - respPacket = converterObj.RespPacket(imPacket.getBody(), command, channelContext); - if(respPacket != null){ - channelContext.setAttribute(ImConst.CONVERTER, converterObj); - return respPacket; - } - } - }catch(Throwable e){ - logger.error(e.toString()); - } - } - } - return respPacket; - } - - /** - * 获取所属终端协议; - * @param byteBuffer - * @param channelContext - */ - public static IProtocol protocol(ByteBuffer byteBuffer , ChannelContext channelContext){ - for(Entry entry : protocols.entrySet()){ - AbProtocol protocol = entry.getValue(); - try { - boolean isProtocol = protocol.isProtocol(byteBuffer, channelContext); - if(isProtocol){ - return protocol; - } - } catch (Throwable e) { - logger.error(e.toString(),e); - } - } - return null; - } /** * 格式化状态码消息响应体; @@ -145,17 +44,9 @@ public class ImKit { * @return */ public static byte[] toImStatusBody(ImStatus status){ - return JsonKit.toJsonBytes(new RespBody().setCode(status.getCode()).setMsg(status.getDescription()+" "+status.getText())); + return JsonKit.toJsonBytes(new RespBody(status).setMsg(status.getDescription()+" "+status.getText())); } - /** - * 获取所有协议判断器,目前内置(HttpProtocol、WebSocketProtocol、HttpProtocol) - * @return - */ - public static Map getProtocols() { - return protocols; - } - /** * 复制用户信息不包括friends、groups下的users信息; * @param source diff --git a/jim-common/src/main/java/org/jim/common/utils/ImUtils.java b/jim-common/src/main/java/org/jim/common/utils/ImUtils.java index 0b72035..e184163 100644 --- a/jim-common/src/main/java/org/jim/common/utils/ImUtils.java +++ b/jim-common/src/main/java/org/jim/common/utils/ImUtils.java @@ -3,6 +3,7 @@ package org.jim.common.utils; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.jim.common.ImChannelContext; import org.jim.common.ImSessionContext; import org.tio.core.ChannelContext; import org.jim.common.packets.Client; @@ -16,10 +17,10 @@ public class ImUtils { * 设置Client对象到ImSessionContext中 * @param channelContext * @return - * @author: wchao + * @author: WChao */ - public static Client setClient(ChannelContext channelContext) { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + public static Client setClient(ImChannelContext channelContext) { + ImSessionContext imSessionContext = channelContext.getSessionContext(); Client client = imSessionContext.getClient(); if (client == null) { client = new Client(); @@ -28,7 +29,6 @@ public class ImUtils { client.setPort(channelContext.getClientNode().getPort()); imSessionContext.setClient(client); } - return client; } diff --git a/jim-common/src/main/java/org/jim/common/ws/IWsMsgHandler.java b/jim-common/src/main/java/org/jim/common/ws/IWsMsgHandler.java index 20b3b4e..68f3aa0 100644 --- a/jim-common/src/main/java/org/jim/common/ws/IWsMsgHandler.java +++ b/jim-common/src/main/java/org/jim/common/ws/IWsMsgHandler.java @@ -1,5 +1,6 @@ package org.jim.common.ws; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.tio.core.ChannelContext; import org.jim.common.ws.WsRequestPacket; @@ -13,43 +14,43 @@ public interface IWsMsgHandler /** * * @param packet - * @param channelContext + * @param imChannelContext * @return * * @author: WChao * 2016年11月18日 下午1:08:45 * */ - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception; + public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws Exception; /** - * @param websocketPacket + * @param wsPacket * @param text - * @param channelContext + * @param imChannelContext * @return 可以是WsResponsePacket、byte[]、ByteBuffer、String或null,如果是null,框架不会回消息 * @throws Exception * @author: WChao */ - Object onText(WsRequestPacket wsPacket, String text, ChannelContext channelContext) throws Exception; + Object onText(WsRequestPacket wsPacket, String text, ImChannelContext imChannelContext) throws Exception; /** * - * @param websocketPacket + * @param webSocketPacket * @param bytes * @param channelContext * @return 可以是WsResponsePacket、byte[]、ByteBuffer、String或null,如果是null,框架不会回消息 * @throws Exception * @author: WChao */ - Object onClose(WsRequestPacket websocketPacket, byte[] bytes, ChannelContext channelContext) throws Exception; + Object onClose(WsRequestPacket webSocketPacket, byte[] bytes, ImChannelContext channelContext) throws Exception; /** * - * @param websocketPacket + * @param webSocketPacket * @param bytes - * @param channelContext + * @param imChannelContext * @return 可以是WsResponsePacket、byte[]、ByteBuffer、String或null,如果是null,框架不会回消息 * @throws Exception * @author: WChao */ - Object onBytes(WsRequestPacket websocketPacket, byte[] bytes, ChannelContext channelContext) throws Exception; + Object onBytes(WsRequestPacket webSocketPacket, byte[] bytes, ImChannelContext imChannelContext) throws Exception; } diff --git a/jim-common/src/main/java/org/jim/common/ws/WsConfig.java b/jim-common/src/main/java/org/jim/common/ws/WsConfig.java new file mode 100644 index 0000000..bd79761 --- /dev/null +++ b/jim-common/src/main/java/org/jim/common/ws/WsConfig.java @@ -0,0 +1,71 @@ +package org.jim.common.ws; + +import org.jim.common.ImConst; +import org.jim.common.config.ImConfig; +import org.jim.common.http.HttpConst; + +/** + * + * 版本: [1.0] + * 功能说明: + * @author : WChao 创建时间: 2017年9月6日 上午11:11:26 + */ +public class WsConfig implements ImConst { + + private String charset = Http.CHARSET_NAME; + + private IWsMsgHandler wsMsgHandler; + + public WsConfig(){}; + + public WsConfig(IWsMsgHandler wsMsgHandler){ + this.wsMsgHandler = wsMsgHandler; + } + + public static WsConfig.Builder newBuilder(){ + return new WsConfig.Builder(); + } + + /** + * @return the charset + */ + public String getCharset() { + return charset; + } + + /** + * @param charset the charset to set + */ + public void setCharset(String charset) { + this.charset = charset; + } + public IWsMsgHandler getWsMsgHandler() { + return wsMsgHandler; + } + public void setWsMsgHandler(IWsMsgHandler wsMsgHandler) { + this.wsMsgHandler = wsMsgHandler; + } + + public static class Builder{ + + private IWsMsgHandler wsMsgHandler; + + private String charset; + + public Builder wsMsgHandler(IWsMsgHandler wsMsgHandler){ + this.wsMsgHandler = wsMsgHandler; + return this; + } + + public Builder charset(String charset){ + this.charset = charset; + return this; + } + + public WsConfig build(){ + WsConfig wsConfig = new WsConfig(wsMsgHandler); + wsConfig.setCharset(charset); + return wsConfig; + } + } +} diff --git a/jim-common/src/main/java/org/jim/common/ws/WsConvertPacket.java b/jim-common/src/main/java/org/jim/common/ws/WsConvertPacket.java index 4e1172f..ed463c7 100644 --- a/jim-common/src/main/java/org/jim/common/ws/WsConvertPacket.java +++ b/jim-common/src/main/java/org/jim/common/ws/WsConvertPacket.java @@ -3,24 +3,24 @@ */ package org.jim.common.ws; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; +import org.jim.common.ImSessionContext; import org.jim.common.packets.Command; -import org.jim.common.protocol.IConvertProtocolPacket; -import org.tio.core.ChannelContext; - +import org.jim.common.protocol.IProtocolConverter; /** * Ws协议消息转化包 * @author WChao * */ -public class WsConvertPacket implements IConvertProtocolPacket { +public class WsConvertPacket implements IProtocolConverter { /** * WebSocket响应包; */ @Override - public ImPacket RespPacket(byte[] body, Command command,ChannelContext channelContext) { - Object sessionContext = channelContext.getAttribute(); + public ImPacket RespPacket(byte[] body, Command command, ImChannelContext channelContext) { + ImSessionContext sessionContext = channelContext.getSessionContext(); //转ws协议响应包; if(sessionContext instanceof WsSessionContext){ WsResponsePacket wsResponsePacket = new WsResponsePacket(); @@ -33,7 +33,7 @@ public class WsConvertPacket implements IConvertProtocolPacket { } @Override - public ImPacket ReqPacket(byte[] body, Command command,ChannelContext channelContext) { + public ImPacket ReqPacket(byte[] body, Command command, ImChannelContext channelContext) { return null; } diff --git a/jim-common/src/main/java/org/jim/common/ws/WsProtocol.java b/jim-common/src/main/java/org/jim/common/ws/WsProtocol.java index ab6d53a..03b386b 100644 --- a/jim-common/src/main/java/org/jim/common/ws/WsProtocol.java +++ b/jim-common/src/main/java/org/jim/common/ws/WsProtocol.java @@ -5,65 +5,62 @@ package org.jim.common.ws; import java.nio.ByteBuffer; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.jim.common.ImSessionContext; -import org.jim.common.Protocol; -import org.jim.common.http.HttpConst; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpRequest; import org.jim.common.http.HttpRequestDecoder; -import org.jim.common.protocol.AbProtocol; -import org.jim.common.protocol.IConvertProtocolPacket; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.common.protocol.IProtocolConverter; import org.jim.common.utils.ImUtils; -import org.tio.core.ChannelContext; - /** * WebSocket协议判断器 * @author WChao * */ -public class WsProtocol extends AbProtocol { +public class WsProtocol extends AbstractProtocol { @Override public String name() { - return Protocol.WEBSOCKET; + return Protocol.WEB_SOCKET; + } + + public WsProtocol(IProtocolConverter converter){ + super(converter); } @Override - public boolean isProtocolByBuffer(ByteBuffer buffer,ChannelContext channelContext) throws Throwable { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - if(imSessionContext != null && imSessionContext instanceof WsSessionContext) { + protected void init(ImChannelContext imChannelContext) { + imChannelContext.setSessionContext(new WsSessionContext(imChannelContext)); + ImUtils.setClient(imChannelContext); + } + + @Override + protected boolean validateProtocol(ImSessionContext imSessionContext) throws ImException { + if(imSessionContext instanceof WsSessionContext) { return true; } - //第一次连接; - if(buffer != null){ - HttpRequest request = HttpRequestDecoder.decode(buffer, channelContext,false); - if(request.getHeaders().get(HttpConst.RequestHeaderKey.Sec_WebSocket_Key) != null) - { - channelContext.setAttribute(new WsSessionContext()); - ImUtils.setClient(channelContext); - return true; - } - } return false; } @Override - public IConvertProtocolPacket converter() { - return new WsConvertPacket(); - } - - @Override - public boolean isProtocol(ImPacket imPacket,ChannelContext channelContext) throws Throwable { - if(imPacket == null) { - return false; - } - if(imPacket instanceof WsPacket){ - Object sessionContext = channelContext.getAttribute(); - if(sessionContext == null){ - channelContext.setAttribute(new WsSessionContext()); - } + protected boolean validateProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException { + //第一次连接; + HttpRequest request = HttpRequestDecoder.decode(buffer, imChannelContext,false); + if(request.getHeaders().get(Http.RequestHeaderKey.Sec_WebSocket_Key) != null) + { return true; } return false; } + + @Override + public boolean validateProtocol(ImPacket imPacket) throws ImException { + if(imPacket instanceof WsPacket){ + return true; + } + return false; + } + } diff --git a/jim-common/src/main/java/org/jim/common/ws/WsServerConfig.java b/jim-common/src/main/java/org/jim/common/ws/WsServerConfig.java deleted file mode 100644 index dce5b39..0000000 --- a/jim-common/src/main/java/org/jim/common/ws/WsServerConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jim.common.ws; - -import org.jim.common.config.Config; -import org.jim.common.http.HttpConst; - -/** - * - * 版本: [1.0] - * 功能说明: - * @author : WChao 创建时间: 2017年9月6日 上午11:11:26 - */ -public class WsServerConfig extends Config{ - - private String charset = HttpConst.CHARSET_NAME; - - private IWsMsgHandler wsMsgHandler; - - public WsServerConfig(){}; - - public WsServerConfig(Integer bindPort) { - this.bindPort = bindPort; - } - /** - * @return the charset - */ - public String getCharset() { - return charset; - } - - /** - * @param charset the charset to set - */ - public void setCharset(String charset) { - this.charset = charset; - } - public IWsMsgHandler getWsMsgHandler() { - return wsMsgHandler; - } - public void setWsMsgHandler(IWsMsgHandler wsMsgHandler) { - this.wsMsgHandler = wsMsgHandler; - } -} diff --git a/jim-common/src/main/java/org/jim/common/ws/WsServerDecoder.java b/jim-common/src/main/java/org/jim/common/ws/WsServerDecoder.java index 46d31d4..f2cd6b4 100644 --- a/jim-common/src/main/java/org/jim/common/ws/WsServerDecoder.java +++ b/jim-common/src/main/java/org/jim/common/ws/WsServerDecoder.java @@ -8,12 +8,12 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.exception.ImDecodeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.ChannelContext; -import org.tio.core.exception.AioDecodeException; import org.tio.core.utils.ByteBufferUtils; -import org.jim.common.http.HttpConst; import org.jim.common.http.HttpRequest; import org.jim.common.http.HttpResponse; import org.jim.common.http.HttpResponseStatus; @@ -24,15 +24,15 @@ import org.jim.common.utils.SHA1Util; * @author wchao * 2017年7月30日 上午10:10:50 */ -public class WsServerDecoder { - public static enum Step { +public class WsServerDecoder implements ImConst{ + public enum Step { header, remain_header, data, } private static Logger log = LoggerFactory.getLogger(WsServerDecoder.class); - public static WsRequestPacket decode(ByteBuffer buf, ChannelContext channelContext) throws AioDecodeException { - WsSessionContext imSessionContext = (WsSessionContext) channelContext.getAttribute(); + public static WsRequestPacket decode(ByteBuffer buf, ImChannelContext imChannelContext) throws ImDecodeException { + WsSessionContext imSessionContext = (WsSessionContext) imChannelContext.getSessionContext(); List lastParts = imSessionContext.getLastParts(); //第一阶段解析 @@ -70,7 +70,7 @@ public class WsServerDecoder { // Client data must be masked if (!hasMask) { //第9为为mask,必须为1 - //throw new AioDecodeException("websocket client data must be masked"); + //throw new ImDecodeException("websocket client data must be masked"); } else { headLength += 4; } @@ -83,7 +83,7 @@ public class WsServerDecoder { return null; } payloadLength = ByteBufferUtils.readUB2WithBigEdian(buf); - log.info("{} payloadLengthFlag: 126,payloadLength {}", channelContext, payloadLength); + log.info("{} payloadLengthFlag: 126,payloadLength {}", imChannelContext, payloadLength); } else if (payloadLength == 127) { //127读8个字节,后8个字节为payloadLength headLength += 8; @@ -92,11 +92,11 @@ public class WsServerDecoder { } payloadLength = (int) buf.getLong(); - log.info("{} payloadLengthFlag: 127,payloadLength {}", channelContext, payloadLength); + log.info("{} payloadLengthFlag: 127,payloadLength {}", imChannelContext, payloadLength); } if (payloadLength < 0 || payloadLength > WsPacket.MAX_BODY_LENGTH) { - throw new AioDecodeException("body length(" + payloadLength + ") is not right"); + throw new ImDecodeException("body length(" + payloadLength + ") is not right"); } if (readableLength < headLength + payloadLength) { @@ -173,14 +173,14 @@ public class WsServerDecoder { * 本方法改编自baseio: https://git.oschina.net/generallycloud/baseio
* 感谢开源作者的付出 * @param request - * @param channelContext + * @param imChannelContext * @return * @author wchao */ - public static HttpResponse updateWebSocketProtocol(HttpRequest request, ChannelContext channelContext) { + public static HttpResponse updateWebSocketProtocol(HttpRequest request, ImChannelContext imChannelContext) { Map headers = request.getHeaders(); - String Sec_WebSocket_Key = headers.get(HttpConst.RequestHeaderKey.Sec_WebSocket_Key); + String Sec_WebSocket_Key = headers.get(Http.RequestHeaderKey.Sec_WebSocket_Key); if (StringUtils.isNotBlank(Sec_WebSocket_Key)) { String Sec_WebSocket_Key_Magic = Sec_WebSocket_Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; @@ -191,9 +191,9 @@ public class WsServerDecoder { httpResponse.setStatus(HttpResponseStatus.C101); Map respHeaders = new HashMap<>(); - respHeaders.put(HttpConst.ResponseHeaderKey.Connection, HttpConst.ResponseHeaderValue.Connection.Upgrade); - respHeaders.put(HttpConst.ResponseHeaderKey.Upgrade, "WebSocket"); - respHeaders.put(HttpConst.ResponseHeaderKey.Sec_WebSocket_Accept, acceptKey); + respHeaders.put(Http.ResponseHeaderKey.Connection, Http.ResponseHeaderValue.Connection.Upgrade); + respHeaders.put(Http.ResponseHeaderKey.Upgrade, "WebSocket"); + respHeaders.put(Http.ResponseHeaderKey.Sec_WebSocket_Accept, acceptKey); httpResponse.setHeaders(respHeaders); return httpResponse; } diff --git a/jim-common/src/main/java/org/jim/common/ws/WsServerEncoder.java b/jim-common/src/main/java/org/jim/common/ws/WsServerEncoder.java index accc120..bbbcf3f 100644 --- a/jim-common/src/main/java/org/jim/common/ws/WsServerEncoder.java +++ b/jim-common/src/main/java/org/jim/common/ws/WsServerEncoder.java @@ -2,10 +2,11 @@ package org.jim.common.ws; import java.nio.ByteBuffer; +import org.jim.common.ImChannelContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; +import org.tio.core.TioConfig; import org.tio.core.utils.ByteBufferUtils; /** @@ -34,8 +35,9 @@ public class WsServerEncoder { } } - public static ByteBuffer encode(WsResponsePacket wsResponsePacket, GroupContext groupContext, ChannelContext channelContext) { - byte[] imBody = wsResponsePacket.getBody();//就是ws的body,不包括ws的头 + public static ByteBuffer encode(WsResponsePacket wsResponsePacket, ImChannelContext imChannelContext) { + //就是ws的body,不包括ws的头 + byte[] imBody = wsResponsePacket.getBody(); int wsBodyLength = 0; if (imBody != null) { diff --git a/jim-common/src/main/java/org/jim/common/ws/WsSessionContext.java b/jim-common/src/main/java/org/jim/common/ws/WsSessionContext.java index b980e87..332a643 100644 --- a/jim-common/src/main/java/org/jim/common/ws/WsSessionContext.java +++ b/jim-common/src/main/java/org/jim/common/ws/WsSessionContext.java @@ -2,6 +2,7 @@ package org.jim.common.ws; import java.util.List; +import org.jim.common.ImChannelContext; import org.jim.common.ImSessionContext; import org.jim.common.http.HttpRequest; import org.jim.common.http.HttpResponse; @@ -18,12 +19,12 @@ public class WsSessionContext extends ImSessionContext { private boolean isHandshaked = false; /** - * websocket 握手请求包 + * webSocket 握手请求包 */ private HttpRequest handshakeRequestPacket = null; /** - * websocket 握手响应包 + * webSocket 握手响应包 */ private HttpResponse handshakeResponsePacket = null; /** @@ -33,20 +34,21 @@ public class WsSessionContext extends ImSessionContext { /** * ws响应状态包; */ - private WsResponsePacket wsResponsPacket = null; + private WsResponsePacket wsResponsePacket = null; - //websocket 协议用到的,有时候数据包是分几个到的,注意那个fin字段,本im暂时不支持 + /** + * webSocket 协议用到的,有时候数据包是分几个到的,注意那个fin字段,本im暂时不支持 + */ private List lastParts = null; /** - * * * @author wchao * 2017年2月21日 上午10:27:54 * */ - public WsSessionContext() { - + public WsSessionContext(ImChannelContext imChannelContext) { + super(imChannelContext); } /** @@ -85,7 +87,7 @@ public class WsSessionContext extends ImSessionContext { } /** - * @param httpHandshakePacket the httpHandshakePacket to set + * @param handshakeRequestPacket the httpHandshakePacket to set */ public void setHandshakeRequestPacket(HttpRequest handshakeRequestPacket) { this.handshakeRequestPacket = handshakeRequestPacket; @@ -113,11 +115,11 @@ public class WsSessionContext extends ImSessionContext { this.wsRequestPacket = wsRequestPacket; } - public WsResponsePacket getWsResponsPacket() { - return wsResponsPacket; + public WsResponsePacket getWsResponsePacket() { + return wsResponsePacket; } - public void setWsResponsPacket(WsResponsePacket wsResponsPacket) { - this.wsResponsPacket = wsResponsPacket; + public void setWsResponsePacket(WsResponsePacket wsResponsePacket) { + this.wsResponsePacket = wsResponsePacket; } } diff --git a/jim-common/src/main/java/org/jim/common/ws/WsTioUuid.java b/jim-common/src/main/java/org/jim/common/ws/WsTioUuid.java index 9801a37..ac4c87d 100644 --- a/jim-common/src/main/java/org/jim/common/ws/WsTioUuid.java +++ b/jim-common/src/main/java/org/jim/common/ws/WsTioUuid.java @@ -1,9 +1,9 @@ package org.jim.common.ws; import org.tio.core.intf.TioUuid; +import org.tio.utils.hutool.Snowflake; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.RandomUtil; +import java.util.concurrent.ThreadLocalRandom; /** * @author WChao @@ -13,11 +13,11 @@ public class WsTioUuid implements TioUuid { private Snowflake snowflake; public WsTioUuid() { - snowflake = new Snowflake(RandomUtil.randomInt(1, 30), RandomUtil.randomInt(1, 30)); + snowflake = new Snowflake(ThreadLocalRandom.current().nextInt(1, 30), ThreadLocalRandom.current().nextInt(1, 30)); } - public WsTioUuid(long workerId, long datacenterId) { - snowflake = new Snowflake(workerId, datacenterId); + public WsTioUuid(long workerId, long dataCenterId) { + snowflake = new Snowflake(workerId, dataCenterId); } /** diff --git a/jim-parent/pom.xml b/jim-parent/pom.xml index 11884cf..be32881 100644 --- a/jim-parent/pom.xml +++ b/jim-parent/pom.xml @@ -5,7 +5,7 @@ jim-parent pom ${project.artifactId} - 2.6.0.v20190114-RELEASE + 3.0.0.v20200101-RELEASE Jim-parent is the dependent parent project of J-IM communication establishment. http://www.j-im.org/ @@ -34,9 +34,9 @@ ../jim-server-demo - 2.6.0.v20190114-RELEASE - 2.4.0.v20180508-RELEASE - 2.4.0.v20180508-RELEASE + 3.0.0.v20200101-RELEASE + 3.5.8.v20191228-RELEASE + 3.5.8.v20191228-RELEASE UTF-8 UTF-8 @@ -62,6 +62,7 @@ 2.7.3 3.7.0 2.3.21-release + 23.0 @@ -250,7 +251,7 @@ com.google.guava guava - 23.0 + ${guava.version} nl.basjes.parse.useragent @@ -267,6 +268,11 @@ j2cache-core ${j2cache.version} + + cn.hutool + hutool-all + ${hutool.version} +
diff --git a/jim-server-demo/pom.xml b/jim-server-demo/pom.xml index de38441..75f4d61 100644 --- a/jim-server-demo/pom.xml +++ b/jim-server-demo/pom.xml @@ -6,7 +6,7 @@ org.j-im jim-parent - 2.6.0.v20190114-RELEASE + 3.0.0.v20200101-RELEASE ../jim-parent/pom.xml diff --git a/jim-server-demo/src/main/java/org/jim/server/demo/ImServerDemoStart.java b/jim-server-demo/src/main/java/org/jim/server/demo/ImServerDemoStart.java index ca7d842..c6fc548 100644 --- a/jim-server-demo/src/main/java/org/jim/server/demo/ImServerDemoStart.java +++ b/jim-server-demo/src/main/java/org/jim/server/demo/ImServerDemoStart.java @@ -3,17 +3,16 @@ */ package org.jim.server.demo; -import com.jfinal.kit.PropKit; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImConfig; -import org.jim.common.ImConst; -import org.jim.common.config.PropertyImConfigBuilder; +import org.jim.common.config.ImConfig; import org.jim.common.packets.Command; import org.jim.common.utils.PropUtil; import org.jim.server.ImServerStarter; import org.jim.server.command.CommandManager; import org.jim.server.command.handler.HandshakeReqHandler; import org.jim.server.command.handler.LoginReqHandler; +import org.jim.server.config.ImServerConfig; +import org.jim.server.config.PropertyImServerConfigBuilder; import org.jim.server.demo.command.DemoWsHandshakeProcessor; import org.jim.server.demo.listener.ImDemoGroupListener; import org.jim.server.demo.service.LoginServiceProcessor; @@ -26,12 +25,12 @@ import org.tio.core.ssl.SslConfig; public class ImServerDemoStart { public static void main(String[] args)throws Exception{ - ImConfig imConfig = new PropertyImConfigBuilder("jim.properties").build(); + ImServerConfig imServerConfig = new PropertyImServerConfigBuilder("jim.properties").build(); //初始化SSL;(开启SSL之前,你要保证你有SSL证书哦...) - initSsl(imConfig); + initSsl(imServerConfig); //设置群组监听器,非必须,根据需要自己选择性实现; - imConfig.setImGroupListener(new ImDemoGroupListener()); - ImServerStarter imServerStarter = new ImServerStarter(imConfig); + imServerConfig.setImGroupListener(new ImDemoGroupListener()); + ImServerStarter imServerStarter = new ImServerStarter(imServerConfig); /*****************start 以下处理器根据业务需要自行添加与扩展,每个Command都可以添加扩展,此处为demo中处理**********************************/ HandshakeReqHandler handshakeReqHandler = CommandManager.getCommand(Command.COMMAND_HANDSHAKE_REQ, HandshakeReqHandler.class); //添加自定义握手处理器; @@ -45,19 +44,19 @@ public class ImServerDemoStart { /** * 开启SSL之前,你要保证你有SSL证书哦! - * @param imConfig + * @param imServerConfig * @throws Exception */ - private static void initSsl(ImConfig imConfig) throws Exception { + private static void initSsl(ImServerConfig imServerConfig) throws Exception { //开启SSL - if(ImConst.ON.equals(imConfig.getIsSSL())){ + if(ImConfig.Const.ON.equals(imServerConfig.getIsSSL())){ String keyStorePath = PropUtil.get("jim.key.store.path"); String keyStoreFile = keyStorePath; String trustStoreFile = keyStorePath; String keyStorePwd = PropUtil.get("jim.key.store.pwd"); if (StringUtils.isNotBlank(keyStoreFile) && StringUtils.isNotBlank(trustStoreFile)) { SslConfig sslConfig = SslConfig.forServer(keyStoreFile, trustStoreFile, keyStorePwd); - imConfig.setSslConfig(sslConfig); + imServerConfig.setSslConfig(sslConfig); } } } diff --git a/jim-server-demo/src/main/java/org/jim/server/demo/command/DemoWsHandshakeProcessor.java b/jim-server-demo/src/main/java/org/jim/server/demo/command/DemoWsHandshakeProcessor.java index c486538..ae9decc 100644 --- a/jim-server-demo/src/main/java/org/jim/server/demo/command/DemoWsHandshakeProcessor.java +++ b/jim-server-demo/src/main/java/org/jim/server/demo/command/DemoWsHandshakeProcessor.java @@ -3,9 +3,11 @@ */ package org.jim.server.demo.command; -import org.jim.common.ImAio; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.Jim; import org.jim.common.ImPacket; -import org.jim.common.http.HttpConst; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpRequest; import org.jim.common.packets.Command; import org.jim.common.packets.LoginReqBody; @@ -13,7 +15,6 @@ import org.jim.common.utils.JsonKit; import org.jim.server.command.CommandManager; import org.jim.server.command.handler.LoginReqHandler; import org.jim.server.command.handler.processor.handshake.WsHandshakeProcessor; -import org.tio.core.ChannelContext; /** * @author WChao * @@ -21,7 +22,7 @@ import org.tio.core.ChannelContext; public class DemoWsHandshakeProcessor extends WsHandshakeProcessor { @Override - public void onAfterHandshaked(ImPacket packet, ChannelContext channelContext) throws Exception { + public void onAfterHandshake(ImPacket packet, ImChannelContext imChannelContext) throws ImException { LoginReqHandler loginHandler = (LoginReqHandler)CommandManager.getCommand(Command.COMMAND_LOGIN_REQ); HttpRequest request = (HttpRequest)packet; String username = request.getParams().get("username") == null ? null : (String)request.getParams().get("username")[0]; @@ -30,10 +31,14 @@ public class DemoWsHandshakeProcessor extends WsHandshakeProcessor { LoginReqBody loginBody = new LoginReqBody(username,password,token); byte[] loginBytes = JsonKit.toJsonBytes(loginBody); request.setBody(loginBytes); - request.setBodyString(new String(loginBytes,HttpConst.CHARSET_NAME)); - ImPacket loginRespPacket = loginHandler.handler(request, channelContext); + try{ + request.setBodyString(new String(loginBytes, ImConst.CHARSET)); + }catch (Exception e){ + throw new ImException(e); + } + ImPacket loginRespPacket = loginHandler.handler(request, imChannelContext); if(loginRespPacket != null){ - ImAio.send(channelContext, loginRespPacket); + Jim.send(imChannelContext, loginRespPacket); } } } diff --git a/jim-server-demo/src/main/java/org/jim/server/demo/listener/ImDemoGroupListener.java b/jim-server-demo/src/main/java/org/jim/server/demo/listener/ImDemoGroupListener.java index eb8a708..41e42c7 100644 --- a/jim-server-demo/src/main/java/org/jim/server/demo/listener/ImDemoGroupListener.java +++ b/jim-server-demo/src/main/java/org/jim/server/demo/listener/ImDemoGroupListener.java @@ -1,33 +1,40 @@ package org.jim.server.demo.listener; -import org.jim.common.ImAio; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.ImSessionContext; +import org.jim.common.exception.ImException; +import org.jim.common.listener.ImGroupListener; import org.tio.core.ChannelContext; import org.jim.common.packets.Client; import org.jim.common.packets.Command; import org.jim.common.packets.ExitGroupNotifyRespBody; import org.jim.common.packets.RespBody; import org.jim.common.packets.User; -import org.jim.server.listener.ImGroupListener; + /** * @author WChao * 2017年5月13日 下午10:38:36 */ -public class ImDemoGroupListener extends ImGroupListener{ - /** +public class ImDemoGroupListener implements ImGroupListener { + @Override + public void onAfterBind(ImChannelContext imChannelContext, String group) throws ImException { + System.out.println("===绑定成功:"+group); + } + + /** * @param channelContext * @param group * @throws Exception * @author: WChao */ @Override - public void onAfterUnbind(ChannelContext channelContext, String group) throws Exception { + public void onAfterUnbind(ImChannelContext channelContext, String group) throws ImException { //发退出房间通知 COMMAND_EXIT_GROUP_NOTIFY_RESP - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); ExitGroupNotifyRespBody exitGroupNotifyRespBody = new ExitGroupNotifyRespBody(); exitGroupNotifyRespBody.setGroup(group); - Client client = imSessionContext.getClient(); + Client client = channelContext.getSessionContext().getClient(); if(client == null){ return; } @@ -40,7 +47,7 @@ public class ImDemoGroupListener extends ImGroupListener{ RespBody respBody = new RespBody(Command.COMMAND_EXIT_GROUP_NOTIFY_RESP,exitGroupNotifyRespBody); ImPacket imPacket = new ImPacket(Command.COMMAND_EXIT_GROUP_NOTIFY_RESP, respBody.toByte()); - ImAio.sendToGroup(group, imPacket); + Jim.sendToGroup(group, imPacket); } } diff --git a/jim-server-demo/src/main/java/org/jim/server/demo/service/LoginServiceProcessor.java b/jim-server-demo/src/main/java/org/jim/server/demo/service/LoginServiceProcessor.java index da1ba38..963c7c6 100644 --- a/jim-server-demo/src/main/java/org/jim/server/demo/service/LoginServiceProcessor.java +++ b/jim-server-demo/src/main/java/org/jim/server/demo/service/LoginServiceProcessor.java @@ -5,10 +5,7 @@ package org.jim.server.demo.service; import cn.hutool.core.util.RandomUtil; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImConst; -import org.jim.common.ImPacket; -import org.jim.common.ImSessionContext; -import org.jim.common.ImStatus; +import org.jim.common.*; import org.jim.common.http.HttpConst; import org.jim.common.packets.Command; import org.jim.common.packets.Group; @@ -51,17 +48,17 @@ public class LoginServiceProcessor implements LoginCmdProcessor { /** * 根据用户名和密码获取用户 - * @param loginname + * @param loginName * @param password * @return * @author: WChao */ - public User getUser(String loginname, String password) { - String text = loginname+password; + public User getUser(String loginName, String password) { + String text = loginName+password; String key = ImConst.AUTH_KEY; - String token = Md5.sign(text, key, HttpConst.CHARSET_NAME); + String token = Md5.sign(text, key, CHARSET); User user = getUser(token); - user.setId(loginname); + user.setId(loginName); return user; } /** @@ -124,17 +121,17 @@ public class LoginServiceProcessor implements LoginCmdProcessor { * 当登陆失败时设置user属性需要为空,相反登陆成功user属性是必须非空的; */ @Override - public LoginRespBody doLogin(LoginReqBody loginReqBody , ChannelContext channelContext) { - String loginname = loginReqBody.getLoginname(); + public LoginRespBody doLogin(LoginReqBody loginReqBody , ImChannelContext channelContext) { + String loginName = loginReqBody.getLoginname(); String password = loginReqBody.getPassword(); - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + ImSessionContext imSessionContext = channelContext.getSessionContext(); String handshakeToken = imSessionContext.getToken(); User user; LoginRespBody loginRespBody; if (!StringUtils.isBlank(handshakeToken)) { user = this.getUser(handshakeToken); }else{ - user = this.getUser(loginname, password); + user = this.getUser(loginName, password); } if(user == null){ loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10008); @@ -145,12 +142,13 @@ public class LoginServiceProcessor implements LoginCmdProcessor { } @Override - public void onSuccess(ChannelContext channelContext) { + public void onSuccess(ImChannelContext channelContext) { logger.info("登录成功回调方法"); - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + ImSessionContext imSessionContext = channelContext.getSessionContext(); User user = imSessionContext.getClient().getUser(); if(user.getGroups() != null){ - for(Group group : user.getGroups()){//发送加入群组通知 + //发送加入群组通知 + for(Group group : user.getGroups()){ ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ,JsonKit.toJsonBytes(group)); try { JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class); @@ -163,7 +161,7 @@ public class LoginServiceProcessor implements LoginCmdProcessor { } @Override - public boolean isProtocol(ChannelContext channelContext) { + public boolean isProtocol(ImChannelContext channelContext) { return true; } diff --git a/jim-server/pom.xml b/jim-server/pom.xml index 8562b3e..c3f091d 100644 --- a/jim-server/pom.xml +++ b/jim-server/pom.xml @@ -7,7 +7,7 @@ org.j-im jim-parent - 2.6.0.v20190114-RELEASE + 3.0.0.v20200101-RELEASE ../jim-parent/pom.xml diff --git a/jim-server/src/main/java/org/jim/server/ImServerChannelContext.java b/jim-server/src/main/java/org/jim/server/ImServerChannelContext.java new file mode 100644 index 0000000..bc12bc8 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/ImServerChannelContext.java @@ -0,0 +1,45 @@ +package org.jim.server; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImHandler; +import org.jim.common.config.ImConfig; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.common.protocol.IProtocol; +import org.jim.server.handler.AbstractProtocolHandler; +import org.tio.core.ChannelContext; +import org.tio.utils.thread.pool.AbstractQueueRunnable; + +/** + * @ClassName ImServerChannelContext + * @Description TODO + * @Author WChao + * @Date 2020/1/5 23:56 + * @Version 1.0 + **/ +public class ImServerChannelContext extends ImChannelContext { + + protected AbstractQueueRunnable msgQue; + + protected AbstractProtocolHandler protocolHandler; + + public ImServerChannelContext(ImConfig imConfig, ChannelContext tioChannelContext) { + super(imConfig, tioChannelContext); + } + + public AbstractQueueRunnable getMsgQue() { + return msgQue; + } + + public void setMsgQue(AbstractQueueRunnable msgQue) { + this.msgQue = msgQue; + } + + public AbstractProtocolHandler getProtocolHandler() { + return protocolHandler; + } + + public void setProtocolHandler(AbstractProtocolHandler protocolHandler) { + this.protocolHandler = protocolHandler; + } + +} diff --git a/jim-server/src/main/java/org/jim/server/ImServerGroupContext.java b/jim-server/src/main/java/org/jim/server/ImServerGroupContext.java index 76a3599..7bace9a 100644 --- a/jim-server/src/main/java/org/jim/server/ImServerGroupContext.java +++ b/jim-server/src/main/java/org/jim/server/ImServerGroupContext.java @@ -3,31 +3,19 @@ */ package org.jim.server; -import org.jim.common.ImConst; -import org.jim.common.ImAio; -import org.jim.common.ImConfig; -import org.jim.common.cache.redis.RedissonTemplate; -import org.jim.common.cluster.redis.RedisCluster; -import org.jim.common.cluster.redis.RedisClusterConfig; -import org.jim.server.command.CommandManager; -import org.jim.server.handler.ImServerAioHandler; -import org.jim.server.handler.ProtocolHandlerManager; -import org.jim.server.listener.ImServerAioListener; +import org.jim.common.config.ImConfig; +import org.jim.server.handler.ImServerHandler; +import org.jim.server.listener.ImServerListenerAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.server.ServerGroupContext; -import org.tio.utils.Threads; -import org.tio.utils.thread.pool.DefaultThreadFactory; import org.tio.utils.thread.pool.SynThreadPoolExecutor; -import java.util.concurrent.LinkedBlockingQueue; - /** * * @author WChao * */ -public class ImServerGroupContext extends ServerGroupContext{ +public class ImServerGroupContext /*extends TioConfig */{ private Logger log = LoggerFactory.getLogger(ImServerGroupContext.class); @@ -39,8 +27,8 @@ public class ImServerGroupContext extends ServerGroupContext{ protected SynThreadPoolExecutor timExecutor = null; - public ImServerGroupContext(ImConfig imConfig , ImServerAioHandler imServerAioHandler,ImServerAioListener imServerAioListener) { - super(imServerAioHandler, imServerAioListener); + public ImServerGroupContext(ImConfig imConfig , ImServerHandler imServerAioHandler, ImServerListenerAdapter imServerAioListener) { + /*super(imServerAioHandler, imServerAioListener); this.imConfig = imConfig; this.setHeartbeatTimeout(imConfig.getHeartbeatTimeout()); //是否开启集群 @@ -67,7 +55,7 @@ public class ImServerGroupContext extends ServerGroupContext{ imConfig.setGroupContext(this); ProtocolHandlerManager.init(imConfig); CommandManager.init(imConfig); - ImAio.imConfig = imConfig; + Jim.imConfig = imConfig;*/ } public SynThreadPoolExecutor getTimExecutor() { diff --git a/jim-server/src/main/java/org/jim/server/ImServerStarter.java b/jim-server/src/main/java/org/jim/server/ImServerStarter.java index 1802124..733ff42 100644 --- a/jim-server/src/main/java/org/jim/server/ImServerStarter.java +++ b/jim-server/src/main/java/org/jim/server/ImServerStarter.java @@ -4,72 +4,60 @@ package org.jim.server; import org.jim.common.ImConst; -import org.jim.common.ImConfig; -import org.jim.server.handler.ImServerAioHandler; +import org.jim.common.cache.redis.RedissonTemplate; +import org.jim.common.cluster.redis.RedisCluster; +import org.jim.common.cluster.redis.RedisClusterConfig; +import org.jim.common.config.ImConfig; +import org.jim.server.config.ImServerConfig; +import org.jim.server.handler.ProtocolManager; import org.jim.server.helper.redis.RedisMessageHelper; -import org.jim.server.listener.ImGroupListener; -import org.jim.server.listener.ImServerAioListener; -import org.tio.core.intf.GroupListener; -import org.tio.core.ssl.SslConfig; -import org.tio.server.AioServer; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.tio.server.ServerTioConfig; +import org.tio.server.TioServer; import java.io.IOException; /** - * + * J-IM服务端启动类 * @author WChao * */ public class ImServerStarter { - - private ImServerAioHandler imAioHandler = null; - private ImServerAioListener imAioListener = null; - private ImServerGroupContext imServerGroupContext = null; - private ImGroupListener imGroupListener = null; - private AioServer aioServer = null; - private ImConfig imConfig = null; - - public ImServerStarter(ImConfig imConfig){ - this(imConfig,null); + + private static Logger log = LoggerFactory.getLogger(ImServerStarter.class); + private TioServer tioServer = null; + private ImServerConfig imServerConfig; + + public ImServerStarter(ImServerConfig imServerConfig){ + this.imServerConfig = imServerConfig; + init(imServerConfig); } - public ImServerStarter(ImConfig imConfig,ImServerAioListener imAioListener){ - this.imConfig = imConfig; - this.imAioListener = imAioListener; - init(); - } - - public void init(){ - System.setProperty("tio.default.read.buffer.size", String.valueOf(imConfig.getReadBufferSize())); - imAioHandler = new ImServerAioHandler(imConfig) ; - if(imAioListener == null){ - imAioListener = new ImServerAioListener(imConfig); + public void init(ImServerConfig imServerConfig){ + ImConfig.Global.set(imServerConfig); + System.setProperty("tio.default.read.buffer.size", String.valueOf(imServerConfig.getReadBufferSize())); + if(imServerConfig.getMessageHelper() == null){ + imServerConfig.setMessageHelper(new RedisMessageHelper()); } - GroupListener groupListener = imConfig.getImGroupListener(); - if(groupListener == null){ - imConfig.setImGroupListener(new ImGroupListener()); - } - this.imGroupListener = (ImGroupListener)imConfig.getImGroupListener(); - imServerGroupContext = new ImServerGroupContext(imConfig,imAioHandler, imAioListener); - imServerGroupContext.setGroupListener(imGroupListener); - if(imConfig.getMessageHelper() == null){ - imConfig.setMessageHelper(new RedisMessageHelper(imConfig)); - } - //开启SSL - if(ImConst.ON.equals(imConfig.getIsSSL())){ - SslConfig sslConfig = imConfig.getSslConfig(); - if(sslConfig != null) { - imServerGroupContext.setSslConfig(sslConfig); + if(ImConfig.Const.ON.equals(imServerConfig.getIsCluster())){ + imServerConfig.setIsStore(ImConfig.Const.ON); + if(imServerConfig.getCluster() == null){ + try{ + imServerConfig.setCluster(new RedisCluster(RedisClusterConfig.newInstance(ImConst.Topic.REDIS_CLUSTER_TOPIC_SUFFIX, RedissonTemplate.me().getRedissonClient()))); + }catch(Exception e){ + log.error("连接集群配置出现异常,请检查!",e); + } } } - aioServer = new AioServer(imServerGroupContext); + ProtocolManager.init(); + tioServer = new TioServer((ServerTioConfig)imServerConfig.getTioConfig()); } public void start() throws IOException { - aioServer.start(this.imConfig.getBindIp(),this.imConfig.getBindPort()); + tioServer.start(this.imServerConfig.getBindIp(), this.imServerConfig.getBindPort()); } public void stop(){ - aioServer.stop(); + tioServer.stop(); } } diff --git a/jim-server/src/main/java/org/jim/server/command/AbstractCmdHandler.java b/jim-server/src/main/java/org/jim/server/command/AbstractCmdHandler.java index 1b90edc..230a67a 100644 --- a/jim-server/src/main/java/org/jim/server/command/AbstractCmdHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/AbstractCmdHandler.java @@ -3,24 +3,21 @@ */ package org.jim.server.command; -import com.google.common.collect.Lists; import org.apache.commons.collections4.CollectionUtils; -import org.jim.common.ImConfig; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.config.ImConfig; import org.jim.server.command.handler.processor.CmdProcessor; -import org.tio.core.ChannelContext; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import org.jim.server.config.ImServerConfig; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; /** * 版本: [1.0] * 功能说明: * @author: WChao 创建时间: 2017年9月11日 下午2:07:44 */ -public abstract class AbstractCmdHandler implements CmdHandler { +public abstract class AbstractCmdHandler implements CmdHandler, ImConst { /** * 不同协议cmd处理命令如(ws、socket、自定义协议)握手、心跳命令等. */ @@ -28,14 +25,10 @@ public abstract class AbstractCmdHandler implements CmdHandler { /** * IM相关配置类 */ - protected ImConfig imConfig; + protected ImServerConfig imConfig = ImConfig.Global.get(); public AbstractCmdHandler() {}; - public AbstractCmdHandler(ImConfig imConfig) { - this.imConfig = imConfig; - } - public AbstractCmdHandler addProcessor(CmdProcessor processor){ this.processors.put(processor.name(), processor); return this; @@ -43,16 +36,16 @@ public abstract class AbstractCmdHandler implements CmdHandler { /** * 根据当前通道所属协议获取cmd业务处理器 - * @param channelContext + * @param imChannelContext * @return */ - public List getProcessor(ChannelContext channelContext,Class clazz){ + public List getProcessor(ImChannelContext imChannelContext, Class clazz){ List processorList = null; for(Entry processorEntry : processors.entrySet()){ CmdProcessor processor = processorEntry.getValue(); - if(processor.isProtocol(channelContext)){ + if(processor.isProtocol(imChannelContext)){ if(CollectionUtils.isEmpty(processorList)){ - processorList = Lists.newArrayList(); + processorList = new ArrayList<>(); } processorList.add((T)processor); } @@ -71,7 +64,7 @@ public abstract class AbstractCmdHandler implements CmdHandler { CmdProcessor processor = processorEntry.getValue(); if(name.equals(processor.name())){ if(CollectionUtils.isEmpty(processorList)){ - processorList = Lists.newArrayList(); + processorList = new ArrayList<>(); } processorList.add((T)processor); } @@ -89,7 +82,7 @@ public abstract class AbstractCmdHandler implements CmdHandler { for(Entry processorEntry : processors.entrySet()){ CmdProcessor processor = processorEntry.getValue(); if(CollectionUtils.isEmpty(processorList)){ - processorList = Lists.newArrayList(); + processorList = new ArrayList<>(); } if(CollectionUtils.isEmpty(names)){ processorList.add((T)processor); @@ -105,13 +98,9 @@ public abstract class AbstractCmdHandler implements CmdHandler { return processors.remove(name); } - - public ImConfig getImConfig() { + + public ImServerConfig getImConfig() { return imConfig; } - public void setImConfig(ImConfig imConfig) { - this.imConfig = imConfig; - } - } diff --git a/jim-server/src/main/java/org/jim/server/command/CmdHandler.java b/jim-server/src/main/java/org/jim/server/command/CmdHandler.java index bcfe8c1..9fbfa66 100644 --- a/jim-server/src/main/java/org/jim/server/command/CmdHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/CmdHandler.java @@ -1,29 +1,31 @@ package org.jim.server.command; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; -import org.tio.core.ChannelContext; +import org.jim.common.exception.ImException; import org.jim.common.packets.Command; /** * * 版本: [1.0] * 功能说明: - * 作者: WChao 创建时间: 2017年9月8日 下午4:29:38 + * @author : WChao 创建时间: 2017年9月8日 下午4:29:38 */ public interface CmdHandler { /** * 功能描述:[命令主键] - * 创建者:WChao 创建时间: 2017年7月17日 下午2:31:51 + * @author:WChao 创建时间: 2017年7月17日 下午2:31:51 * @return */ - public Command command(); + Command command(); /** - * @param packet - * @param channelContext + * 处理Cmd命令 + * @param imPacket + * @param imChannelContext * @return - * @throws Exception + * @throws ImException * @date 2016年11月18日 下午1:08:45 */ - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception; + ImPacket handler(ImPacket imPacket, ImChannelContext imChannelContext) throws ImException; } diff --git a/jim-server/src/main/java/org/jim/server/command/CommandManager.java b/jim-server/src/main/java/org/jim/server/command/CommandManager.java index 85304f8..6b35e85 100644 --- a/jim-server/src/main/java/org/jim/server/command/CommandManager.java +++ b/jim-server/src/main/java/org/jim/server/command/CommandManager.java @@ -3,9 +3,9 @@ */ package org.jim.server.command; -import org.jim.common.ImConfig; import org.jim.common.packets.Command; import org.jim.server.command.handler.processor.CmdProcessor; +import org.jim.server.config.ImServerConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,9 +24,7 @@ public class CommandManager{ */ private static Map handlerMap = new HashMap<>(); private static Logger LOG = LoggerFactory.getLogger(CommandManager.class); - - private static ImConfig imConfig; - + private CommandManager(){}; static{ @@ -63,7 +61,6 @@ public class CommandManager{ } if(handlerMap.get(cmd_number) == null) { - imCommandHandler.setImConfig(imConfig); return handlerMap.put(cmd_number,imCommandHandler); } return null; @@ -95,18 +92,4 @@ public class CommandManager{ } return handlerMap.get(command.getNumber()); } - - public static void init(ImConfig config) { - imConfig = config; - for(Entry entry : handlerMap.entrySet()){ - try { - entry.getValue().setImConfig(imConfig); - } catch (Exception e) { - LOG.error(e.toString()); - } - } - } - public static ImConfig getImConfig() { - return imConfig; - } } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/AuthReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/AuthReqHandler.java index 3eb0a41..e6c9846 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/AuthReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/AuthReqHandler.java @@ -1,15 +1,18 @@ package org.jim.server.command.handler; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; import org.jim.common.ImPacket; import org.jim.common.ImStatus; -import org.tio.core.ChannelContext; +import org.jim.common.exception.ImException; import org.jim.common.packets.AuthReqBody; import org.jim.common.packets.Command; import org.jim.common.packets.RespBody; import org.jim.common.utils.ImKit; import org.jim.common.utils.JsonKit; import org.jim.server.command.AbstractCmdHandler; +import org.jim.server.handler.ProtocolManager; + /** * * 版本: [1.0] @@ -19,11 +22,11 @@ import org.jim.server.command.AbstractCmdHandler; public class AuthReqHandler extends AbstractCmdHandler { @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception + public ImPacket handler(ImPacket packet, ImChannelContext channelContext) throws ImException { if (packet.getBody() == null) { RespBody respBody = new RespBody(Command.COMMAND_AUTH_RESP,ImStatus.C10010); - return ImKit.ConvertRespPacket(respBody, channelContext); + return ProtocolManager.Converter.respPacket(respBody, channelContext); } AuthReqBody authReqBody = JsonKit.toBean(packet.getBody(), AuthReqBody.class); String token = authReqBody.getToken() == null ? "" : authReqBody.getToken(); @@ -31,7 +34,7 @@ public class AuthReqHandler extends AbstractCmdHandler authReqBody.setToken(data); authReqBody.setCmd(null); RespBody respBody = new RespBody(Command.COMMAND_AUTH_RESP,ImStatus.C10009).setData(authReqBody); - return ImKit.ConvertRespPacket(respBody, channelContext); + return ProtocolManager.Converter.respPacket(respBody, channelContext); } @Override diff --git a/jim-server/src/main/java/org/jim/server/command/handler/ChatReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/ChatReqHandler.java index ad96571..a6c337a 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/ChatReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/ChatReqHandler.java @@ -1,21 +1,18 @@ package org.jim.server.command.handler; -import com.google.common.collect.Sets; -import org.apache.commons.collections4.CollectionUtils; -import org.jim.common.ImAio; -import org.jim.common.ImConst; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; +import org.jim.common.exception.ImException; import org.jim.common.packets.ChatBody; import org.jim.common.packets.ChatType; import org.jim.common.packets.Command; import org.jim.common.packets.RespBody; import org.jim.common.utils.ChatKit; +import org.jim.server.ImServerChannelContext; import org.jim.server.command.AbstractCmdHandler; -import org.jim.server.command.handler.processor.chat.ChatCmdProcessor; -import org.jim.server.command.handler.processor.chat.MsgQueueRunnable; -import org.tio.core.ChannelContext; - -import java.util.List; +import org.jim.server.handler.ProtocolManager; +import org.tio.utils.thread.pool.AbstractQueueRunnable; /** * 版本: [1.0] @@ -25,26 +22,27 @@ import java.util.List; public class ChatReqHandler extends AbstractCmdHandler { @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handler(ImPacket packet, ImChannelContext channelContext) throws ImException { + ImServerChannelContext imServerChannelContext = (ImServerChannelContext)channelContext; if (packet.getBody() == null) { - throw new Exception("body is null"); + throw new ImException("body is null"); } ChatBody chatBody = ChatKit.toChatBody(packet.getBody(), channelContext); packet.setBody(chatBody.toByte()); //聊天数据格式不正确 if(chatBody == null || chatBody.getChatType() == null){ - ImPacket respChatPacket = ChatKit.dataInCorrectRespPacket(channelContext); + ImPacket respChatPacket = ProtocolManager.Packet.dataInCorrect(channelContext); return respChatPacket; } - List chatProcessors = this.getProcessorNotEqualName(Sets.newHashSet(ImConst.BASE_ASYNC_CHAT_MESSAGE_PROCESSOR),ChatCmdProcessor.class); + /*List chatProcessors = this.getProcessorNotEqualName(new HashSet<>(ImConst.BASE_ASYNC_CHAT_MESSAGE_PROCESSOR),ChatCmdProcessor.class); if(CollectionUtils.isNotEmpty(chatProcessors)){ chatProcessors.forEach(chatProcessor -> chatProcessor.handler(packet,channelContext)); - } + }*/ //异步调用业务处理消息接口 if(ChatType.forNumber(chatBody.getChatType()) != null){ - MsgQueueRunnable msgQueueRunnable = (MsgQueueRunnable)channelContext.getAttribute(ImConst.CHAT_QUEUE); + AbstractQueueRunnable msgQueueRunnable = imServerChannelContext.getMsgQue(); msgQueueRunnable.addMsg(packet); - msgQueueRunnable.getExecutor().execute(msgQueueRunnable); + msgQueueRunnable.executor.execute(msgQueueRunnable); } ImPacket chatPacket = new ImPacket(Command.COMMAND_CHAT_REQ,new RespBody(Command.COMMAND_CHAT_REQ,chatBody).toByte()); //设置同步序列号; @@ -53,19 +51,19 @@ public class ChatReqHandler extends AbstractCmdHandler { if(ChatType.CHAT_TYPE_PRIVATE.getNumber() == chatBody.getChatType()){ String toId = chatBody.getTo(); if(ChatKit.isOnline(toId,imConfig)){ - ImAio.sendToUser(toId, chatPacket); + Jim.sendToUser(toId, chatPacket); //发送成功响应包 - return ChatKit.sendSuccessRespPacket(channelContext); + return ProtocolManager.Packet.success(channelContext); }else{ //用户不在线响应包 - return ChatKit.offlineRespPacket(channelContext); + return ProtocolManager.Packet.offline(channelContext); } //群聊 }else if(ChatType.CHAT_TYPE_PUBLIC.getNumber() == chatBody.getChatType()){ String group_id = chatBody.getGroup_id(); - ImAio.sendToGroup(group_id, chatPacket); + Jim.sendToGroup(group_id, chatPacket); //发送成功响应包 - return ChatKit.sendSuccessRespPacket(channelContext); + return ProtocolManager.Packet.success(channelContext); } return null; } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/CloseReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/CloseReqHandler.java index c845055..3883635 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/CloseReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/CloseReqHandler.java @@ -1,15 +1,17 @@ package org.jim.server.command.handler; -import org.jim.common.ImAio; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.ImStatus; +import org.jim.common.exception.ImException; import org.jim.common.packets.CloseReqBody; import org.jim.common.packets.Command; import org.jim.common.packets.RespBody; import org.jim.common.utils.ImKit; import org.jim.common.utils.JsonKit; import org.jim.server.command.AbstractCmdHandler; -import org.tio.core.ChannelContext; +import org.jim.server.handler.ProtocolManager; /** * 版本: [1.0] @@ -19,22 +21,23 @@ import org.tio.core.ChannelContext; public class CloseReqHandler extends AbstractCmdHandler { @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception + public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws ImException { CloseReqBody closeReqBody = null; try{ closeReqBody = JsonKit.toBean(packet.getBody(),CloseReqBody.class); }catch (Exception e) { //关闭请求消息格式不正确 - return ImKit.ConvertRespPacket(new RespBody(Command.COMMAND_CLOSE_REQ, ImStatus.C10020), channelContext); + return ProtocolManager.Converter.respPacket(new RespBody(Command.COMMAND_CLOSE_REQ, ImStatus.C10020), imChannelContext); } + Jim.bSend(imChannelContext, ProtocolManager.Converter.respPacket(new RespBody(Command.COMMAND_CLOSE_REQ, ImStatus.C10021), imChannelContext)); if(closeReqBody == null || closeReqBody.getUserid() == null){ - ImAio.remove(channelContext, "收到关闭请求"); + Jim.remove(imChannelContext, "收到关闭请求"); }else{ String userId = closeReqBody.getUserid(); - ImAio.remove(userId, "收到关闭请求!"); + Jim.remove(userId, "收到关闭请求!"); } - return ImKit.ConvertRespPacket(new RespBody(Command.COMMAND_CLOSE_REQ, ImStatus.C10021), channelContext); + return null; } @Override diff --git a/jim-server/src/main/java/org/jim/server/command/handler/HandshakeReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/HandshakeReqHandler.java index 1522d6b..6ee95b1 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/HandshakeReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/HandshakeReqHandler.java @@ -1,16 +1,15 @@ package org.jim.server.command.handler; import org.apache.commons.collections4.CollectionUtils; -import org.jim.common.ImAio; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpRequest; import org.jim.common.packets.Command; import org.jim.common.ws.WsSessionContext; import org.jim.server.command.AbstractCmdHandler; import org.jim.server.command.handler.processor.handshake.HandshakeCmdProcessor; -import org.tio.core.Aio; -import org.tio.core.ChannelContext; - import java.util.List; /** @@ -21,22 +20,22 @@ import java.util.List; public class HandshakeReqHandler extends AbstractCmdHandler { @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handler(ImPacket packet, ImChannelContext channelContext) throws ImException { List handshakeProcessors = this.getProcessor(channelContext,HandshakeCmdProcessor.class); if(CollectionUtils.isEmpty(handshakeProcessors)){ - Aio.remove(channelContext, "没有对应的握手协议处理器HandshakeProCmd..."); + Jim.remove(channelContext, "没有对应的握手协议处理器HandshakeProCmd..."); return null; } HandshakeCmdProcessor handShakeProCmdHandler = handshakeProcessors.get(0); ImPacket handShakePacket = handShakeProCmdHandler.handshake(packet, channelContext); if (handShakePacket == null) { - Aio.remove(channelContext, "业务层不同意握手"); + Jim.remove(channelContext, "业务层不同意握手"); return null; } - ImAio.send(channelContext, handShakePacket); - WsSessionContext wsSessionContext = (WsSessionContext) channelContext.getAttribute(); + Jim.send(channelContext, handShakePacket); + WsSessionContext wsSessionContext = (WsSessionContext) channelContext.getSessionContext(); HttpRequest request = wsSessionContext.getHandshakeRequestPacket(); - handShakeProCmdHandler.onAfterHandshaked(request, channelContext); + handShakeProCmdHandler.onAfterHandshake(request, channelContext); return null; } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/HeartbeatReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/HeartbeatReqHandler.java index 6476876..2f754fb 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/HeartbeatReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/HeartbeatReqHandler.java @@ -1,13 +1,13 @@ package org.jim.server.command.handler; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; -import org.jim.common.Protocol; +import org.jim.common.exception.ImException; import org.jim.common.packets.Command; import org.jim.common.packets.HeartbeatBody; import org.jim.common.packets.RespBody; -import org.jim.common.utils.ImKit; import org.jim.server.command.AbstractCmdHandler; -import org.tio.core.ChannelContext; +import org.jim.server.handler.ProtocolManager; /** * @@ -15,10 +15,10 @@ import org.tio.core.ChannelContext; public class HeartbeatReqHandler extends AbstractCmdHandler { @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception + public ImPacket handler(ImPacket packet, ImChannelContext channelContext) throws ImException { RespBody heartbeatBody = new RespBody(Command.COMMAND_HEARTBEAT_REQ).setData(new HeartbeatBody(Protocol.HEARTBEAT_BYTE)); - ImPacket heartbeatPacket = ImKit.ConvertRespPacket(heartbeatBody,channelContext); + ImPacket heartbeatPacket = ProtocolManager.Converter.respPacket(heartbeatBody,channelContext); return heartbeatPacket; } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/JoinGroupReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/JoinGroupReqHandler.java index 3f03961..b72db0c 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/JoinGroupReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/JoinGroupReqHandler.java @@ -2,15 +2,12 @@ package org.jim.server.command.handler; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImAio; -import org.jim.common.ImPacket; -import org.jim.common.ImSessionContext; -import org.jim.common.ImStatus; +import org.jim.common.*; +import org.jim.common.exception.ImException; import org.jim.server.command.handler.processor.group.GroupCmdProcessor; +import org.jim.server.handler.ProtocolManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.Aio; -import org.tio.core.ChannelContext; import org.jim.common.packets.Command; import org.jim.common.packets.Group; import org.jim.common.packets.JoinGroupNotifyRespBody; @@ -18,10 +15,8 @@ import org.jim.common.packets.JoinGroupRespBody; import org.jim.common.packets.JoinGroupResult; import org.jim.common.packets.RespBody; import org.jim.common.packets.User; -import org.jim.common.utils.ImKit; import org.jim.common.utils.JsonKit; import org.jim.server.command.AbstractCmdHandler; - import java.util.List; /** @@ -35,20 +30,20 @@ public class JoinGroupReqHandler extends AbstractCmdHandler { private static Logger log = LoggerFactory.getLogger(JoinGroupReqHandler.class); @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws ImException { //绑定群组; - ImPacket joinGroupRespPacket = bindGroup(packet, channelContext); + ImPacket joinGroupRespPacket = bindGroup(packet, imChannelContext); //发送进房间通知; - joinGroupNotify(packet,channelContext); + joinGroupNotify(packet,imChannelContext); return joinGroupRespPacket; } /** * 发送进房间通知; * @param packet - * @param channelContext + * @param imChannelContext */ - public void joinGroupNotify(ImPacket packet,ChannelContext channelContext){ - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + public void joinGroupNotify(ImPacket packet, ImChannelContext imChannelContext)throws ImException{ + ImSessionContext imSessionContext = imChannelContext.getSessionContext(); User clientUser = imSessionContext.getClient().getUser(); User notifyUser = new User(clientUser.getId(),clientUser.getNick()); @@ -56,55 +51,52 @@ public class JoinGroupReqHandler extends AbstractCmdHandler { Group joinGroup = JsonKit.toBean(packet.getBody(),Group.class); String groupId = joinGroup.getGroup_id(); //发进房间通知 COMMAND_JOIN_GROUP_NOTIFY_RESP - JoinGroupNotifyRespBody joinGroupNotifyRespBody = new JoinGroupNotifyRespBody().setGroup(groupId).setUser(notifyUser); - RespBody notifyRespBody = new RespBody(Command.COMMAND_JOIN_GROUP_NOTIFY_RESP,joinGroupNotifyRespBody); - - ImPacket joinGroupNotifyRespPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_NOTIFY_RESP,notifyRespBody.toByte()); - ImAio.sendToGroup(groupId, joinGroupNotifyRespPacket); + JoinGroupNotifyRespBody joinGroupNotifyRespBody = new JoinGroupNotifyRespBody(Command.COMMAND_JOIN_GROUP_NOTIFY_RESP, ImStatus.C10011) + .setGroup(groupId) + .setUser(notifyUser); + Jim.sendToGroup(groupId, ProtocolManager.Converter.respPacket(joinGroupNotifyRespBody,imChannelContext)); } /** * 绑定群组 * @param packet - * @param channelContext + * @param imChannelContext * @return - * @throws Exception + * @throws ImException */ - public ImPacket bindGroup(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket bindGroup(ImPacket packet, ImChannelContext imChannelContext) throws ImException { if (packet.getBody() == null) { - throw new Exception("body is null"); + throw new ImException("body is null"); } Group joinGroup = JsonKit.toBean(packet.getBody(),Group.class); String groupId = joinGroup.getGroup_id(); if (StringUtils.isBlank(groupId)) { - log.error("group is null,{}", channelContext); - Aio.close(channelContext, "group is null when join group"); + log.error("group is null,{}", imChannelContext); + Jim.close(imChannelContext, "group is null when join group"); return null; } //实际绑定之前执行处理器动作 - List groupCmdProcessors = this.getProcessor(channelContext, GroupCmdProcessor.class); + List groupCmdProcessors = this.getProcessor(imChannelContext, GroupCmdProcessor.class); - //先定义为操作成功 - JoinGroupResult joinGroupResult = JoinGroupResult.JOIN_GROUP_RESULT_OK; - JoinGroupRespBody joinGroupRespBody = new JoinGroupRespBody(); + JoinGroupRespBody joinGroupRespBody = new JoinGroupRespBody(Command.COMMAND_JOIN_GROUP_RESP,ImStatus.C10011); //当有群组处理器时候才会去处理 if(CollectionUtils.isNotEmpty(groupCmdProcessors)){ GroupCmdProcessor groupCmdProcessor = groupCmdProcessors.get(0); - joinGroupRespBody = groupCmdProcessor.join(joinGroup, channelContext); + joinGroupRespBody = groupCmdProcessor.join(joinGroup, imChannelContext); if (joinGroupRespBody == null || JoinGroupResult.JOIN_GROUP_RESULT_OK.getNumber() != joinGroupRespBody.getResult().getNumber()) { RespBody joinRespBody = new RespBody(Command.COMMAND_JOIN_GROUP_RESP, ImStatus.C10012).setData(joinGroupRespBody); - ImPacket respPacket = ImKit.ConvertRespPacket(joinRespBody, channelContext); + ImPacket respPacket = ProtocolManager.Converter.respPacket(joinRespBody, imChannelContext); return respPacket; } } //处理完处理器内容后 - ImAio.bindGroup(channelContext, groupId,imConfig.getMessageHelper().getBindListener()); + Jim.bindGroup(imChannelContext, groupId); //回一条消息,告诉对方进群结果 joinGroupRespBody.setGroup(groupId); - joinGroupRespBody.setResult(joinGroupResult); - - RespBody joinRespBody = new RespBody(Command.COMMAND_JOIN_GROUP_RESP,ImStatus.C10011).setData(joinGroupRespBody); - ImPacket respPacket = ImKit.ConvertRespPacket(joinRespBody, channelContext); + //先定义为操作成功 + joinGroupRespBody.setResult(JoinGroupResult.JOIN_GROUP_RESULT_OK); + joinGroupRespBody.setData(joinGroupRespBody); + ImPacket respPacket = ProtocolManager.Converter.respPacket(joinGroupRespBody, imChannelContext); return respPacket; } @Override diff --git a/jim-server/src/main/java/org/jim/server/command/handler/LoginReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/LoginReqHandler.java index 8976c3d..0a1ee42 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/LoginReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/LoginReqHandler.java @@ -1,11 +1,9 @@ package org.jim.server.command.handler; import org.apache.commons.collections4.CollectionUtils; -import org.jim.common.ImConst; -import org.jim.common.ImAio; -import org.jim.common.ImPacket; -import org.jim.common.ImSessionContext; -import org.jim.common.ImStatus; +import org.jim.common.*; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImException; import org.jim.common.message.MessageHelper; import org.jim.common.packets.Command; import org.jim.common.packets.Group; @@ -15,13 +13,15 @@ import org.jim.common.packets.User; import org.jim.common.protocol.IProtocol; import org.jim.common.utils.ImKit; import org.jim.common.utils.JsonKit; +import org.jim.server.ImServerChannelContext; import org.jim.server.command.AbstractCmdHandler; import org.jim.server.command.CommandManager; import org.jim.server.command.handler.processor.login.LoginCmdProcessor; +import org.jim.server.handler.ProtocolManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.Aio; import org.tio.core.ChannelContext; +import org.tio.core.Tio; import java.util.List; @@ -34,22 +34,23 @@ public class LoginReqHandler extends AbstractCmdHandler { private static Logger log = LoggerFactory.getLogger(LoginReqHandler.class); @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws ImException { + ImServerChannelContext imServerChannelContext = (ImServerChannelContext)imChannelContext; if (packet.getBody() == null) { - Aio.remove(channelContext, "body is null"); + Jim.remove(imChannelContext, "body is null"); return null; } - List loginProcessors = this.getProcessor(channelContext, LoginCmdProcessor.class); + List loginProcessors = this.getProcessor(imChannelContext, LoginCmdProcessor.class); if(CollectionUtils.isEmpty(loginProcessors)){ log.info("登录失败,没有登录命令业务处理器!"); - Aio.remove(channelContext, "no login serviceHandler processor!"); + Jim.remove(imChannelContext, "no login serviceHandler processor!"); return null; } LoginCmdProcessor loginServiceHandler = loginProcessors.get(0); - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + ImSessionContext imSessionContext = imChannelContext.getSessionContext(); LoginReqBody loginReqBody = JsonKit.toBean(packet.getBody(),LoginReqBody.class); - LoginRespBody loginRespBody = loginServiceHandler.doLogin(loginReqBody,channelContext); + LoginRespBody loginRespBody = loginServiceHandler.doLogin(loginReqBody, imChannelContext); if (loginRespBody == null || loginRespBody.getUser() == null) { log.info("登录失败, loginName:{}, password:{}", loginReqBody.getLoginname(), loginReqBody.getPassword()); if(loginRespBody == null){ @@ -57,32 +58,30 @@ public class LoginReqHandler extends AbstractCmdHandler { } loginRespBody.clear(); ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte()); - ImAio.bSend(channelContext,loginRespPacket); - ImAio.remove(channelContext, "loginName and token is incorrect"); + Jim.bSend(imChannelContext, loginRespPacket); + Jim.remove(imChannelContext, "loginName and token is incorrect"); return null; } User user = loginRespBody.getUser(); - String userId = user.getId(); - IProtocol protocol = ImKit.protocol(null, channelContext); + IProtocol protocol = imServerChannelContext.getProtocolHandler().getProtocol(); String terminal = protocol == null ? "" : protocol.name(); user.setTerminal(terminal); imSessionContext.getClient().setUser(user); - ImAio.bindUser(channelContext,userId,imConfig.getMessageHelper().getBindListener()); + Jim.bindUser(imServerChannelContext, user.getId()); //初始化绑定或者解绑群组; - bindUnbindGroup(channelContext, user); - loginServiceHandler.onSuccess(channelContext); + bindUnbindGroup(imChannelContext, user); + loginServiceHandler.onSuccess(imChannelContext); loginRespBody.clear(); - ImPacket loginRespPacket = new ImPacket(Command.COMMAND_LOGIN_RESP, loginRespBody.toByte()); - return loginRespPacket; + return ProtocolManager.Converter.respPacket(loginRespBody, imChannelContext); } /** * 初始化绑定或者解绑群组; */ - public void bindUnbindGroup(ChannelContext channelContext , User user)throws Exception{ + public void bindUnbindGroup(ImChannelContext imChannelContext , User user)throws ImException{ String userId = user.getId(); List groups = user.getGroups(); if( groups != null){ - boolean isStore = ImConst.ON.equals(imConfig.getIsStore()); + boolean isStore = ImConfig.Const.ON.equals(imConfig.getIsStore()); MessageHelper messageHelper = null; List groupIds = null; if(isStore){ @@ -97,14 +96,14 @@ public class LoginReqHandler extends AbstractCmdHandler { ImPacket groupPacket = new ImPacket(Command.COMMAND_JOIN_GROUP_REQ,JsonKit.toJsonBytes(group)); try { JoinGroupReqHandler joinGroupReqHandler = CommandManager.getCommand(Command.COMMAND_JOIN_GROUP_REQ, JoinGroupReqHandler.class); - joinGroupReqHandler.bindGroup(groupPacket, channelContext); + joinGroupReqHandler.bindGroup(groupPacket, imChannelContext); } catch (Exception e) { log.error(e.toString(),e); } } if(isStore && groupIds != null){ for(String groupId : groupIds){ - messageHelper.getBindListener().onAfterGroupUnbind(channelContext, groupId); + messageHelper.getBindListener().onAfterGroupUnbind(imChannelContext, groupId); } } } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/MessageReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/MessageReqHandler.java index 5093579..65054c2 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/MessageReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/MessageReqHandler.java @@ -1,10 +1,11 @@ package org.jim.server.command.handler; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImConst; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.jim.common.ImStatus; -import org.tio.core.ChannelContext; +import org.jim.common.exception.ImException; +import org.jim.server.config.ImServerConfig; import org.jim.common.message.MessageHelper; import org.jim.common.packets.Command; import org.jim.common.packets.RespBody; @@ -13,6 +14,7 @@ import org.jim.common.packets.MessageReqBody; import org.jim.common.utils.ImKit; import org.jim.common.utils.JsonKit; import org.jim.server.command.AbstractCmdHandler; +import org.jim.server.handler.ProtocolManager; /** * 获取聊天消息命令处理器 @@ -28,14 +30,14 @@ public class MessageReqHandler extends AbstractCmdHandler { } @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception { - RespBody resPacket = null; - MessageReqBody messageReqBody = null; + public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws ImException { + RespBody resPacket; + MessageReqBody messageReqBody; try{ messageReqBody = JsonKit.toBean(packet.getBody(),MessageReqBody.class); }catch (Exception e) { //用户消息格式不正确 - return getMessageFailedPacket(channelContext); + return getMessageFailedPacket(imChannelContext); } UserMessageData messageData = null; MessageHelper messageHelper = imConfig.getMessageHelper(); @@ -56,8 +58,8 @@ public class MessageReqHandler extends AbstractCmdHandler { //消息类型; int type = messageReqBody.getType(); //如果用户ID为空或者type格式不正确,获取消息失败; - if(StringUtils.isEmpty(userId) || (0 != type && 1 != type) || !ImConst.ON.equals(imConfig.getIsStore())){ - return getMessageFailedPacket(channelContext); + if(StringUtils.isEmpty(userId) || (0 != type && 1 != type) || !ImServerConfig.Const.ON.equals(imConfig.getIsStore())){ + return getMessageFailedPacket(imChannelContext); } if(type == 0){ resPacket = new RespBody(Command.COMMAND_GET_MESSAGE_RESP,ImStatus.C10016); @@ -78,7 +80,7 @@ public class MessageReqHandler extends AbstractCmdHandler { if(0 == type){ messageData = messageHelper.getFriendsOfflineMessage(userId); }else{ - return getMessageFailedPacket(channelContext); + return getMessageFailedPacket(imChannelContext); } }else{ //获取与指定用户离线消息; @@ -90,15 +92,15 @@ public class MessageReqHandler extends AbstractCmdHandler { } } resPacket.setData(messageData); - return ImKit.ConvertRespPacket(resPacket, channelContext); + return ProtocolManager.Converter.respPacket(resPacket, imChannelContext); } /** * 获取用户消息失败响应包; - * @param channelContext + * @param imChannelContext * @return */ - public ImPacket getMessageFailedPacket(ChannelContext channelContext){ + public ImPacket getMessageFailedPacket(ImChannelContext imChannelContext) throws ImException{ RespBody resPacket = new RespBody(Command.COMMAND_GET_MESSAGE_RESP,ImStatus.C10015); - return ImKit.ConvertRespPacket(resPacket, channelContext); + return ProtocolManager.Converter.respPacket(resPacket, imChannelContext); } } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/UserReqHandler.java b/jim-server/src/main/java/org/jim/server/command/handler/UserReqHandler.java index 58d363c..73152d4 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/UserReqHandler.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/UserReqHandler.java @@ -4,10 +4,9 @@ package org.jim.server.command.handler; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImConst; -import org.jim.common.ImAio; -import org.jim.common.ImPacket; -import org.jim.common.ImStatus; +import org.jim.common.*; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImException; import org.jim.common.message.MessageHelper; import org.jim.common.packets.Command; import org.jim.common.packets.Group; @@ -17,7 +16,7 @@ import org.jim.common.packets.UserReqBody; import org.jim.common.utils.ImKit; import org.jim.common.utils.JsonKit; import org.jim.server.command.AbstractCmdHandler; -import org.tio.core.ChannelContext; +import org.jim.server.handler.ProtocolManager; import java.util.ArrayList; import java.util.List; @@ -34,14 +33,13 @@ public class UserReqHandler extends AbstractCmdHandler { } @Override - public ImPacket handler(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handler(ImPacket packet, ImChannelContext imChannelContext) throws ImException { UserReqBody userReqBody = JsonKit.toBean(packet.getBody(),UserReqBody.class); User user = null; RespBody resPacket = null; - String userId = userReqBody.getUserid(); if(StringUtils.isEmpty(userId)) { - return ImKit.ConvertRespPacket(new RespBody(Command.COMMAND_GET_USER_RESP, ImStatus.C10004), channelContext); + return ProtocolManager.Converter.respPacket(new RespBody(Command.COMMAND_GET_USER_RESP, ImStatus.C10004), imChannelContext); } //(0:所有在线用户,1:所有离线用户,2:所有用户[在线+离线]); Integer type = userReqBody.getType() == null ? 2 : userReqBody.getType(); @@ -59,34 +57,34 @@ public class UserReqHandler extends AbstractCmdHandler { } } if(user == null) { - return ImKit.ConvertRespPacket(new RespBody(Command.COMMAND_GET_USER_RESP, ImStatus.C10004), channelContext); + return ProtocolManager.Converter.respPacket(new RespBody(Command.COMMAND_GET_USER_RESP, ImStatus.C10004), imChannelContext); } resPacket.setData(user); - return ImKit.ConvertRespPacket(resPacket, channelContext); + return ProtocolManager.Converter.respPacket(resPacket, imChannelContext); } /** * 根据用户id获取用户在线及离线用户; - * @param userid + * @param userId * @param type(0:所有在线用户,1:所有离线用户,2:所有用户[在线+离线]) * @return */ - public User getUserInfo(String userid , Integer type){ + public User getUserInfo(String userId , Integer type){ User user = null; //是否开启持久化; - boolean isStore = ImConst.ON.equals(imConfig.getIsStore()); + boolean isStore = ImConfig.Const.ON.equals(imConfig.getIsStore()); //消息持久化助手; MessageHelper messageHelper = imConfig.getMessageHelper(); if(isStore){ - user = messageHelper.getUserByType(userid, 2); + user = messageHelper.getUserByType(userId, 2); if(user == null) { return null; } - user.setFriends(messageHelper.getAllFriendUsers(userid, type)); - user.setGroups(messageHelper.getAllGroupUsers(userid, type)); + user.setFriends(messageHelper.getAllFriendUsers(userId, type)); + user.setGroups(messageHelper.getAllGroupUsers(userId, type)); return user; }else{ - user = ImAio.getUser(userid); + //user = Jim.getUser(userId); if(user == null) { return null; } @@ -129,14 +127,14 @@ public class UserReqHandler extends AbstractCmdHandler { Group copyGroup = ImKit.copyGroupWithoutUsers(group); List users = null; if(flag == 1){ - users = ImAio.getAllUserByGroup(group.getGroup_id()); + //users = Jim.getAllUserByGroup(group.getGroup_id()); }else if(flag == 0){ users = group.getUsers(); } if(users != null && !users.isEmpty()){ List copyUsers = new ArrayList(); for(User userObj : users){ - User onlineUser = ImAio.getUser(userObj.getId()); + /*User onlineUser = Jim.getUser(userObj.getId()); //在线 if(onlineUser != null && type == 0){ User copyOnlineUser = ImKit.copyUserWithoutFriendsGroups(onlineUser); @@ -145,7 +143,7 @@ public class UserReqHandler extends AbstractCmdHandler { }else if(onlineUser == null && type == 1){ User copyOnlineUser = ImKit.copyUserWithoutFriendsGroups(onlineUser); copyUsers.add(copyOnlineUser); - } + }*/ } copyGroup.setUsers(copyUsers); } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/CmdProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/CmdProcessor.java index b317a85..5975f92 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/CmdProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/CmdProcessor.java @@ -3,24 +3,24 @@ */ package org.jim.server.command.handler.processor; -import org.tio.core.ChannelContext; - +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; /** * 不同协议CMD命令处理接口 * @author WChao * */ -public interface CmdProcessor { +public interface CmdProcessor extends ImConst { /** * 不同协议判断方法 - * @param channelContext + * @param imChannelContext * @return */ - public boolean isProtocol(ChannelContext channelContext); + boolean isProtocol(ImChannelContext imChannelContext); /** * 该proCmd处理器名称(自定义) * @return */ - public String name(); + String name(); } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/AsyncChatMessageProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/AsyncChatMessageProcessor.java index 687438c..accb420 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/AsyncChatMessageProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/AsyncChatMessageProcessor.java @@ -10,10 +10,9 @@ */ package org.jim.server.command.handler.processor.chat; +import org.jim.common.ImChannelContext; import org.jim.common.packets.ChatBody; import org.jim.server.command.handler.processor.CmdProcessor; -import org.tio.core.ChannelContext; - /** * * 聊天消息异步业务处理器 @@ -26,8 +25,8 @@ public interface AsyncChatMessageProcessor extends CmdProcessor{ /** * 聊天消息异步业务处理器执行方法; * @param chatBody - * @param channelContext + * @param imChannelContext * @throws Exception */ - public void handler(ChatBody chatBody, ChannelContext channelContext); + void handler(ChatBody chatBody, ImChannelContext imChannelContext); } \ No newline at end of file diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/BaseAsyncChatMessageProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/BaseAsyncChatMessageProcessor.java index 99c1540..c131f0e 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/BaseAsyncChatMessageProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/BaseAsyncChatMessageProcessor.java @@ -1,14 +1,13 @@ package org.jim.server.command.handler.processor.chat; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; -import org.jim.common.ImConfig; +import org.jim.common.config.ImConfig; import org.jim.common.message.MessageHelper; import org.jim.common.packets.ChatBody; import org.jim.common.packets.ChatType; import org.jim.common.utils.ChatKit; -import org.jim.server.command.CommandManager; -import org.tio.core.ChannelContext; - +import org.jim.server.config.ImServerConfig; import java.util.List; /** * @author WChao @@ -16,16 +15,16 @@ import java.util.List; */ public abstract class BaseAsyncChatMessageProcessor implements AsyncChatMessageProcessor,ImConst { - protected ImConfig imConfig = null; + protected ImServerConfig imServerConfig = ImConfig.Global.get(); /** * 供子类拿到消息进行业务处理(如:消息持久化到数据库等)的抽象方法 * @param chatBody - * @param channelContext + * @param imChannelContext */ - protected abstract void doHandler(ChatBody chatBody, ChannelContext channelContext); + protected abstract void doHandler(ChatBody chatBody, ImChannelContext imChannelContext); @Override - public boolean isProtocol(ChannelContext channelContext) { + public boolean isProtocol(ImChannelContext imChannelContext) { return true; } @@ -35,12 +34,9 @@ public abstract class BaseAsyncChatMessageProcessor implements AsyncChatMessageP } @Override - public void handler(ChatBody chatBody, ChannelContext channelContext){ - if(imConfig == null) { - imConfig = CommandManager.getImConfig(); - } + public void handler(ChatBody chatBody, ImChannelContext imChannelContext){ //开启持久化 - if(ON.equals(imConfig.getIsStore())){ + if(ImServerConfig.Const.ON.equals(imServerConfig.getIsStore())){ //存储群聊消息; if(ChatType.CHAT_TYPE_PUBLIC.getNumber() == chatBody.getChatType()){ pushGroupMessages(PUSH,STORE, chatBody); @@ -49,13 +45,13 @@ public abstract class BaseAsyncChatMessageProcessor implements AsyncChatMessageP String to = chatBody.getTo(); String sessionId = ChatKit.sessionId(from,to); writeMessage(STORE,USER+":"+sessionId,chatBody); - boolean isOnline = ChatKit.isOnline(to,imConfig); + boolean isOnline = ChatKit.isOnline(to,imServerConfig); if(!isOnline){ writeMessage(PUSH,USER+":"+to+":"+from,chatBody); } } } - doHandler(chatBody, channelContext); + doHandler(chatBody, imChannelContext); } /** * 推送持久化群组消息 @@ -64,7 +60,7 @@ public abstract class BaseAsyncChatMessageProcessor implements AsyncChatMessageP * @param chatBody */ private void pushGroupMessages(String pushTable, String storeTable , ChatBody chatBody){ - MessageHelper messageHelper = imConfig.getMessageHelper(); + MessageHelper messageHelper = imServerConfig.getMessageHelper(); String group_id = chatBody.getGroup_id(); //先将群消息持久化到存储Timeline; writeMessage(storeTable,GROUP+":"+group_id,chatBody); @@ -72,10 +68,10 @@ public abstract class BaseAsyncChatMessageProcessor implements AsyncChatMessageP //通过写扩散模式将群消息同步到所有的群成员 for(String userId : userIds){ boolean isOnline = false; - if(ON.equals(imConfig.getIsStore()) && ON.equals(imConfig.getIsCluster())){ + if(ImServerConfig.Const.ON.equals(imServerConfig.getIsStore()) && ImServerConfig.Const.ON.equals(imServerConfig.getIsCluster())){ isOnline = messageHelper.isOnline(userId); }else{ - isOnline = ChatKit.isOnline(userId,imConfig); + isOnline = ChatKit.isOnline(userId,imServerConfig); } if(!isOnline){ writeMessage(pushTable, GROUP+":"+group_id+":"+userId, chatBody); @@ -84,7 +80,7 @@ public abstract class BaseAsyncChatMessageProcessor implements AsyncChatMessageP } private void writeMessage(String timelineTable , String timelineId , ChatBody chatBody){ - MessageHelper messageHelper = imConfig.getMessageHelper(); + MessageHelper messageHelper = imServerConfig.getMessageHelper(); messageHelper.writeMessage(timelineTable, timelineId, chatBody); } } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/ChatCmdProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/ChatCmdProcessor.java index fad9a61..3696810 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/ChatCmdProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/ChatCmdProcessor.java @@ -1,5 +1,6 @@ package org.jim.server.command.handler.processor.chat; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; import org.tio.core.ChannelContext; import org.jim.server.command.handler.processor.CmdProcessor; @@ -12,8 +13,8 @@ public interface ChatCmdProcessor extends CmdProcessor { /** * 聊天cmd业务处理器处理方法; * @param chatPacket - * @param channelContext + * @param imChannelContext * @throws Exception */ - public void handler(ImPacket chatPacket,ChannelContext channelContext); + void handler(ImPacket chatPacket, ImChannelContext imChannelContext); } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/DefaultAsyncChatMessageProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/DefaultAsyncChatMessageProcessor.java index 1701211..15cf95a 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/DefaultAsyncChatMessageProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/DefaultAsyncChatMessageProcessor.java @@ -1,7 +1,7 @@ package org.jim.server.command.handler.processor.chat; +import org.jim.common.ImChannelContext; import org.jim.common.packets.ChatBody; -import org.tio.core.ChannelContext; /** * @author WChao * @date 2018年4月3日 下午1:12:30 @@ -9,7 +9,7 @@ import org.tio.core.ChannelContext; public class DefaultAsyncChatMessageProcessor extends BaseAsyncChatMessageProcessor { @Override - public void doHandler(ChatBody chatBody, ChannelContext channelContext){ + public void doHandler(ChatBody chatBody, ImChannelContext imChannelContext){ } } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/MsgQueueRunnable.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/MsgQueueRunnable.java index 41ee4ed..b43e630 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/MsgQueueRunnable.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/chat/MsgQueueRunnable.java @@ -1,5 +1,6 @@ package org.jim.server.command.handler.processor.chat; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; import org.jim.common.ImPacket; import org.jim.common.packets.ChatBody; @@ -10,6 +11,8 @@ import org.jim.server.command.handler.ChatReqHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tio.core.ChannelContext; +import org.tio.utils.queue.FullWaitQueue; +import org.tio.utils.queue.TioFullWaitQueue; import org.tio.utils.thread.pool.AbstractQueueRunnable; import java.util.concurrent.Executor; @@ -22,38 +25,30 @@ public class MsgQueueRunnable extends AbstractQueueRunnable { private Logger log = LoggerFactory.getLogger(MsgQueueRunnable.class); - private ChannelContext channelContext = null; + private ImChannelContext imChannelContext; private AsyncChatMessageProcessor chatMessageProcessor; @Override - public boolean addMsg(ImPacket msg) { - if (this.isCanceled()) { - log.error("{}, 任务已经取消,{}添加到消息队列失败", channelContext, msg); - return false; - } - return msgQueue.add(msg); + public FullWaitQueue getMsgQueue() { + return new TioFullWaitQueue(Integer.MAX_VALUE,true); } - public MsgQueueRunnable(ChannelContext channelContext, Executor executor) { + public MsgQueueRunnable(ImChannelContext imChannelContext, Executor executor) { super(executor); - this.channelContext = channelContext; + this.imChannelContext = imChannelContext; ChatReqHandler chatReqHandler = CommandManager.getCommand(Command.COMMAND_CHAT_REQ,ChatReqHandler.class); chatMessageProcessor = chatReqHandler.getProcessor(ImConst.BASE_ASYNC_CHAT_MESSAGE_PROCESSOR,BaseAsyncChatMessageProcessor.class).get(0); } @Override public void runTask() { - int queueSize = msgQueue.size(); - if (queueSize == 0) { - return; - } ImPacket packet = null; - while ((packet = msgQueue.poll()) != null) { + while ((packet = this.getMsgQueue().poll()) != null) { if(chatMessageProcessor != null){ try { - ChatBody chatBody = ChatKit.toChatBody(packet.getBody(), channelContext); - chatMessageProcessor.handler(chatBody, channelContext); + ChatBody chatBody = ChatKit.toChatBody(packet.getBody(), imChannelContext); + chatMessageProcessor.handler(chatBody, imChannelContext); } catch (Exception e) { log.error(e.toString(),e); } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/group/GroupCmdProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/group/GroupCmdProcessor.java index 7edf2cc..2087442 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/group/GroupCmdProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/group/GroupCmdProcessor.java @@ -1,10 +1,9 @@ package org.jim.server.command.handler.processor.group; +import org.jim.common.ImChannelContext; import org.jim.common.packets.Group; import org.jim.common.packets.JoinGroupRespBody; import org.jim.server.command.handler.processor.CmdProcessor; -import org.tio.core.ChannelContext; - /** * @author ensheng */ @@ -12,8 +11,8 @@ public interface GroupCmdProcessor extends CmdProcessor { /** * 加入群组处理 * @param joinGroup - * @param channelContext + * @param imChannelContext * @return */ - JoinGroupRespBody join(Group joinGroup, ChannelContext channelContext); + JoinGroupRespBody join(Group joinGroup, ImChannelContext imChannelContext); } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/HandshakeCmdProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/HandshakeCmdProcessor.java index 0ae4061..2f649dd 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/HandshakeCmdProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/HandshakeCmdProcessor.java @@ -3,8 +3,9 @@ */ package org.jim.server.command.handler.processor.handshake; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; -import org.tio.core.ChannelContext; +import org.jim.common.exception.ImException; import org.jim.server.command.handler.processor.CmdProcessor; /** * @ClassName HandshakeCmdProcessor @@ -17,18 +18,18 @@ public interface HandshakeCmdProcessor extends CmdProcessor { /** * 对httpResponsePacket参数进行补充并返回,如果返回null表示不想和对方建立连接,框架会断开连接,如果返回非null,框架会把这个对象发送给对方 * @param packet - * @param channelContext + * @param imChannelContext * @return - * @throws Exception + * @throws ImException * @author: Wchao */ - public ImPacket handshake(ImPacket packet,ChannelContext channelContext) throws Exception; + ImPacket handshake(ImPacket packet, ImChannelContext imChannelContext) throws ImException; /** * 握手成功后 * @param packet - * @param channelContext - * @throws Exception + * @param imChannelContext + * @throws ImException * @author Wchao */ - public void onAfterHandshaked(ImPacket packet, ChannelContext channelContext) throws Exception; + void onAfterHandshake(ImPacket packet, ImChannelContext imChannelContext) throws ImException; } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/TcpHandshakeProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/TcpHandshakeProcessor.java index 5fa8c29..352418f 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/TcpHandshakeProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/TcpHandshakeProcessor.java @@ -3,14 +3,16 @@ */ package org.jim.server.command.handler.processor.handshake; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; -import org.jim.common.Protocol; -import org.tio.core.ChannelContext; +import org.jim.common.ImSessionContext; +import org.jim.common.exception.ImException; import org.jim.common.packets.Command; import org.jim.common.packets.HandshakeBody; import org.jim.common.packets.RespBody; import org.jim.common.tcp.TcpSessionContext; -import org.jim.common.utils.ImKit; +import org.jim.server.handler.ProtocolManager; + /** * 版本: [1.0] * 功能说明: @@ -19,9 +21,9 @@ import org.jim.common.utils.ImKit; public class TcpHandshakeProcessor implements HandshakeCmdProcessor { @Override - public ImPacket handshake(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handshake(ImPacket packet, ImChannelContext channelContext) throws ImException { RespBody handshakeBody = new RespBody(Command.COMMAND_HANDSHAKE_RESP,new HandshakeBody(Protocol.HANDSHAKE_BYTE)); - ImPacket handshakePacket = ImKit.ConvertRespPacket(handshakeBody,channelContext); + ImPacket handshakePacket = ProtocolManager.Converter.respPacket(handshakeBody,channelContext); return handshakePacket; } @@ -29,16 +31,16 @@ public class TcpHandshakeProcessor implements HandshakeCmdProcessor { * 握手成功后 * @param packet * @param channelContext - * @throws Exception + * @throws ImException * @author Wchao */ @Override - public void onAfterHandshaked(ImPacket packet, ChannelContext channelContext)throws Exception { + public void onAfterHandshake(ImPacket packet, ImChannelContext channelContext)throws ImException { } @Override - public boolean isProtocol(ChannelContext channelContext){ - Object sessionContext = channelContext.getAttribute(); + public boolean isProtocol(ImChannelContext channelContext){ + ImSessionContext sessionContext = channelContext.getSessionContext(); if(sessionContext == null){ return false; }else if(sessionContext instanceof TcpSessionContext){ diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/WsHandshakeProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/WsHandshakeProcessor.java index 449eb97..c76dafe 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/WsHandshakeProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/handshake/WsHandshakeProcessor.java @@ -3,9 +3,10 @@ */ package org.jim.server.command.handler.processor.handshake; +import org.jim.common.ImChannelContext; import org.jim.common.ImPacket; -import org.jim.common.Protocol; -import org.tio.core.ChannelContext; +import org.jim.common.ImSessionContext; +import org.jim.common.exception.ImException; import org.jim.common.packets.Command; import org.jim.common.ws.WsRequestPacket; import org.jim.common.ws.WsResponsePacket; @@ -20,15 +21,15 @@ public class WsHandshakeProcessor implements HandshakeCmdProcessor { /** * 对httpResponsePacket参数进行补充并返回,如果返回null表示不想和对方建立连接,框架会断开连接,如果返回非null,框架会把这个对象发送给对方 * @param packet - * @param channelContext + * @param imChannelContext * @return * @throws Exception * @author: WChao */ @Override - public ImPacket handshake(ImPacket packet, ChannelContext channelContext) throws Exception { + public ImPacket handshake(ImPacket packet, ImChannelContext imChannelContext) throws ImException { WsRequestPacket wsRequestPacket = (WsRequestPacket) packet; - WsSessionContext wsSessionContext = (WsSessionContext) channelContext.getAttribute(); + WsSessionContext wsSessionContext = (WsSessionContext) imChannelContext.getSessionContext(); if (wsRequestPacket.isHandShake()) { WsResponsePacket wsResponsePacket = new WsResponsePacket(); wsResponsePacket.setHandShake(true); @@ -42,24 +43,24 @@ public class WsHandshakeProcessor implements HandshakeCmdProcessor { /** * 握手成功后 * @param packet - * @param channelContext + * @param imChannelContext * @throws Exception * @author Wchao */ @Override - public void onAfterHandshaked(ImPacket packet, ChannelContext channelContext)throws Exception { + public void onAfterHandshake(ImPacket packet, ImChannelContext imChannelContext)throws ImException { } /** * @Author WChao * @Description 判断当前连接是否属于WS协议 - * @param [channelContext] + * @param imChannelContext * @return boolean **/ @Override - public boolean isProtocol(ChannelContext channelContext){ - Object sessionContext = channelContext.getAttribute(); + public boolean isProtocol(ImChannelContext imChannelContext){ + ImSessionContext sessionContext = imChannelContext.getSessionContext(); if(sessionContext == null){ return false; }else if(sessionContext instanceof WsSessionContext){ @@ -71,13 +72,13 @@ public class WsHandshakeProcessor implements HandshakeCmdProcessor { /** * @Author WChao * @Description 协议名称 - * @param [] + * @param * @return java.lang.String **/ @Override public String name() { - return Protocol.WEBSOCKET; + return Protocol.WEB_SOCKET; } } diff --git a/jim-server/src/main/java/org/jim/server/command/handler/processor/login/LoginCmdProcessor.java b/jim-server/src/main/java/org/jim/server/command/handler/processor/login/LoginCmdProcessor.java index 1016768..5bc8ce1 100644 --- a/jim-server/src/main/java/org/jim/server/command/handler/processor/login/LoginCmdProcessor.java +++ b/jim-server/src/main/java/org/jim/server/command/handler/processor/login/LoginCmdProcessor.java @@ -3,7 +3,7 @@ */ package org.jim.server.command.handler.processor.login; -import org.tio.core.ChannelContext; +import org.jim.common.ImChannelContext; import org.jim.common.packets.LoginReqBody; import org.jim.common.packets.LoginRespBody; import org.jim.server.command.handler.processor.CmdProcessor; @@ -15,14 +15,14 @@ public interface LoginCmdProcessor extends CmdProcessor { /** * 执行登录操作接口方法 * @param loginReqBody - * @param channelContext + * @param imChannelContext * @return */ - public LoginRespBody doLogin(LoginReqBody loginReqBody ,ChannelContext channelContext); + LoginRespBody doLogin(LoginReqBody loginReqBody , ImChannelContext imChannelContext); /** * 登录成功回调方法 - * @param channelContext + * @param imChannelContext */ - public void onSuccess(ChannelContext channelContext); + void onSuccess(ImChannelContext imChannelContext); } diff --git a/jim-server/src/main/java/org/jim/server/config/DefaultImConfigBuilder.java b/jim-server/src/main/java/org/jim/server/config/DefaultImConfigBuilder.java new file mode 100644 index 0000000..3d0d93d --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/config/DefaultImConfigBuilder.java @@ -0,0 +1,32 @@ +/** + * + */ +package org.jim.server.config; + +import org.jim.common.http.HttpConfig; +import org.jim.common.ws.WsConfig; + +/** + * @author WChao + * + */ +public class DefaultImConfigBuilder extends ImServerConfigBuilder { + + @Override + public ImServerConfigBuilder configHttp(HttpConfig httpConfig) { + // TODO Auto-generated method stub + return this; + } + + @Override + public ImServerConfigBuilder configWs(WsConfig wsServerConfig) { + // TODO Auto-generated method stub + return this; + } + + @Override + protected ImServerConfigBuilder getThis() { + return this; + } + +} diff --git a/jim-server/src/main/java/org/jim/server/config/ImServerConfig.java b/jim-server/src/main/java/org/jim/server/config/ImServerConfig.java new file mode 100644 index 0000000..ad3f066 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/config/ImServerConfig.java @@ -0,0 +1,279 @@ +package org.jim.server.config; + +import org.jim.common.ImHandler; +import org.jim.common.config.ImConfig; +import org.jim.common.cluster.ImCluster; +import org.jim.common.http.HttpConfig; +import org.jim.common.listener.ImListener; +import org.jim.common.message.MessageHelper; +import org.jim.common.ws.WsConfig; +import org.jim.server.handler.DefaultImServerHandler; +import org.jim.server.handler.ImServerHandler; +import org.jim.server.handler.ImServerHandlerAdapter; +import org.jim.server.listener.DefaultImServerListener; +import org.jim.server.listener.ImServerListener; +import org.jim.server.listener.ImServerListenerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.tio.core.ssl.SslConfig; +import org.tio.server.ServerTioConfig; + +import java.util.Objects; + +/** + * @ClassName ImServerConfig + * @Description TODO + * @Author WChao + * @Date 2020/1/4 10:40 + * @Version 1.0 + **/ +public class ImServerConfig extends ImConfig { + + private static Logger log = LoggerFactory.getLogger(ImServerConfig.class); + /** + * 服务端消息处理器 + */ + private ImServerHandler imServerHandler; + /** + * 服务端消息监听器 + */ + private ImServerListener imServerListener; + + /** + * 用户消息持久化助手; + */ + private MessageHelper messageHelper; + /** + * 是否开启持久化; + */ + private String isStore = Const.OFF; + /** + * 是否开启集群; + */ + private String isCluster = Const.OFF; + /** + * 是否开启SSL加密 + */ + private String isSSL = Const.OFF; + /** + * SSL配置 + */ + private SslConfig sslConfig; + /** + * 集群配置 + * 如果此值不为null,就表示要集群 + */ + private ImCluster cluster; + + /** + * http相关配置; + */ + private HttpConfig httpConfig; + /** + * WebSocket相关配置; + */ + private WsConfig wsConfig; + + private ImServerConfig(ImServerHandler imServerHandler, ImServerListener imServerListener){ + setImServerHandler(imServerHandler); + setImServerListener(imServerListener); + this.tioConfig = new ServerTioConfig(this.getName(), new ImServerHandlerAdapter(this.imServerHandler),new ImServerListenerAdapter(this.imServerListener)); + } + + public static Builder newBuilder(){ + return new ImServerConfig.Builder(); + } + + @Override + public ImHandler getImHandler() { + return getImServerHandler(); + } + + @Override + public ImListener getImListener() { + return getImServerListener(); + } + + public static class Builder extends ImConfig.Builder{ + + private ImServerListener imServerListener; + + private MessageHelper messageHelper; + + private String isStore = Const.OFF; + + private String isCluster = Const.OFF; + + private String isSSL = Const.OFF; + + private SslConfig sslConfig; + + private ImCluster cluster; + + private HttpConfig httpConfig; + + private WsConfig wsConfig; + + @Override + protected Builder getThis() { + return this; + } + + public Builder serverListener(ImServerListener imServerListener){ + this.imServerListener = imServerListener; + return getThis(); + } + + public Builder messageHelper(MessageHelper messageHelper){ + this.messageHelper = messageHelper; + return getThis(); + } + + public Builder isStore(String isStore){ + this.isStore = isStore; + return getThis(); + } + + public Builder isCluster(String isCluster){ + this.isCluster = isCluster; + return getThis(); + } + + public Builder isSSL(String isSSL){ + this.isSSL = isSSL; + return getThis(); + } + + public Builder sslConfig(SslConfig sslConfig){ + this.sslConfig = sslConfig; + return getThis(); + } + + public Builder cluster(ImCluster cluster){ + this.cluster = cluster; + return getThis(); + } + + public Builder httConfig(HttpConfig httpConfig){ + this.httpConfig = httpConfig; + return getThis(); + } + + public Builder wsConfig(WsConfig wsConfig){ + this.wsConfig = wsConfig; + return getThis(); + } + + @Override + public ImServerConfig build(){ + ImServerConfig imServerConfig = new ImServerConfig(new DefaultImServerHandler(), this.imServerListener); + imServerConfig.setBindIp(this.bindIp); + imServerConfig.setBindPort(this.bindPort); + imServerConfig.setReadBufferSize(this.readBufferSize); + imServerConfig.setMessageHelper(this.messageHelper); + imServerConfig.setIsStore(this.isStore); + imServerConfig.setIsCluster(this.isCluster); + imServerConfig.setIsSSL(this.isSSL); + imServerConfig.setSslConfig(this.sslConfig); + imServerConfig.setCluster(this.cluster); + imServerConfig.setHttpConfig(this.httpConfig); + imServerConfig.setWsConfig(this.wsConfig); + imServerConfig.setHeartbeatTimeout(this.heartbeatTimeout); + imServerConfig.setImGroupListener(this.imGroupListener); + imServerConfig.setImUserListener(this.imUserListener); + return imServerConfig; + } + } + + public ImServerListener getImServerListener() { + return imServerListener; + } + + public void setImServerHandler(ImServerHandler imServerHandler) { + this.imServerHandler = imServerHandler; + if(Objects.isNull(this.imServerHandler)){ + this.imServerHandler = new DefaultImServerHandler(); + } + } + + public void setImServerListener(ImServerListener imServerListener) { + this.imServerListener = imServerListener; + if(Objects.isNull(this.imServerListener)){ + this.imServerListener = new DefaultImServerListener(); + } + } + + public MessageHelper getMessageHelper() { + return messageHelper; + } + + public void setMessageHelper(MessageHelper messageHelper) { + this.messageHelper = messageHelper; + } + + public String getIsStore() { + return isStore; + } + + public void setIsStore(String isStore) { + this.isStore = isStore; + } + + public String getIsCluster() { + return isCluster; + } + + /** + * 设置是否开启集群 + * @param isCluster + */ + public void setIsCluster(String isCluster) { + this.isCluster = isCluster; + } + + public String getIsSSL() { + return isSSL; + } + + public void setIsSSL(String isSSL) { + this.isSSL = isSSL; + } + + public SslConfig getSslConfig() { + return sslConfig; + } + + public void setSslConfig(SslConfig sslConfig) { + this.sslConfig = sslConfig; + this.tioConfig.setSslConfig(sslConfig); + } + + public ImCluster getCluster() { + return cluster; + } + + public void setCluster(ImCluster cluster) { + this.cluster = cluster; + + } + + public HttpConfig getHttpConfig() { + return httpConfig; + } + + public void setHttpConfig(HttpConfig httpConfig) { + this.httpConfig = httpConfig; + } + + public WsConfig getWsConfig() { + return wsConfig; + } + + public void setWsConfig(WsConfig wsConfig) { + this.wsConfig = wsConfig; + } + + public ImServerHandler getImServerHandler() { + return imServerHandler; + } +} diff --git a/jim-server/src/main/java/org/jim/server/config/ImServerConfigBuilder.java b/jim-server/src/main/java/org/jim/server/config/ImServerConfigBuilder.java new file mode 100644 index 0000000..96fd33e --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/config/ImServerConfigBuilder.java @@ -0,0 +1,57 @@ +/** + * + */ +package org.jim.server.config; + +import org.jim.common.http.HttpConfig; +import org.jim.common.ws.WsConfig; +import org.jim.server.listener.ImServerListener; + +/** + * @author WChao + * 2018/08/26 + */ +public abstract class ImServerConfigBuilder{ + + protected T conf; + protected ImServerListener serverListener; + protected HttpConfig httpConfig; + protected WsConfig wsConfig; + + /** + * 留给子类配置Http服务器相关配置 + * @param httpConfig + * @throws Exception + * @return + */ + public abstract B configHttp(HttpConfig httpConfig)throws Exception; + + /** + * 配置WebSocket服务器相关配置 + * @param wsConfig + * @throws Exception + * @return + * + */ + public abstract B configWs(WsConfig wsConfig)throws Exception; + + /** + * 供子类获取自身builder抽象类; + * @return + */ + protected abstract B getThis(); + + public B serverListener(ImServerListener serverListener){ + this.serverListener = serverListener; + return getThis(); + } + + public T build() throws Exception{ + this.httpConfig = HttpConfig.newBuilder().build(); + this.wsConfig = WsConfig.newBuilder().build(); + this.configHttp(httpConfig); + this.configWs(wsConfig); + return conf; + } + +} diff --git a/jim-server/src/main/java/org/jim/server/config/PropertyImServerConfigBuilder.java b/jim-server/src/main/java/org/jim/server/config/PropertyImServerConfigBuilder.java new file mode 100644 index 0000000..59e64c6 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/config/PropertyImServerConfigBuilder.java @@ -0,0 +1,56 @@ +/** + * + */ +package org.jim.server.config; + +import org.jim.common.http.HttpConfig; +import org.jim.common.utils.PropUtil; +import org.jim.common.ws.WsConfig; + +/** + * @author WChao + * 2018/08/26 + */ +public class PropertyImServerConfigBuilder extends ImServerConfigBuilder { + + public PropertyImServerConfigBuilder(String file) { + PropUtil.use(file); + } + + @Override + public PropertyImServerConfigBuilder configHttp(HttpConfig httpConfig)throws Exception{ + httpConfig.setBindPort(PropUtil.getInt("jim.port")); + //设置web访问路径;html/css/js等的根目录,支持classpath:,也支持绝对路径 + httpConfig.setPageRoot(PropUtil.get("jim.http.page")); + //不缓存资源; + httpConfig.setMaxLiveTimeOfStaticRes(PropUtil.getInt("jim.http.max.live.time")); + //设置j-im mvc扫描目录; + httpConfig.setScanPackages(PropUtil.get("jim.http.scan.packages").split(",")); + return this; + } + + @Override + public PropertyImServerConfigBuilder configWs(WsConfig wsConfig)throws Exception{ + + return this; + } + + @Override + protected PropertyImServerConfigBuilder getThis() { + return this; + } + + @Override + public ImServerConfig build()throws Exception { + super.build(); + return ImServerConfig.newBuilder() + .bindIp(PropUtil.get("jim.bind.ip")) + .bindPort(PropUtil.getInt("jim.port")) + .heartbeatTimeout(PropUtil.getLong("jim.heartbeat.timeout")) + .isStore(PropUtil.get("jim.store")) + .httConfig(this.httpConfig) + .wsConfig(this.wsConfig) + .serverListener(this.serverListener) + .isCluster(PropUtil.get("jim.cluster")).build(); + } +} diff --git a/jim-server/src/main/java/org/jim/server/handler/AbstractProtocolHandler.java b/jim-server/src/main/java/org/jim/server/handler/AbstractProtocolHandler.java index 0d1d65b..ad3dedf 100644 --- a/jim-server/src/main/java/org/jim/server/handler/AbstractProtocolHandler.java +++ b/jim-server/src/main/java/org/jim/server/handler/AbstractProtocolHandler.java @@ -3,54 +3,31 @@ */ package org.jim.server.handler; -import org.jim.common.ImConfig; -import org.jim.common.protocol.IProtocol; -import org.tio.core.ChannelContext; -import org.tio.core.exception.AioDecodeException; -import org.tio.core.intf.Packet; -import org.tio.server.intf.ServerAioHandler; - -import java.nio.ByteBuffer; +import org.jim.common.exception.ImException; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.server.config.ImServerConfig; /** - * 版本: [1.0] 功能说明: 封装tioServerAioHandler,提供更丰富的方法供客户端定制化; + * 版本: [1.0] 功能说明: 抽象协议处理器; * @author : WChao 创建时间: 2017年8月3日 上午9:47:44 */ -public abstract class AbstractProtocolHandler implements ServerAioHandler{ - /** - * 获取不同协议管理器 - * @return - */ - public abstract IProtocol protocol(); +public abstract class AbstractProtocolHandler implements ImServerHandler { + + protected AbstractProtocol protocol; + + public AbstractProtocolHandler(){}; + + public AbstractProtocolHandler(AbstractProtocol protocol){ + this.protocol = protocol; + } /** * 初始化不同协议 - * @param imConfig - * @throws Exception + * @param imServerConfig + * @throws ImException */ - public abstract void init(ImConfig imConfig)throws Exception; + public abstract void init(ImServerConfig imServerConfig)throws ImException; - /** - * 将数据解码为消息Packet包 - * @param buffer - * @param channelContext - * @return - * @throws AioDecodeException - */ - public abstract Packet decode(ByteBuffer buffer, ChannelContext channelContext)throws AioDecodeException; - - /** - * t-io解码适配方法 - * @param buffer - * @param limit - * @param position - * @param readableLength - * @param channelContext - * @return - * @throws AioDecodeException - */ - @Override - public Packet decode(ByteBuffer buffer, int limit, int position,int readableLength, ChannelContext channelContext)throws AioDecodeException { - return decode(buffer,channelContext); + public AbstractProtocol getProtocol() { + return protocol; } - } diff --git a/jim-server/src/main/java/org/jim/server/handler/DefaultImServerHandler.java b/jim-server/src/main/java/org/jim/server/handler/DefaultImServerHandler.java new file mode 100644 index 0000000..0c1bb12 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/handler/DefaultImServerHandler.java @@ -0,0 +1,79 @@ +package org.jim.server.handler; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImPacket; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImDecodeException; +import org.jim.common.exception.ImException; +import org.jim.server.ImServerChannelContext; + +import java.nio.ByteBuffer; +import java.util.Objects; + +/** + * @ClassName DefaultImServerHandler + * @Description TODO + * @Author WChao + * @Date 2020/1/6 2:25 + * @Version 1.0 + **/ +public class DefaultImServerHandler implements ImServerHandler{ + /** + * 处理消息包 + * @param imPacket + * @param imChannelContext + * @throws Exception + */ + @Override + public void handler(ImPacket imPacket, ImChannelContext imChannelContext) throws ImException { + ImServerChannelContext imServerChannelContext = (ImServerChannelContext)imChannelContext; + AbstractProtocolHandler handler = imServerChannelContext.getProtocolHandler(); + if(Objects.isNull(handler)){ + return; + } + handler.handler(imPacket, imChannelContext); + } + + /** + * 编码 + * @param imPacket + * @param imConfig + * @param imChannelContext + * @return + */ + @Override + public ByteBuffer encode(ImPacket imPacket, ImConfig imConfig, ImChannelContext imChannelContext) { + ImServerChannelContext imServerChannelContext = (ImServerChannelContext)imChannelContext; + AbstractProtocolHandler handler = imServerChannelContext.getProtocolHandler(); + if(handler != null){ + return handler.encode(imPacket, imConfig, imServerChannelContext); + } + return null; + } + + /** + * 解码 + * @param buffer + * @param limit + * @param position + * @param readableLength + * @param imChannelContext + * @return + * @throws ImDecodeException + */ + @Override + public ImPacket decode(ByteBuffer buffer, int limit, int position, int readableLength, ImChannelContext imChannelContext) throws ImDecodeException { + ImServerChannelContext imServerChannelContext = (ImServerChannelContext)imChannelContext; + AbstractProtocolHandler handler; + if(Objects.isNull(imServerChannelContext.getSessionContext())){ + handler = ProtocolManager.initProtocolHandler(buffer, imServerChannelContext); + }else{ + handler = imServerChannelContext.getProtocolHandler(); + } + if(handler != null){ + return handler.decode(buffer, limit, position, readableLength, imServerChannelContext); + }else{ + throw new ImDecodeException("不支持的协议类型,无法找到对应的协议解码器!"); + } + } +} diff --git a/jim-server/src/main/java/org/jim/server/handler/IProtocolHandler.java b/jim-server/src/main/java/org/jim/server/handler/IProtocolHandler.java new file mode 100644 index 0000000..bdd7a60 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/handler/IProtocolHandler.java @@ -0,0 +1,11 @@ +package org.jim.server.handler; + +/** + * @ClassName ProtocolHandler + * @Description TODO + * @Author WChao + * @Date 2020/1/11 14:07 + * @Version 1.0 + **/ +public interface IProtocolHandler extends ImServerHandler{ +} diff --git a/jim-server/src/main/java/org/jim/server/handler/ImServerAioHandler.java b/jim-server/src/main/java/org/jim/server/handler/ImServerAioHandler.java deleted file mode 100644 index 397e7cf..0000000 --- a/jim-server/src/main/java/org/jim/server/handler/ImServerAioHandler.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.jim.server.handler; - -import java.nio.ByteBuffer; - -import org.jim.common.ImConst; -import org.jim.common.ImConfig; -import org.jim.common.ImSessionContext; -import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; -import org.tio.core.exception.AioDecodeException; -import org.tio.core.intf.Packet; -import org.jim.server.ImServerGroupContext; -import org.jim.server.command.handler.processor.chat.MsgQueueRunnable; -import org.tio.server.intf.ServerAioHandler; -/** - * - * @author WChao - * - */ -public class ImServerAioHandler implements ServerAioHandler { - - private ImConfig imConfig; - - public ImServerAioHandler(ImConfig imConfig) { - this.imConfig = imConfig; - } - /** - * @see org.tio.core.intf.AioHandler#handler(org.tio.core.intf.Packet) - * - * @param packet - * @return - * @throws Exception - * @author: Wchao - * 2016年11月18日 上午9:37:44 - * - */ - @Override - public void handler(Packet packet, ChannelContext channelContext) throws Exception { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - AbstractProtocolHandler handler = (AbstractProtocolHandler)imSessionContext.getProtocolHandler(); - if(handler != null){ - handler.handler(packet, channelContext); - } - } - - /** - * @see org.tio.core.intf.AioHandler#encode(org.tio.core.intf.Packet) - * - * @param packet - * @return - * @author: Wchao - * 2016年11月18日 上午9:37:44 - * - */ - @Override - public ByteBuffer encode(Packet packet, GroupContext groupContext, ChannelContext channelContext) { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - AbstractProtocolHandler handler = (AbstractProtocolHandler)imSessionContext.getProtocolHandler(); - if(handler != null){ - return handler.encode(packet, groupContext, channelContext); - } - return null; - } - - /** - * @see org.tio.core.intf.AioHandler#decode(java.nio.ByteBuffer) - * - * @param buffer - * @return - * @throws AioDecodeException - * @author: Wchao - * 2016年11月18日 上午9:37:44 - * - */ - @Override - public Packet decode(ByteBuffer buffer,int limit, int position, int readableLength,ChannelContext channelContext) throws AioDecodeException { - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); - AbstractProtocolHandler handler = null; - if(imSessionContext == null){ - handler = ProtocolHandlerManager.initServerHandlerToChannelContext(buffer, channelContext); - ImServerGroupContext imGroupContext = (ImServerGroupContext)imConfig.getGroupContext(); - channelContext.setAttribute(ImConst.CHAT_QUEUE,new MsgQueueRunnable(channelContext,imGroupContext.getTimExecutor())); - }else{ - handler = (AbstractProtocolHandler)imSessionContext.getProtocolHandler(); - } - if(handler != null){ - return handler.decode(buffer, channelContext); - }else{ - throw new AioDecodeException("不支持的协议类型,无法找到对应的协议解码器!"); - } - } - - public ImConfig getImConfig() { - return imConfig; - } - public void setImConfig(ImConfig imConfig) { - this.imConfig = imConfig; - } - -} diff --git a/jim-server/src/main/java/org/jim/server/handler/ImServerHandler.java b/jim-server/src/main/java/org/jim/server/handler/ImServerHandler.java new file mode 100644 index 0000000..f391c45 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/handler/ImServerHandler.java @@ -0,0 +1,11 @@ +package org.jim.server.handler; + +import org.jim.common.ImHandler; +/** + * + * @author WChao + * + */ +public interface ImServerHandler extends ImHandler { + +} diff --git a/jim-server/src/main/java/org/jim/server/handler/ImServerHandlerAdapter.java b/jim-server/src/main/java/org/jim/server/handler/ImServerHandlerAdapter.java new file mode 100644 index 0000000..51df9d9 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/handler/ImServerHandlerAdapter.java @@ -0,0 +1,53 @@ +package org.jim.server.handler; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.ImPacket; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImDecodeException; +import org.jim.server.ImServerChannelContext; +import org.tio.core.ChannelContext; +import org.tio.core.TioConfig; +import org.tio.core.exception.AioDecodeException; +import org.tio.core.intf.Packet; +import org.tio.server.intf.ServerAioHandler; + +import java.nio.ByteBuffer; + +/** + * @ClassName ImServerHandlerAdapter + * @Description TODO + * @Author WChao + * @Date 2020/1/6 2:30 + * @Version 1.0 + **/ +public class ImServerHandlerAdapter implements ServerAioHandler, ImConst{ + + private ImServerHandler imServerHandler; + + public ImServerHandlerAdapter(ImServerHandler imServerHandler){ + this.imServerHandler = imServerHandler; + } + + @Override + public Packet decode(ByteBuffer buffer, int limit, int position, int readableLength, ChannelContext channelContext) throws AioDecodeException { + ImPacket imPacket; + try { + imPacket = this.imServerHandler.decode(buffer, limit, position, readableLength, (ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY)); + }catch (ImDecodeException e) { + throw new AioDecodeException(e); + } + return imPacket; + } + + @Override + public ByteBuffer encode(Packet packet, TioConfig tioConfig, ChannelContext channelContext) { + return this.imServerHandler.encode((ImPacket)packet, ImConfig.Global.get(), (ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY)); + } + + @Override + public void handler(Packet packet, ChannelContext channelContext) throws Exception { + this.imServerHandler.handler((ImPacket)packet, (ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY)); + } + +} diff --git a/jim-server/src/main/java/org/jim/server/handler/ProtocolHandlerManager.java b/jim-server/src/main/java/org/jim/server/handler/ProtocolHandlerManager.java deleted file mode 100644 index 2d3d9be..0000000 --- a/jim-server/src/main/java/org/jim/server/handler/ProtocolHandlerManager.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * - */ -package org.jim.server.handler; - -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; - -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; -import org.jim.common.ImConfig; -import org.jim.common.ImSessionContext; -import org.jim.common.exception.ImException; -import org.jim.common.protocol.IProtocol; -import org.jim.common.utils.ImKit; -import org.tio.core.ChannelContext; -/** - * 版本: [1.0] - * 功能说明: - * @author : WChao 创建时间: 2017年8月3日 下午2:40:24 - */ -public class ProtocolHandlerManager{ - - private static Logger logger = Logger.getLogger(ProtocolHandlerManager.class); - - private static Map serverHandlers = new HashMap(); - - static{ - try { - List configurations = ProtocolHandlerConfigurationFactory.parseConfiguration(); - init(configurations); - } catch (Exception e) { - logger.error(e.toString(),e); - } - } - - private static void init(List configurations) throws Exception{ - for(ProtocolHandlerConfiguration configuration : configurations){ - Class serverHandlerClazz = (Class)Class.forName(configuration.getServerHandler()); - AbstractProtocolHandler serverHandler = serverHandlerClazz.newInstance(); - addServerHandler(serverHandler); - } - } - - public static AbstractProtocolHandler addServerHandler(AbstractProtocolHandler serverHandler)throws ImException{ - if(Objects.isNull(serverHandler)){ - throw new ImException("ProtocolHandler must not null "); - } - return serverHandlers.put(serverHandler.protocol().name(),serverHandler); - } - - public static AbstractProtocolHandler removeServerHandler(String name)throws ImException{ - if(StringUtils.isEmpty(name)){ - throw new ImException("server name must not empty"); - } - return serverHandlers.remove(name); - } - - public static AbstractProtocolHandler initServerHandlerToChannelContext(ByteBuffer buffer, ChannelContext channelContext){ - IProtocol protocol = ImKit.protocol(buffer, channelContext); - for(Entry entry : serverHandlers.entrySet()){ - AbstractProtocolHandler protocolHandler = entry.getValue(); - String protocolName = protocolHandler.protocol().name(); - try { - if(protocol != null && protocol.name().equals(protocolName)){ - ImSessionContext sessionContext = (ImSessionContext)channelContext.getAttribute(); - sessionContext.setProtocolHandler(protocolHandler); - channelContext.setAttribute(sessionContext); - return protocolHandler; - } - } catch (Throwable e) { - logger.error(e); - } - } - return null; - } - - public static T getServerHandler(String name,Class clazz){ - AbstractProtocolHandler serverHandler = serverHandlers.get(name); - if(Objects.isNull(serverHandler)) { - return null; - } - return (T)serverHandler; - } - - public static void init(ImConfig imConfig){ - for(Entry entry : serverHandlers.entrySet()){ - try { - entry.getValue().init(imConfig); - } catch (Exception e) { - logger.error(e); - } - } - } -} diff --git a/jim-server/src/main/java/org/jim/server/handler/ProtocolManager.java b/jim-server/src/main/java/org/jim/server/handler/ProtocolManager.java new file mode 100644 index 0000000..4d98c6b --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/handler/ProtocolManager.java @@ -0,0 +1,194 @@ +/** + * + */ +package org.jim.server.handler; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.Logger; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.ImPacket; +import org.jim.common.ImStatus; +import org.jim.common.exception.ImException; +import org.jim.common.packets.Command; +import org.jim.common.packets.RespBody; +import org.jim.common.protocol.IProtocolConverter; +import org.jim.common.utils.ImKit; +import org.jim.server.ImServerChannelContext; +import org.jim.server.config.ImServerConfig; +/** + * 版本: [1.0] + * 功能说明: + * @author : WChao 创建时间: 2017年8月3日 下午2:40:24 + */ +public class ProtocolManager implements ImConst{ + + private static Logger logger = Logger.getLogger(ProtocolManager.class); + + private static Map serverHandlers = new HashMap(); + + static{ + try { + List configurations = ProtocolHandlerConfigurationFactory.parseConfiguration(); + init(configurations); + } catch (Exception e) { + logger.error(e.toString(),e); + } + } + + private static void init(List configurations) throws Exception{ + for(ProtocolHandlerConfiguration configuration : configurations){ + Class serverHandlerClazz = (Class)Class.forName(configuration.getServerHandler()); + AbstractProtocolHandler serverHandler = serverHandlerClazz.newInstance(); + addServerHandler(serverHandler); + } + } + + public static AbstractProtocolHandler addServerHandler(AbstractProtocolHandler serverHandler)throws ImException{ + if(Objects.isNull(serverHandler)){ + throw new ImException("ProtocolHandler must not null "); + } + return serverHandlers.put(serverHandler.getProtocol().name(),serverHandler); + } + + public static AbstractProtocolHandler removeServerHandler(String name)throws ImException{ + if(StringUtils.isEmpty(name)){ + throw new ImException("server name must not empty"); + } + return serverHandlers.remove(name); + } + + public static AbstractProtocolHandler initProtocolHandler(ByteBuffer buffer, ImChannelContext imChannelContext){ + ImServerChannelContext imServerChannelContext = (ImServerChannelContext)imChannelContext; + for(Entry entry : serverHandlers.entrySet()){ + AbstractProtocolHandler protocolHandler = entry.getValue(); + try { + if(protocolHandler.getProtocol().isProtocol(buffer, imServerChannelContext)){ + imServerChannelContext.setProtocolHandler(protocolHandler); + return protocolHandler; + } + } catch (Throwable e) { + logger.error(e); + } + } + return null; + } + + public static T getServerHandler(String name,Class clazz){ + AbstractProtocolHandler serverHandler = serverHandlers.get(name); + if(Objects.isNull(serverHandler)) { + return null; + } + return (T)serverHandler; + } + + public static void init(){ + init((ImServerConfig)ImServerConfig.Global.get()); + } + public static void init(ImServerConfig imServerConfig){ + for(Entry entry : serverHandlers.entrySet()){ + try { + entry.getValue().init(imServerConfig); + } catch (Exception e) { + logger.error(e); + } + } + } + + public static class Converter{ + + /** + * 功能描述:[转换不同协议响应包] + * @author:WChao 创建时间: 2017年9月21日 下午3:21:54 + * @param respBody + * @param channelContext + * @return + * + */ + public static ImPacket respPacket(RespBody respBody, ImChannelContext channelContext)throws ImException { + if(Objects.isNull(respBody)) { + throw new ImException("响应包体不能为空!"); + } + return respPacket(respBody.toByte(), respBody.getCommand(), channelContext); + } + + /** + * 功能描述:[转换不同协议响应包] + * @author:WChao 创建时间: 2017年9月21日 下午3:21:54 + * @param body + * @param channelContext + * @return + * + */ + public static ImPacket respPacket(byte[] body, Command command, ImChannelContext channelContext)throws ImException{ + ImServerChannelContext serverChannelContext = (ImServerChannelContext)channelContext; + AbstractProtocolHandler protocolHandler = serverChannelContext.getProtocolHandler(); + if(Objects.isNull(protocolHandler)){ + throw new ImException("协议[ProtocolHandler]未初始化,协议包转化失败"); + } + IProtocolConverter converter = protocolHandler.getProtocol().getConverter(); + if(converter != null){ + return converter.RespPacket(body, command, channelContext); + }else { + throw new ImException("未获取到协议转化器[ProtocolConverter]"); + } + } + + public static ImPacket respPacket(ImPacket imPacket, ImChannelContext channelContext)throws ImException{ + return respPacket(imPacket, imPacket.getCommand(), channelContext); + } + + public static ImPacket respPacket(ImPacket imPacket,Command command, ImChannelContext channelContext)throws ImException{ + return respPacket(imPacket.getBody(), command, channelContext); + } + + } + + public static class Packet{ + /** + * 数据格式不正确响应包 + * @param imChannelContext + * @return imPacket + * @throws ImException + */ + public static ImPacket dataInCorrect(ImChannelContext imChannelContext) throws ImException{ + RespBody chatDataInCorrectRespPacket = new RespBody(Command.COMMAND_CHAT_RESP,ImStatus.C10002); + ImPacket respPacket = Converter.respPacket(chatDataInCorrectRespPacket, imChannelContext); + respPacket.setStatus(ImStatus.C10002); + return respPacket; + } + + /** + * 发送成功响应包 + * @param imChannelContext + * @return imPacket + * @throws ImException + */ + public static ImPacket success(ImChannelContext imChannelContext) throws ImException{ + RespBody chatDataInCorrectRespPacket = new RespBody(Command.COMMAND_CHAT_RESP, ImStatus.C10000); + ImPacket respPacket = Converter.respPacket(chatDataInCorrectRespPacket, imChannelContext); + respPacket.setStatus(ImStatus.C10000); + return respPacket; + } + + /** + * 用户不在线响应包 + * @param imChannelContext + * @return + * @throws ImException + */ + public static ImPacket offline(ImChannelContext imChannelContext) throws ImException{ + RespBody chatDataInCorrectRespPacket = new RespBody(Command.COMMAND_CHAT_RESP,ImStatus.C10001); + ImPacket respPacket = Converter.respPacket(chatDataInCorrectRespPacket, imChannelContext); + respPacket.setStatus(ImStatus.C10001); + return respPacket; + } + } +} diff --git a/jim-server/src/main/java/org/jim/server/helper/redis/RedisImBindListener.java b/jim-server/src/main/java/org/jim/server/helper/redis/RedisImBindListener.java index 0746ced..be3b97e 100644 --- a/jim-server/src/main/java/org/jim/server/helper/redis/RedisImBindListener.java +++ b/jim-server/src/main/java/org/jim/server/helper/redis/RedisImBindListener.java @@ -1,17 +1,18 @@ package org.jim.server.helper.redis; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImConfig; +import org.jim.common.ImChannelContext; +import org.jim.common.config.ImConfig; import org.jim.common.ImSessionContext; import org.jim.common.cache.redis.RedisCache; import org.jim.common.cache.redis.RedisCacheManager; +import org.jim.common.exception.ImException; import org.jim.common.listener.AbstractImBindListener; import org.jim.common.packets.Client; import org.jim.common.packets.Group; import org.jim.common.packets.User; import org.jim.common.utils.ImKit; -import org.tio.core.ChannelContext; - +import org.jim.server.config.ImServerConfig; import java.io.Serializable; import java.util.List; /** @@ -21,9 +22,9 @@ import java.util.List; */ public class RedisImBindListener extends AbstractImBindListener{ - private RedisCache groupCache = null; - private RedisCache userCache = null; - private final String SUBFIX = ":"; + private RedisCache groupCache; + private RedisCache userCache; + private final String SUFFIX = ":"; public RedisImBindListener(){ this(null); @@ -40,49 +41,48 @@ public class RedisImBindListener extends AbstractImBindListener{ RedisCacheManager.register(GROUP, Integer.MAX_VALUE, Integer.MAX_VALUE); RedisCacheManager.register(STORE, Integer.MAX_VALUE, Integer.MAX_VALUE); RedisCacheManager.register(PUSH, Integer.MAX_VALUE, Integer.MAX_VALUE); - } @Override - public void onAfterGroupBind(ChannelContext channelContext, String group) throws Exception { + public void onAfterGroupBind(ImChannelContext imChannelContext, String group) throws ImException { if(!isStore()) { return; } - initGroupUsers(group,channelContext); + initGroupUsers(group, imChannelContext); } @Override - public void onAfterGroupUnbind(ChannelContext channelContext, String group) throws Exception { + public void onAfterGroupUnbind(ImChannelContext imChannelContext, String group) throws ImException { if(!isStore()) { return; } - String userid = channelContext.getUserid(); + String userId = imChannelContext.getUserId(); //移除群组成员; - groupCache.listRemove(group+SUBFIX+USER, userid); + groupCache.listRemove(group+SUFFIX+USER, userId); //移除成员群组; - userCache.listRemove(userid+SUBFIX+GROUP, group); - RedisCacheManager.getCache(PUSH).remove(GROUP+SUBFIX+group+SUBFIX+userid); + userCache.listRemove(userId+SUFFIX+GROUP, group); + RedisCacheManager.getCache(PUSH).remove(GROUP+SUFFIX+group+SUFFIX+userId); } @Override - public void onAfterUserBind(ChannelContext channelContext, String userid) throws Exception { + public void onAfterUserBind(ImChannelContext imChannelContext, String userId) throws ImException { if(!isStore()) { return; } - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + ImSessionContext imSessionContext = imChannelContext.getSessionContext(); Client client = imSessionContext.getClient(); if(client == null) { return; } User onlineUser = client.getUser(); if(onlineUser != null){ - initUserTerminal(channelContext,onlineUser.getTerminal(),ONLINE); + initUserTerminal(imChannelContext,onlineUser.getTerminal(),ONLINE); initUserInfo(onlineUser); } } @Override - public void onAfterUserUnbind(ChannelContext channelContext, String userid) throws Exception { + public void onAfterUserUnbind(ImChannelContext imChannelContext, String userId) throws ImException { if(!isStore()) { return; } @@ -91,24 +91,24 @@ public class RedisImBindListener extends AbstractImBindListener{ /** * 初始化群组用户; * @param groupId - * @param channelContext + * @param imChannelContext */ - public void initGroupUsers(String groupId ,ChannelContext channelContext){ + public void initGroupUsers(String groupId ,ImChannelContext imChannelContext){ if(!isStore()) { return; } - String userId = channelContext.getUserid(); + String userId = imChannelContext.getUserId(); if(StringUtils.isEmpty(groupId) || StringUtils.isEmpty(userId)) { return; } - String group_user_key = groupId+SUBFIX+USER; + String group_user_key = groupId+SUFFIX+USER; List users = groupCache.listGetAll(group_user_key); if(!users.contains(userId)){ groupCache.listPushTail(group_user_key, userId); } initUserGroups(userId, groupId); - ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute(); + ImSessionContext imSessionContext = imChannelContext.getSessionContext(); Client client = imSessionContext.getClient(); if(client == null) { return; @@ -123,44 +123,44 @@ public class RedisImBindListener extends AbstractImBindListener{ } for(Group group : groups){ if(groupId.equals(group.getGroup_id())){ - groupCache.put(groupId+SUBFIX+INFO, group); + groupCache.put(groupId+SUFFIX+INFO, group); break; } } } /** * 初始化用户拥有哪些群组; - * @param userid + * @param userId * @param group */ - public void initUserGroups(String userid, String group){ + public void initUserGroups(String userId, String group){ if(!isStore()) { return; } - if(StringUtils.isEmpty(group) || StringUtils.isEmpty(userid)) { + if(StringUtils.isEmpty(group) || StringUtils.isEmpty(userId)) { return; } - List groups = userCache.listGetAll(userid+SUBFIX+GROUP); + List groups = userCache.listGetAll(userId+SUFFIX+GROUP); if(!groups.contains(group)){ - userCache.listPushTail(userid+SUBFIX+GROUP, group); + userCache.listPushTail(userId+SUFFIX+GROUP, group); } } /** * 初始化用户终端协议类型; - * @param channelContext + * @param imChannelContext * @param terminal * @param status(online、offline) */ @Override - public void initUserTerminal(ChannelContext channelContext , String terminal , String status){ + public void initUserTerminal(ImChannelContext imChannelContext , String terminal , String status){ if(!isStore()) { return; } - String userId = channelContext.getUserid(); + String userId = imChannelContext.getUserId(); if(StringUtils.isEmpty(userId) || StringUtils.isEmpty(terminal)) { return; } - userCache.put(userId+SUBFIX+TERMINAL+SUBFIX+terminal, status); + userCache.put(userId+SUFFIX+TERMINAL+SUFFIX+terminal, status); } /** * 初始化用户终端协议类型; @@ -175,10 +175,10 @@ public class RedisImBindListener extends AbstractImBindListener{ return; } User userCopy = ImKit.copyUserWithoutFriendsGroups(user); - userCache.put(userId+SUBFIX+INFO, userCopy); + userCache.put(userId+SUFFIX+INFO, userCopy); List friends = user.getFriends(); if(friends != null){ - userCache.put(userId+SUBFIX+FRIENDS, (Serializable) friends); + userCache.put(userId+SUFFIX+FRIENDS, (Serializable) friends); } } /** @@ -186,6 +186,7 @@ public class RedisImBindListener extends AbstractImBindListener{ * @return */ public boolean isStore(){ - return ON.equals(imConfig.getIsStore()); + ImServerConfig imServerConfig = (ImServerConfig)imConfig; + return ImConfig.Const.ON.equals(imServerConfig.getIsStore()); } } diff --git a/jim-server/src/main/java/org/jim/server/helper/redis/RedisMessageHelper.java b/jim-server/src/main/java/org/jim/server/helper/redis/RedisMessageHelper.java index 57b753e..e1b7c6c 100644 --- a/jim-server/src/main/java/org/jim/server/helper/redis/RedisMessageHelper.java +++ b/jim-server/src/main/java/org/jim/server/helper/redis/RedisMessageHelper.java @@ -3,7 +3,7 @@ package org.jim.server.helper.redis; import com.alibaba.fastjson.JSONObject; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.jim.common.ImConfig; +import org.jim.common.config.ImConfig; import org.jim.common.cache.redis.JedisTemplate; import org.jim.common.cache.redis.RedisCache; import org.jim.common.cache.redis.RedisCacheManager; @@ -47,9 +47,6 @@ public class RedisMessageHelper extends AbstractMessageHelper{ } public RedisMessageHelper(){ - this(null); - } - public RedisMessageHelper(ImConfig imConfig){ this.groupCache = RedisCacheManager.getCache(GROUP); this.pushCache = RedisCacheManager.getCache(PUSH); this.storeCache = RedisCacheManager.getCache(STORE); diff --git a/jim-server/src/main/java/org/jim/server/http/DefaultHttpRequestHandler.java b/jim-server/src/main/java/org/jim/server/http/DefaultHttpRequestHandler.java index 209ad91..24de490 100644 --- a/jim-server/src/main/java/org/jim/server/http/DefaultHttpRequestHandler.java +++ b/jim-server/src/main/java/org/jim/server/http/DefaultHttpRequestHandler.java @@ -10,12 +10,13 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import org.apache.commons.lang3.StringUtils; +import org.jim.common.ImConst; +import org.jim.common.exception.ImException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tio.core.ChannelContext; import org.jim.common.http.Cookie; import org.jim.common.http.HttpConfig; -import org.jim.common.http.HttpConst; import org.jim.common.http.HttpRequest; import org.jim.common.http.HttpResponse; import org.jim.common.http.HttpResponseStatus; @@ -38,16 +39,9 @@ import cn.hutool.core.util.ClassUtil; * @author WChao * */ -public class DefaultHttpRequestHandler implements IHttpRequestHandler { +public class DefaultHttpRequestHandler implements IHttpRequestHandler,ImConst.Http { private static Logger log = LoggerFactory.getLogger(DefaultHttpRequestHandler.class); - // /** - // * 静态资源的CacheName - // * key: path 譬如"/index.html" - // * value: HttpResponse - // */ - // private static final String STATIC_RES_CACHENAME = "TIO_HTTP_STATIC_RES"; - /** * 静态资源的CacheName * key: path 譬如"/index.html" @@ -55,22 +49,10 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { */ private static final String STATIC_RES_CONTENT_CACHENAME = "TIO_HTTP_STATIC_RES_CONTENT"; - /** - * @param args - * - * @author WChao - * 2016年11月18日 上午9:13:15 - * - */ - public static void main(String[] args) { - } - protected HttpConfig httpConfig; protected Routes routes = null; - // private LoadingCache loadingCache = null; - private IHttpServerListener httpServerListener; private GuavaCache staticResCache; @@ -84,7 +66,6 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { this.httpConfig = httpConfig; if (httpConfig.getMaxLiveTimeOfStaticRes() > 0) { - // GuavaCache.register(STATIC_RES_CACHENAME, (long) httpConfig.getMaxLiveTimeOfStaticRes(), null); staticResCache = GuavaCache.register(STATIC_RES_CONTENT_CACHENAME, (long) httpConfig.getMaxLiveTimeOfStaticRes(), null); } this.setHttpServerListener(httpConfig.getHttpServerListener()); @@ -102,7 +83,7 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { } /** - * 创建httpsession + * 创建httpSession * @return * @author WChao */ @@ -136,11 +117,11 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { } @Override - public HttpResponse handler(HttpRequest request, RequestLine requestLine) throws Exception { + public HttpResponse handler(HttpRequest request, RequestLine requestLine) throws ImException { HttpResponse ret = null; try { processCookieBeforeHandler(request, requestLine); - HttpSession httpSession = request.getHttpSession();//(HttpSession) channelContext.getAttribute(); + HttpSession httpSession = request.getHttpSession(); if (httpServerListener != null) { ret = httpServerListener.doBeforeHandler(request, requestLine, ret); @@ -175,7 +156,7 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { } else if (paramType.isAssignableFrom(HttpConfig.class)) { paramValues[i] = httpConfig; } else if (paramType.isAssignableFrom(ChannelContext.class)) { - paramValues[i] = request.getChannelContext(); + paramValues[i] = request.getImChannelContext(); } else { if (params != null) { if (ClassUtils.isSimpleTypeOrArray(paramType)) { @@ -188,7 +169,8 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { } } } else { - paramValues[i] = paramType.newInstance();//BeanUtil.mapToBean(params, paramType, true); + //BeanUtil.mapToBean(params, paramType, true); + paramValues[i] = paramType.newInstance(); Set> set = params.entrySet(); label2: for (Entry entry : set) { String fieldName = entry.getKey(); @@ -254,7 +236,7 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { ret = HttpResps.try304(request, lastModified); if (ret != null) { - ret.addHeader(HttpConst.ResponseHeaderKey.tio_from_cache, "true"); + ret.addHeader(ResponseHeaderKey.tio_from_cache, "true"); return ret; } @@ -281,21 +263,21 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { if (contentCache != null && request.getIsSupportGzip()) { if (ret.getBody() != null && ret.getStatus() == HttpResponseStatus.C200) { - String contentType = ret.getHeader(HttpConst.ResponseHeaderKey.Content_Type); - String contentEncoding = ret.getHeader(HttpConst.ResponseHeaderKey.Content_Encoding); - String lastModified = ret.getHeader(HttpConst.ResponseHeaderKey.Last_Modified); + String contentType = ret.getHeader(ResponseHeaderKey.Content_Type); + String contentEncoding = ret.getHeader(ResponseHeaderKey.Content_Encoding); + String lastModified = ret.getHeader(ResponseHeaderKey.Last_Modified); Map headers = new HashMap<>(); if (StringUtils.isNotBlank(contentType)) { - headers.put(HttpConst.ResponseHeaderKey.Content_Type, contentType); + headers.put(ResponseHeaderKey.Content_Type, contentType); } if (StringUtils.isNotBlank(contentEncoding)) { - headers.put(HttpConst.ResponseHeaderKey.Content_Encoding, contentEncoding); + headers.put(ResponseHeaderKey.Content_Encoding, contentEncoding); } if (StringUtils.isNotBlank(lastModified)) { - headers.put(HttpConst.ResponseHeaderKey.Last_Modified, lastModified); + headers.put(ResponseHeaderKey.Last_Modified, lastModified); } - headers.put(HttpConst.ResponseHeaderKey.tio_from_cache, "true"); + headers.put(ResponseHeaderKey.tio_from_cache, "true"); fileCache = new FileCache(headers, file.lastModified(), ret.getBody()); contentCache.put(initPath, fileCache); @@ -342,24 +324,22 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { String sessionId = null; if (cookie == null) { - String domain = request.getHeader(HttpConst.RequestHeaderKey.Host); + String domain = request.getHeader(RequestHeaderKey.Host); String name = httpConfig.getSessionCookieName(); long maxAge = httpConfig.getSessionTimeout(); - // maxAge = Integer.MAX_VALUE; //把过期时间掌握在服务器端 - - sessionId = httpSession.getId();//randomCookieValue(); + sessionId = httpSession.getId(); cookie = new Cookie(domain, name, sessionId, maxAge); httpResponse.addCookie(cookie); httpConfig.getSessionStore().put(sessionId, httpSession); - log.info("{} 创建会话Cookie, {}", request.getChannelContext(), cookie); + log.info("{} 创建会话Cookie, {}", request.getImChannelContext(), cookie); } else { sessionId = cookie.getValue(); HttpSession httpSession1 = (HttpSession) httpConfig.getSessionStore().get(sessionId); if (httpSession1 == null) {//有cookie但是超时了 sessionId = httpSession.getId(); - String domain = request.getHeader(HttpConst.RequestHeaderKey.Host); + String domain = request.getHeader(RequestHeaderKey.Host); String name = httpConfig.getSessionCookieName(); long maxAge = httpConfig.getSessionTimeout(); // maxAge = Long.MAX_VALUE; //把过期时间掌握在服务器端 @@ -381,7 +361,7 @@ public class DefaultHttpRequestHandler implements IHttpRequestHandler { String sessionId = cookie.getValue(); httpSession = (HttpSession) httpConfig.getSessionStore().get(sessionId); if (httpSession == null) { - log.info("{} session【{}】超时", request.getChannelContext(), sessionId); + log.info("{} session【{}】超时", request.getImChannelContext(), sessionId); httpSession = createSession(); } } diff --git a/jim-server/src/main/java/org/jim/server/http/HttpProtocolHandler.java b/jim-server/src/main/java/org/jim/server/http/HttpProtocolHandler.java index 0231fe0..5d1e02c 100644 --- a/jim-server/src/main/java/org/jim/server/http/HttpProtocolHandler.java +++ b/jim-server/src/main/java/org/jim/server/http/HttpProtocolHandler.java @@ -3,36 +3,34 @@ */ package org.jim.server.http; -import org.jim.common.ImConfig; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; -import org.jim.common.http.GroupContextKey; -import org.jim.common.http.HttpConfig; -import org.jim.common.http.HttpProtocol; -import org.jim.common.http.HttpRequest; -import org.jim.common.http.HttpRequestDecoder; -import org.jim.common.http.HttpResponse; -import org.jim.common.http.HttpResponseEncoder; +import org.jim.common.ImPacket; +import org.jim.common.Jim; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImDecodeException; +import org.jim.common.exception.ImException; +import org.jim.common.http.*; import org.jim.common.http.handler.IHttpRequestHandler; +import org.jim.common.protocol.AbstractProtocol; import org.jim.common.protocol.IProtocol; import org.jim.common.session.id.impl.UUIDSessionIdGenerator; import org.jim.server.ImServerStarter; +import org.jim.server.config.ImServerConfig; import org.jim.server.handler.AbstractProtocolHandler; import org.jim.server.http.mvc.Routes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.Aio; -import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; -import org.tio.core.exception.AioDecodeException; -import org.tio.core.intf.Packet; import org.tio.utils.SystemTimer; import org.tio.utils.cache.guava.GuavaCache; import java.nio.ByteBuffer; +import java.util.Objects; + /** * 版本: [1.0] * 功能说明: - * 作者: WChao 创建时间: 2017年8月3日 下午3:07:54 + * @author : WChao 创建时间: 2017年8月3日 下午3:07:54 */ public class HttpProtocolHandler extends AbstractProtocolHandler { @@ -41,27 +39,28 @@ public class HttpProtocolHandler extends AbstractProtocolHandler { private HttpConfig httpConfig; private IHttpRequestHandler httpRequestHandler; - - public HttpProtocolHandler() {} - - public HttpProtocolHandler(HttpConfig httpServerConfig){ - this.httpConfig = httpServerConfig; + + public HttpProtocolHandler(){ + this(null, new HttpProtocol(new HttpConvertPacket())); + }; + + public HttpProtocolHandler(HttpConfig httpConfig, AbstractProtocol protocol){ + super(protocol); + this.httpConfig = httpConfig; } + @Override - public void init(ImConfig imConfig)throws Exception{ + public void init(ImServerConfig imConfig)throws ImException { long start = SystemTimer.currentTimeMillis(); this.httpConfig = imConfig.getHttpConfig(); - if (httpConfig.getSessionStore() == null) { + if (Objects.isNull(httpConfig.getSessionStore())) { GuavaCache guavaCache = GuavaCache.register(httpConfig.getSessionCacheName(), null, httpConfig.getSessionTimeout()); httpConfig.setSessionStore(guavaCache); } - if (httpConfig.getPageRoot() == null) { - httpConfig.setPageRoot("page"); - } - if (httpConfig.getSessionIdGenerator() == null) { + if (Objects.isNull(httpConfig.getSessionIdGenerator())) { httpConfig.setSessionIdGenerator(UUIDSessionIdGenerator.instance); } - if(httpConfig.getScanPackages() == null){ + if(Objects.isNull(httpConfig.getScanPackages())){ //J-IM MVC需要扫描的根目录包 String[] scanPackages = new String[] { ImServerStarter.class.getPackage().getName() }; httpConfig.setScanPackages(scanPackages); @@ -74,30 +73,29 @@ public class HttpProtocolHandler extends AbstractProtocolHandler { Routes routes = new Routes(httpConfig.getScanPackages()); httpRequestHandler = new DefaultHttpRequestHandler(httpConfig, routes); httpConfig.setHttpRequestHandler(httpRequestHandler); - imConfig.getGroupContext().setAttribute(GroupContextKey.HTTP_SERVER_CONFIG, httpConfig); long end = SystemTimer.currentTimeMillis(); long iv = end - start; - log.info("J-IM Http Server初始化完毕,耗时:{}ms", iv); + log.info("J-IM Http协议初始化完毕,耗时:{}ms", iv); } @Override - public ByteBuffer encode(Packet packet, GroupContext groupContext,ChannelContext channelContext) { - HttpResponse httpResponsePacket = (HttpResponse) packet; - ByteBuffer byteBuffer = HttpResponseEncoder.encode(httpResponsePacket, groupContext, channelContext,false); + public ByteBuffer encode(ImPacket imPacket, ImConfig imConfig, ImChannelContext imChannelContext) { + HttpResponse httpResponsePacket = (HttpResponse) imPacket; + ByteBuffer byteBuffer = HttpResponseEncoder.encode(httpResponsePacket, imChannelContext,false); return byteBuffer; } @Override - public void handler(Packet packet, ChannelContext channelContext)throws Exception { - HttpRequest httpRequestPacket = (HttpRequest) packet; + public void handler(ImPacket imPacket, ImChannelContext imChannelContext)throws ImException { + HttpRequest httpRequestPacket = (HttpRequest) imPacket; HttpResponse httpResponsePacket = httpRequestHandler.handler(httpRequestPacket, httpRequestPacket.getRequestLine()); - Aio.send(channelContext, httpResponsePacket); + Jim.send(imChannelContext, httpResponsePacket); } @Override - public Packet decode(ByteBuffer buffer, ChannelContext channelContext)throws AioDecodeException { - HttpRequest request = HttpRequestDecoder.decode(buffer, channelContext,true); - channelContext.setAttribute(ImConst.HTTP_REQUEST,request); + public ImPacket decode(ByteBuffer buffer, int limit, int position, int readableLength, ImChannelContext imChannelContext)throws ImDecodeException { + HttpRequest request = HttpRequestDecoder.decode(buffer, imChannelContext,true); + imChannelContext.setAttribute(ImConst.HTTP_REQUEST,request); return request; } @@ -117,8 +115,4 @@ public class HttpProtocolHandler extends AbstractProtocolHandler { this.httpConfig = httpConfig; } - @Override - public IProtocol protocol() { - return new HttpProtocol(); - } } diff --git a/jim-server/src/main/java/org/jim/server/http/api/HttpApiController.java b/jim-server/src/main/java/org/jim/server/http/api/HttpApiController.java index 2bb4fbd..2c5fe42 100644 --- a/jim-server/src/main/java/org/jim/server/http/api/HttpApiController.java +++ b/jim-server/src/main/java/org/jim/server/http/api/HttpApiController.java @@ -3,7 +3,8 @@ */ package org.jim.server.http.api; -import org.jim.common.ImAio; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.ImStatus; import org.jim.common.http.HttpConfig; @@ -28,7 +29,7 @@ import org.tio.core.ChannelContext; public class HttpApiController { @RequestPath(value = "/message/send") - public HttpResponse chat(HttpRequest request, HttpConfig httpConfig, ChannelContext channelContext)throws Exception { + public HttpResponse chat(HttpRequest request, HttpConfig httpConfig, ImChannelContext channelContext)throws Exception { HttpResponse response = new HttpResponse(request,httpConfig); ChatReqHandler chatReqHandler = CommandManager.getCommand(Command.COMMAND_CHAT_REQ,ChatReqHandler.class); ImPacket chatPacket = chatReqHandler.handler(request, channelContext); @@ -52,7 +53,7 @@ public class HttpApiController { return HttpResps.json(request, new RespBody(ImStatus.C10020)); } String userId = params[0].toString(); - User user = ImAio.getUser(userId); + User user = null/*Jim.getUser(userId)*/; if(user != null){ return HttpResps.json(request, new RespBody(ImStatus.C10019)); }else{ @@ -68,7 +69,7 @@ public class HttpApiController { * @throws Exception */ @RequestPath(value = "user/close") - public HttpResponse close(HttpRequest request, HttpConfig httpConfig, ChannelContext channelContext)throws Exception { + public HttpResponse close(HttpRequest request, HttpConfig httpConfig, ImChannelContext channelContext)throws Exception { Object[] params = request.getParams().get("userid"); if(params == null || params.length == 0){ return HttpResps.json(request, new RespBody(ImStatus.C10020)); diff --git a/jim-server/src/main/java/org/jim/server/listener/DefaultImServerListener.java b/jim-server/src/main/java/org/jim/server/listener/DefaultImServerListener.java new file mode 100644 index 0000000..71cbbdc --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/listener/DefaultImServerListener.java @@ -0,0 +1,54 @@ +package org.jim.server.listener; + +import org.jim.common.ImChannelContext; +import org.jim.common.ImPacket; +import org.jim.common.ImStatus; +import org.jim.common.Jim; +import org.jim.common.packets.Command; +import org.jim.common.packets.RespBody; +import org.jim.server.handler.ProtocolManager; + +/** + * @ClassName DefaultImServerListener + * @Description TODO + * @Author WChao + * @Date 2020/1/4 11:15 + * @Version 1.0 + **/ +public class DefaultImServerListener implements ImServerListener { + + + @Override + public boolean onHeartbeatTimeout(ImChannelContext channelContext, Long interval, int heartbeatTimeoutCount) { + return false; + } + + @Override + public void onAfterConnected(ImChannelContext channelContext, boolean isConnected, boolean isReconnect) throws Exception { + + } + + @Override + public void onAfterDecoded(ImChannelContext channelContext, ImPacket packet, int packetSize) throws Exception { + + } + + @Override + public void onAfterReceivedBytes(ImChannelContext channelContext, int receivedBytes) throws Exception { + + } + + @Override + public void onAfterSent(ImChannelContext channelContext, ImPacket packet, boolean isSentSuccess) throws Exception { + + } + + @Override + public void onAfterHandled(ImChannelContext channelContext, ImPacket packet, long cost) throws Exception { + + } + + @Override + public void onBeforeClose(ImChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) throws Exception { + } +} diff --git a/jim-server/src/main/java/org/jim/server/listener/ImGroupListener.java b/jim-server/src/main/java/org/jim/server/listener/ImGroupListener.java deleted file mode 100644 index 3ca6e6b..0000000 --- a/jim-server/src/main/java/org/jim/server/listener/ImGroupListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.jim.server.listener; - -import org.tio.core.ChannelContext; -import org.tio.core.intf.GroupListener; -/** - * 绑定群组监听器 - * @author WChao - * 2017年5月13日 下午10:38:36 - */ -public class ImGroupListener implements GroupListener{ - - /** - * 默认构造器 - */ - public ImGroupListener() {} - - /** - * 绑定回调方法 - * @param channelContext - * @param group - * @throws Exception - */ - @Override - public void onAfterBind(ChannelContext channelContext, String group) throws Exception { - } - - /** - * 解绑回调方法 - * @param channelContext - * @param group - * @throws Exception - */ - @Override - public void onAfterUnbind(ChannelContext channelContext, String group) throws Exception { - } -} diff --git a/jim-server/src/main/java/org/jim/server/listener/ImServerListener.java b/jim-server/src/main/java/org/jim/server/listener/ImServerListener.java new file mode 100644 index 0000000..aff1654 --- /dev/null +++ b/jim-server/src/main/java/org/jim/server/listener/ImServerListener.java @@ -0,0 +1,24 @@ +package org.jim.server.listener; + +import org.jim.common.ImChannelContext; +import org.jim.common.listener.ImListener; +import org.tio.core.ChannelContext; + +/** + * @ClassName ImServerListener + * @Description TODO + * @Author WChao + * @Date 2020/1/4 9:35 + * @Version 1.0 + **/ +public interface ImServerListener extends ImListener { + /** + * + * 服务器检查到心跳超时时,会调用这个函数(一般场景,该方法只需要直接返回false即可) + * @param imChannelContext + * @param interval 已经多久没有收发消息了,单位:毫秒 + * @param heartbeatTimeoutCount 心跳超时次数,第一次超时此值是1,以此类推。此值被保存在:channelContext.stat.heartbeatTimeoutCount + * @return 返回true,那么服务器则不关闭此连接;返回false,服务器将按心跳超时关闭该连接 + */ + boolean onHeartbeatTimeout(ImChannelContext imChannelContext, Long interval, int heartbeatTimeoutCount); +} diff --git a/jim-server/src/main/java/org/jim/server/listener/ImServerAioListener.java b/jim-server/src/main/java/org/jim/server/listener/ImServerListenerAdapter.java similarity index 56% rename from jim-server/src/main/java/org/jim/server/listener/ImServerAioListener.java rename to jim-server/src/main/java/org/jim/server/listener/ImServerListenerAdapter.java index 165f13c..5e79f74 100644 --- a/jim-server/src/main/java/org/jim/server/listener/ImServerAioListener.java +++ b/jim-server/src/main/java/org/jim/server/listener/ImServerListenerAdapter.java @@ -1,35 +1,30 @@ package org.jim.server.listener; -import org.apache.log4j.Logger; +import org.jim.common.ImChannelContext; import org.jim.common.ImConst; -import org.jim.common.ImConfig; -import org.jim.common.ImSessionContext; -import org.jim.common.message.MessageHelper; -import org.jim.common.packets.Client; -import org.jim.common.packets.User; +import org.jim.common.ImPacket; +import org.jim.server.ImServerChannelContext; +import org.jim.server.command.handler.processor.chat.MsgQueueRunnable; +import org.jim.server.config.ImServerConfig; import org.tio.core.ChannelContext; import org.tio.core.intf.Packet; import org.tio.server.intf.ServerAioListener; - /** - * - * @author WChao + * + * @author WChao * */ -public class ImServerAioListener implements ServerAioListener { +public class ImServerListenerAdapter implements ServerAioListener, ImConst{ + + private ImServerListener imServerListener; - Logger logger = Logger.getLogger(ImServerAioListener.class); - - private ImConfig imConfig; - /** * @author: WChao * 2016年12月16日 下午5:52:06 * */ - public ImServerAioListener() {} - public ImServerAioListener(ImConfig imConfig) { - this.imConfig = imConfig; + public ImServerListenerAdapter(ImServerListener imServerListener) { + this.imServerListener = imServerListener == null ? new DefaultImServerListener(): imServerListener; } /** * @@ -41,8 +36,11 @@ public class ImServerAioListener implements ServerAioListener { * @author: WChao */ @Override - public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect) { - return; + public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect)throws Exception{ + ImServerChannelContext imChannelContext = new ImServerChannelContext(ImServerConfig.Global.get(),channelContext); + channelContext.set(Key.IM_CHANNEL_CONTEXT_KEY, imChannelContext); + imChannelContext.setMsgQue(new MsgQueueRunnable(imChannelContext, imChannelContext.getImConfig().getJimExecutor())); + imServerListener.onAfterConnected(imChannelContext, isConnected, isReconnect); } /** @@ -54,11 +52,12 @@ public class ImServerAioListener implements ServerAioListener { * @author WChao */ @Override - public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess) { + public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess)throws Exception{ + imServerListener.onAfterSent((ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY), (ImPacket)packet, isSentSuccess); } /** * 连接关闭前触发本方法 - * @param channelContext the channelcontext + * @param channelContext the channelContext * @param throwable the throwable 有可能为空 * @param remark the remark 有可能为空 * @param isRemove @@ -66,8 +65,9 @@ public class ImServerAioListener implements ServerAioListener { * @throws Exception */ @Override - public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) { - if (imConfig == null) { + public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove)throws Exception{ + imServerListener.onBeforeClose((ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY), throwable, remark, isRemove); + /*if (imConfig == null) { return; } MessageHelper messageHelper = imConfig.getMessageHelper(); @@ -85,7 +85,7 @@ public class ImServerAioListener implements ServerAioListener { return; } messageHelper.getBindListener().initUserTerminal(channelContext, onlineUser.getTerminal(), ImConst.OFFLINE); - } + }*/ } /** * 解码成功后触发本方法 @@ -97,7 +97,7 @@ public class ImServerAioListener implements ServerAioListener { */ @Override public void onAfterDecoded(ChannelContext channelContext, Packet packet,int packetSize) throws Exception { - + imServerListener.onAfterDecoded((ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY), (ImPacket)packet, packetSize); } /** * 接收到TCP层传过来的数据后 @@ -107,7 +107,7 @@ public class ImServerAioListener implements ServerAioListener { */ @Override public void onAfterReceivedBytes(ChannelContext channelContext,int receivedBytes) throws Exception { - + imServerListener.onAfterReceivedBytes((ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY), receivedBytes); } /** * 处理一个消息包后 @@ -118,7 +118,11 @@ public class ImServerAioListener implements ServerAioListener { */ @Override public void onAfterHandled(ChannelContext channelContext, Packet packet,long cost) throws Exception { - + imServerListener.onAfterHandled((ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY), (ImPacket)packet, cost); } + @Override + public boolean onHeartbeatTimeout(ChannelContext channelContext, Long aLong, int i) { + return imServerListener.onHeartbeatTimeout((ImChannelContext)channelContext.get(Key.IM_CHANNEL_CONTEXT_KEY), aLong, i); + } } diff --git a/jim-server/src/main/java/org/jim/server/tcp/TcpProtocolHandler.java b/jim-server/src/main/java/org/jim/server/tcp/TcpProtocolHandler.java index 9fb2813..ed0146e 100644 --- a/jim-server/src/main/java/org/jim/server/tcp/TcpProtocolHandler.java +++ b/jim-server/src/main/java/org/jim/server/tcp/TcpProtocolHandler.java @@ -4,26 +4,23 @@ package org.jim.server.tcp; import org.apache.log4j.Logger; -import org.jim.common.ImAio; -import org.jim.common.ImConfig; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.ImStatus; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImDecodeException; +import org.jim.common.exception.ImException; import org.jim.common.packets.Command; import org.jim.common.packets.RespBody; -import org.jim.common.protocol.IProtocol; -import org.jim.common.tcp.TcpPacket; -import org.jim.common.tcp.TcpProtocol; -import org.jim.common.tcp.TcpServerDecoder; -import org.jim.common.tcp.TcpServerEncoder; +import org.jim.common.protocol.AbstractProtocol; +import org.jim.common.tcp.*; import org.jim.server.command.AbstractCmdHandler; import org.jim.server.command.CommandManager; +import org.jim.server.config.ImServerConfig; import org.jim.server.handler.AbstractProtocolHandler; -import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; -import org.tio.core.exception.AioDecodeException; -import org.tio.core.intf.Packet; - import java.nio.ByteBuffer; + /** * 版本: [1.0] * 功能说明: @@ -32,40 +29,44 @@ import java.nio.ByteBuffer; public class TcpProtocolHandler extends AbstractProtocolHandler { Logger logger = Logger.getLogger(TcpProtocolHandler.class); - - @Override - public void init(ImConfig imConfig) { + + public TcpProtocolHandler(){ + this.protocol = new TcpProtocol(new TcpConvertPacket()); + } + + public TcpProtocolHandler(AbstractProtocol protocol){ + super(protocol); } @Override - public ByteBuffer encode(Packet packet, GroupContext groupContext,ChannelContext channelContext) { - TcpPacket tcpPacket = (TcpPacket)packet; - return TcpServerEncoder.encode(tcpPacket, groupContext, channelContext); + public void init(ImServerConfig imServerConfig) { + logger.info("J-IM TCP协议初始化完毕..."); + } + @Override + public ByteBuffer encode(ImPacket imPacket, ImConfig imConfig, ImChannelContext imChannelContext) { + TcpPacket tcpPacket = (TcpPacket)imPacket; + return TcpServerEncoder.encode(tcpPacket, imConfig, imChannelContext); } @Override - public void handler(Packet packet, ChannelContext channelContext)throws Exception { + public void handler(ImPacket packet, ImChannelContext imChannelContext)throws ImException { TcpPacket tcpPacket = (TcpPacket)packet; AbstractCmdHandler cmdHandler = CommandManager.getCommand(tcpPacket.getCommand()); if(cmdHandler == null){ ImPacket imPacket = new ImPacket(Command.COMMAND_UNKNOW, new RespBody(Command.COMMAND_UNKNOW,ImStatus.C10017).toByte()); - ImAio.send(channelContext, imPacket); + Jim.send(imChannelContext, imPacket); return; } - ImPacket response = cmdHandler.handler(tcpPacket, channelContext); + ImPacket response = cmdHandler.handler(tcpPacket, imChannelContext); if(response != null && tcpPacket.getSynSeq() < 1){ - ImAio.send(channelContext,response); + Jim.send(imChannelContext, response); } } @Override - public TcpPacket decode(ByteBuffer buffer, ChannelContext channelContext)throws AioDecodeException { - TcpPacket tcpPacket = TcpServerDecoder.decode(buffer, channelContext); + public TcpPacket decode(ByteBuffer buffer, int limit, int position, int readableLength, ImChannelContext imChannelContext)throws ImDecodeException { + TcpPacket tcpPacket = TcpServerDecoder.decode(buffer, imChannelContext); return tcpPacket; } - @Override - public IProtocol protocol() { - return new TcpProtocol(); - } } diff --git a/jim-server/src/main/java/org/jim/server/util/HttpResps.java b/jim-server/src/main/java/org/jim/server/util/HttpResps.java index de0ade9..ee9660e 100644 --- a/jim-server/src/main/java/org/jim/server/util/HttpResps.java +++ b/jim-server/src/main/java/org/jim/server/util/HttpResps.java @@ -8,6 +8,7 @@ import java.util.Map; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.jim.common.ImConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.jim.common.http.HttpConfig; @@ -24,7 +25,7 @@ import cn.hutool.core.io.FileUtil; * @author WChao * 2017年6月29日 下午4:17:24 */ -public class HttpResps { +public class HttpResps implements ImConst.Http { private static Logger log = LoggerFactory.getLogger(HttpResps.class); /** @@ -92,7 +93,7 @@ public class HttpResps { String filename = fileOnServer.getName(); String extension = FilenameUtils.getExtension(filename); ret = file(request, bodyBytes, extension); - ret.addHeader(HttpConst.ResponseHeaderKey.Last_Modified, lastModified.getTime() + ""); + ret.addHeader(ResponseHeaderKey.Last_Modified, lastModified.getTime() + ""); return ret; } @@ -107,7 +108,7 @@ public class HttpResps { public static HttpResponse fileWithContentType(HttpRequest request, byte[] bodyBytes, String contentType) { HttpResponse ret = new HttpResponse(request, HttpServerUtils.getHttpConfig(request)); ret.setBodyAndGzip(bodyBytes, request); - ret.addHeader(HttpConst.ResponseHeaderKey.Content_Type, contentType); + ret.addHeader(ResponseHeaderKey.Content_Type, contentType); return ret; } @@ -227,7 +228,7 @@ public class HttpResps { public static HttpResponse redirect(HttpRequest request, String path) { HttpResponse ret = new HttpResponse(request, HttpServerUtils.getHttpConfig(request)); ret.setStatus(HttpResponseStatus.C302); - ret.addHeader(HttpConst.ResponseHeaderKey.Location, path); + ret.addHeader(ResponseHeaderKey.Location, path); return ret; } @@ -261,7 +262,7 @@ public class HttpResps { log.error(e.toString(), e); } } - ret.addHeader(HttpConst.ResponseHeaderKey.Content_Type, Content_Type); + ret.addHeader(ResponseHeaderKey.Content_Type, Content_Type); return ret; } @@ -273,7 +274,8 @@ public class HttpResps { * @author WChao */ public static HttpResponse try304(HttpRequest request, long lastModifiedOnServer) { - String If_Modified_Since = request.getHeader(HttpConst.RequestHeaderKey.If_Modified_Since);//If-Modified-Since + //If-Modified-Since + String If_Modified_Since = request.getHeader(RequestHeaderKey.If_Modified_Since); if (StringUtils.isNoneBlank(If_Modified_Since)) { Long If_Modified_Since_Date = null; try { @@ -285,7 +287,7 @@ public class HttpResps { return ret; } } catch (NumberFormatException e) { - log.warn("{}, {}不是整数,浏览器信息:{}", request.getRemote(), If_Modified_Since, request.getHeader(HttpConst.RequestHeaderKey.User_Agent)); + log.warn("{}, {}不是整数,浏览器信息:{}", request.getRemote(), If_Modified_Since, request.getHeader(RequestHeaderKey.User_Agent)); return null; } } diff --git a/jim-server/src/main/java/org/jim/server/util/HttpServerUtils.java b/jim-server/src/main/java/org/jim/server/util/HttpServerUtils.java index 5c5850f..f4b8ceb 100644 --- a/jim-server/src/main/java/org/jim/server/util/HttpServerUtils.java +++ b/jim-server/src/main/java/org/jim/server/util/HttpServerUtils.java @@ -1,7 +1,8 @@ package org.jim.server.util; +import org.jim.common.ImChannelContext; +import org.jim.common.ImSessionContext; +import org.jim.server.config.ImServerConfig; import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; -import org.jim.common.http.GroupContextKey; import org.jim.common.http.HttpConfig; import org.jim.common.http.HttpRequest; /** @@ -16,10 +17,8 @@ public class HttpServerUtils { * @author WChao */ public static HttpConfig getHttpConfig(HttpRequest request) { - ChannelContext channelContext = request.getChannelContext(); - GroupContext groupContext = channelContext.getGroupContext(); - HttpConfig httpConfig = (HttpConfig) groupContext.getAttribute(GroupContextKey.HTTP_SERVER_CONFIG); - return httpConfig; + ImServerConfig imServerConfig = (ImServerConfig)request.getImChannelContext().getImConfig(); + return imServerConfig.getHttpConfig(); } /** diff --git a/jim-server/src/main/java/org/jim/server/ws/WsMsgHandler.java b/jim-server/src/main/java/org/jim/server/ws/WsMsgHandler.java index 0195cba..feb52fc 100644 --- a/jim-server/src/main/java/org/jim/server/ws/WsMsgHandler.java +++ b/jim-server/src/main/java/org/jim/server/ws/WsMsgHandler.java @@ -1,6 +1,8 @@ package org.jim.server.ws; -import org.jim.common.ImAio; +import org.jim.common.ImChannelContext; +import org.jim.common.ImConst; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.http.HttpConst; import org.jim.common.packets.ChatBody; @@ -9,11 +11,12 @@ import org.jim.common.ws.IWsMsgHandler; import org.jim.common.ws.Opcode; import org.jim.common.ws.WsRequestPacket; import org.jim.common.ws.WsResponsePacket; -import org.jim.common.ws.WsServerConfig; +import org.jim.common.ws.WsConfig; +import org.jim.server.handler.ProtocolManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.Aio; import org.tio.core.ChannelContext; +import org.tio.core.Tio; import java.nio.ByteBuffer; /** @@ -23,40 +26,40 @@ import java.nio.ByteBuffer; public class WsMsgHandler implements IWsMsgHandler{ private static Logger log = LoggerFactory.getLogger(WsMsgHandler.class); - private WsServerConfig wsServerConfig = null; + private WsConfig wsServerConfig = null; /** * * @param text - * @param channelContext + * @param imChannelContext * @return 可以是WsResponsePacket、String、null * @author: WChao */ @Override - public Object onText(WsRequestPacket wsRequestPacket, String text, ChannelContext channelContext) throws Exception { - ChatBody chatBody = ChatKit.toChatBody(wsRequestPacket.getBody(), channelContext); + public Object onText(WsRequestPacket wsRequestPacket, String text, ImChannelContext imChannelContext) throws Exception { + ChatBody chatBody = ChatKit.toChatBody(wsRequestPacket.getBody(), imChannelContext); String toId = chatBody.getTo(); - if(ChatKit.isOnline(toId,wsServerConfig)){ - ImAio.sendToUser(toId, wsRequestPacket); - ImPacket sendSuccessPacket = ChatKit.sendSuccessRespPacket(channelContext); - text = new String(sendSuccessPacket.getBody(),HttpConst.CHARSET_NAME); + if(ChatKit.isOnline(toId,null)){ + Jim.sendToUser(toId, wsRequestPacket); + ImPacket sendSuccessPacket = ProtocolManager.Packet.success(imChannelContext); + text = new String(sendSuccessPacket.getBody(), ImConst.Http.CHARSET_NAME); }else{ - ImPacket offlineRespPacket = ChatKit.offlineRespPacket(channelContext); - text = new String(offlineRespPacket.getBody(),HttpConst.CHARSET_NAME); + ImPacket offlineRespPacket = ProtocolManager.Packet.offline(imChannelContext); + text = new String(offlineRespPacket.getBody(), ImConst.Http.CHARSET_NAME); } return text; } /** * - * @param websocketPacket + * @param webSocketPacket * @param bytes - * @param channelContext + * @param imChannelContext * @return 可以是WsResponsePacket、byte[]、ByteBuffer、null * @author: WChao */ @Override - public Object onBytes(WsRequestPacket websocketPacket, byte[] bytes, ChannelContext channelContext) throws Exception { + public Object onBytes(WsRequestPacket webSocketPacket, byte[] bytes, ImChannelContext imChannelContext) throws Exception { String text = new String(bytes, "utf-8"); log.info("收到byte消息:{},{}", bytes, text); ByteBuffer buffer = ByteBuffer.allocate(bytes.length); @@ -65,54 +68,54 @@ public class WsMsgHandler implements IWsMsgHandler{ } /** - * @param channelContext + * @param imChannelContext * @return * @throws Exception * @author: WChao */ @Override - public WsResponsePacket handler(ImPacket imPacket, ChannelContext channelContext)throws Exception { + public WsResponsePacket handler(ImPacket imPacket, ImChannelContext imChannelContext)throws Exception { WsRequestPacket wsRequest = (WsRequestPacket)imPacket; - return h(wsRequest, wsRequest.getBody(), wsRequest.getWsOpcode(), channelContext); + return h(wsRequest, wsRequest.getBody(), wsRequest.getWsOpcode(), imChannelContext); } - public WsResponsePacket h(WsRequestPacket wsRequest, byte[] bytes, Opcode opcode, ChannelContext channelContext) throws Exception { + public WsResponsePacket h(WsRequestPacket wsRequest, byte[] bytes, Opcode opcode, ImChannelContext imChannelContext) throws Exception { WsResponsePacket wsResponse = null; if (opcode == Opcode.TEXT) { if (bytes == null || bytes.length == 0) { - Aio.remove(channelContext, "错误的websocket包,body为空"); + Jim.remove(imChannelContext, "错误的webSocket包,body为空"); return null; } String text = new String(bytes, wsServerConfig.getCharset()); - Object retObj = this.onText(wsRequest, text, channelContext); + Object retObj = this.onText(wsRequest, text, imChannelContext); String methodName = "onText"; - wsResponse = processRetObj(retObj, methodName, channelContext); + wsResponse = processRetObj(retObj, methodName, imChannelContext); return wsResponse; } else if (opcode == Opcode.BINARY) { if (bytes == null || bytes.length == 0) { - Aio.remove(channelContext, "错误的websocket包,body为空"); + Jim.remove(imChannelContext, "错误的webSocket包,body为空"); return null; } - Object retObj = this.onBytes(wsRequest, bytes, channelContext); + Object retObj = this.onBytes(wsRequest, bytes, imChannelContext); String methodName = "onBytes"; - wsResponse = processRetObj(retObj, methodName, channelContext); + wsResponse = processRetObj(retObj, methodName, imChannelContext); return wsResponse; } else if (opcode == Opcode.PING || opcode == Opcode.PONG) { log.error("收到" + opcode); return null; } else if (opcode == Opcode.CLOSE) { - Object retObj = this.onClose(wsRequest, bytes, channelContext); + Object retObj = this.onClose(wsRequest, bytes, imChannelContext); String methodName = "onClose"; - wsResponse = processRetObj(retObj, methodName, channelContext); + wsResponse = processRetObj(retObj, methodName, imChannelContext); return wsResponse; } else { - Aio.remove(channelContext, "错误的websocket包,错误的Opcode"); + Jim.remove(imChannelContext, "错误的webSocket包,错误的Opcode"); return null; } } - private WsResponsePacket processRetObj(Object obj, String methodName, ChannelContext channelContext) throws Exception { - WsResponsePacket wsResponse = null; + private WsResponsePacket processRetObj(Object obj, String methodName, ImChannelContext imChannelContext) throws Exception { + WsResponsePacket wsResponse; if (obj == null) { return null; } else { @@ -136,15 +139,15 @@ public class WsMsgHandler implements IWsMsgHandler{ wsResponse.setWsOpcode(Opcode.BINARY); return wsResponse; } else { - log.error("{} {}.{}()方法,只允许返回byte[]、ByteBuffer、WebSocketResponsePacket或null,但是程序返回了{}", channelContext, this.getClass().getName(), methodName, obj.getClass().getName()); + log.error("{} {}.{}()方法,只允许返回byte[]、ByteBuffer、WebSocketResponsePacket或null,但是程序返回了{}", imChannelContext, this.getClass().getName(), methodName, obj.getClass().getName()); return null; } } } @Override - public Object onClose(WsRequestPacket websocketPacket, byte[] bytes, ChannelContext channelContext) throws Exception { - Aio.remove(channelContext, "receive close flag"); + public Object onClose(WsRequestPacket webSocketPacket, byte[] bytes, ImChannelContext imChannelContext) throws Exception { + Jim.remove(imChannelContext, "receive close flag"); return null; } @@ -152,25 +155,25 @@ public class WsMsgHandler implements IWsMsgHandler{ * * @author: WChao */ - public WsMsgHandler(WsServerConfig wsServerConfig, String[] scanPackages) { + public WsMsgHandler(WsConfig wsServerConfig, String[] scanPackages) { this.setWsServerConfig(wsServerConfig); //this.routes = new Routes(scanPackages); } public WsMsgHandler() { - this(new WsServerConfig(0), null); + this(WsConfig.newBuilder().build(), null); } /** * @return the wsServerConfig */ - public WsServerConfig getWsServerConfig() { + public WsConfig getWsServerConfig() { return wsServerConfig; } /** * @param wsServerConfig the wsServerConfig to set */ - public void setWsServerConfig(WsServerConfig wsServerConfig) { + public void setWsServerConfig(WsConfig wsServerConfig) { this.wsServerConfig = wsServerConfig; } diff --git a/jim-server/src/main/java/org/jim/server/ws/WsProtocolHandler.java b/jim-server/src/main/java/org/jim/server/ws/WsProtocolHandler.java index 80be588..6590b5b 100644 --- a/jim-server/src/main/java/org/jim/server/ws/WsProtocolHandler.java +++ b/jim-server/src/main/java/org/jim/server/ws/WsProtocolHandler.java @@ -3,10 +3,13 @@ */ package org.jim.server.ws; -import org.jim.common.ImAio; -import org.jim.common.ImConfig; +import org.jim.common.ImChannelContext; +import org.jim.common.Jim; import org.jim.common.ImPacket; import org.jim.common.ImStatus; +import org.jim.common.config.ImConfig; +import org.jim.common.exception.ImDecodeException; +import org.jim.common.exception.ImException; import org.jim.common.http.HttpRequest; import org.jim.common.http.HttpRequestDecoder; import org.jim.common.http.HttpResponse; @@ -14,108 +17,101 @@ import org.jim.common.http.HttpResponseEncoder; import org.jim.common.packets.Command; import org.jim.common.packets.Message; import org.jim.common.packets.RespBody; -import org.jim.common.protocol.IProtocol; +import org.jim.common.protocol.AbstractProtocol; import org.jim.common.utils.JsonKit; -import org.jim.common.ws.IWsMsgHandler; -import org.jim.common.ws.Opcode; -import org.jim.common.ws.WsProtocol; -import org.jim.common.ws.WsRequestPacket; -import org.jim.common.ws.WsResponsePacket; -import org.jim.common.ws.WsServerConfig; -import org.jim.common.ws.WsServerDecoder; -import org.jim.common.ws.WsServerEncoder; -import org.jim.common.ws.WsSessionContext; +import org.jim.common.ws.*; import org.jim.server.command.AbstractCmdHandler; import org.jim.server.command.CommandManager; +import org.jim.server.config.ImServerConfig; import org.jim.server.handler.AbstractProtocolHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.tio.core.ChannelContext; -import org.tio.core.GroupContext; -import org.tio.core.exception.AioDecodeException; -import org.tio.core.intf.Packet; import java.nio.ByteBuffer; +import java.util.Objects; + /** * 版本: [1.0] * 功能说明: - * 作者: WChao 创建时间: 2017年8月3日 下午6:38:36 + * @author : WChao 创建时间: 2017年8月3日 下午6:38:36 */ public class WsProtocolHandler extends AbstractProtocolHandler { private Logger logger = LoggerFactory.getLogger(WsProtocolHandler.class); - private WsServerConfig wsServerConfig; + private WsConfig wsServerConfig; private IWsMsgHandler wsMsgHandler; - public WsProtocolHandler() {} + public WsProtocolHandler() { + this.protocol = new WsProtocol(new WsConvertPacket()); + } - public WsProtocolHandler(WsServerConfig wsServerConfig, IWsMsgHandler wsMsgHandler) { + public WsProtocolHandler(WsConfig wsServerConfig, AbstractProtocol protocol) { + super(protocol); this.wsServerConfig = wsServerConfig; - this.wsMsgHandler = wsMsgHandler; } @Override - public void init(ImConfig imConfig) { - WsServerConfig wsServerConfig = imConfig.getWsServerConfig(); - if(wsServerConfig == null){ - wsServerConfig = new WsServerConfig(); - imConfig.setWsServerConfig(wsServerConfig); + public void init(ImServerConfig imServerConfig) { + WsConfig wsConfig = imServerConfig.getWsConfig(); + if(Objects.isNull(wsConfig)){ + wsConfig = WsConfig.newBuilder().build(); + imServerConfig.setWsConfig(wsConfig); } - IWsMsgHandler wsMsgHandler = wsServerConfig.getWsMsgHandler(); - if(wsMsgHandler == null){ - wsServerConfig.setWsMsgHandler(new WsMsgHandler()); + IWsMsgHandler wsMsgHandler = wsConfig.getWsMsgHandler(); + if(Objects.isNull(wsMsgHandler)){ + wsConfig.setWsMsgHandler(new WsMsgHandler()); } - this.wsServerConfig = wsServerConfig; + this.wsServerConfig = wsConfig; this.wsMsgHandler = wsServerConfig.getWsMsgHandler(); - logger.info("wsServerHandler 初始化完毕..."); + logger.info("J-IM WebSocket协议初始化完毕..."); } @Override - public ByteBuffer encode(Packet packet, GroupContext groupContext, ChannelContext channelContext) { - WsSessionContext wsSessionContext = (WsSessionContext)channelContext.getAttribute(); - WsResponsePacket wsResponsePacket = (WsResponsePacket)packet; + public ByteBuffer encode(ImPacket imPacket, ImConfig imConfig, ImChannelContext imChannelContext) { + WsSessionContext wsSessionContext = (WsSessionContext)imChannelContext.getSessionContext(); + WsResponsePacket wsResponsePacket = (WsResponsePacket)imPacket; if (wsResponsePacket.getCommand() == Command.COMMAND_HANDSHAKE_RESP) { //握手包 HttpResponse handshakeResponsePacket = wsSessionContext.getHandshakeResponsePacket(); - return HttpResponseEncoder.encode(handshakeResponsePacket, groupContext, channelContext,true); + return HttpResponseEncoder.encode(handshakeResponsePacket, imChannelContext,true); }else{ - return WsServerEncoder.encode(wsResponsePacket , groupContext, channelContext); + return WsServerEncoder.encode(wsResponsePacket , imChannelContext); } } @Override - public void handler(Packet packet, ChannelContext channelContext) throws Exception { - WsRequestPacket wsRequestPacket = (WsRequestPacket) packet; + public void handler(ImPacket imPacket, ImChannelContext imChannelContext) throws ImException { + WsRequestPacket wsRequestPacket = (WsRequestPacket) imPacket; AbstractCmdHandler cmdHandler = CommandManager.getCommand(wsRequestPacket.getCommand()); if(cmdHandler == null){ //是否ws分片发包尾帧包 if(!wsRequestPacket.isWsEof()) { return; } - ImPacket imPacket = new ImPacket(Command.COMMAND_UNKNOW, new RespBody(Command.COMMAND_UNKNOW,ImStatus.C10017).toByte()); - ImAio.send(channelContext, imPacket); + ImPacket wsPacket = new ImPacket(Command.COMMAND_UNKNOW, new RespBody(Command.COMMAND_UNKNOW,ImStatus.C10017).toByte()); + Jim.send(imChannelContext, wsPacket); return; } - ImPacket response = cmdHandler.handler(wsRequestPacket, channelContext); + ImPacket response = cmdHandler.handler(wsRequestPacket, imChannelContext); if(response != null){ - ImAio.send(channelContext, response); + Jim.send(imChannelContext, response); } } @Override - public ImPacket decode(ByteBuffer buffer, ChannelContext channelContext) throws AioDecodeException { - WsSessionContext wsSessionContext = (WsSessionContext)channelContext.getAttribute(); + public ImPacket decode(ByteBuffer buffer, int limit, int position, int readableLength, ImChannelContext imChannelContext) throws ImDecodeException { + WsSessionContext wsSessionContext = (WsSessionContext)imChannelContext.getSessionContext(); //握手 if(!wsSessionContext.isHandshaked()){ - HttpRequest httpRequest = HttpRequestDecoder.decode(buffer,channelContext,true); + HttpRequest httpRequest = HttpRequestDecoder.decode(buffer,imChannelContext,true); if(httpRequest == null) { return null; } //升级到WebSocket协议处理 - HttpResponse httpResponse = WsServerDecoder.updateWebSocketProtocol(httpRequest,channelContext); + HttpResponse httpResponse = WsServerDecoder.updateWebSocketProtocol(httpRequest, imChannelContext); if (httpResponse == null) { - throw new AioDecodeException("http协议升级到websocket协议失败"); + throw new ImDecodeException("http协议升级到webSocket协议失败"); } wsSessionContext.setHandshakeRequestPacket(httpRequest); wsSessionContext.setHandshakeResponsePacket(httpResponse); @@ -125,7 +121,7 @@ public class WsProtocolHandler extends AbstractProtocolHandler { wsRequestPacket.setCommand(Command.COMMAND_HANDSHAKE_REQ); return wsRequestPacket; }else{ - WsRequestPacket wsRequestPacket = WsServerDecoder.decode(buffer, channelContext); + WsRequestPacket wsRequestPacket = WsServerDecoder.decode(buffer, imChannelContext); if(wsRequestPacket == null) { return null; } @@ -144,11 +140,11 @@ public class WsProtocolHandler extends AbstractProtocolHandler { return wsRequestPacket; } } - public WsServerConfig getWsServerConfig() { + public WsConfig getWsServerConfig() { return wsServerConfig; } - public void setWsServerConfig(WsServerConfig wsServerConfig) { + public void setWsServerConfig(WsConfig wsServerConfig) { this.wsServerConfig = wsServerConfig; } @@ -160,8 +156,4 @@ public class WsProtocolHandler extends AbstractProtocolHandler { this.wsMsgHandler = wsMsgHandler; } - @Override - public IProtocol protocol() { - return new WsProtocol(); - } }