mirror of
https://gitee.com/xchao/j-im.git
synced 2024-12-02 11:57:43 +08:00
3.0版本大重构中
This commit is contained in:
parent
9da70fa0f8
commit
cf6437fe4f
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.j-im</groupId>
|
||||
<artifactId>jim-parent</artifactId>
|
||||
<version>2.6.0.v20190114-RELEASE</version>
|
||||
<version>3.0.0.v20200101-RELEASE</version>
|
||||
<relativePath>../jim-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
25
jim-client/src/main/java/org/jim/client/ImClientConfig.java
Normal file
25
jim-client/src/main/java/org/jim/client/ImClientConfig.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.j-im</groupId>
|
||||
<artifactId>jim-parent</artifactId>
|
||||
<version>2.6.0.v20190114-RELEASE</version>
|
||||
<version>3.0.0.v20200101-RELEASE</version>
|
||||
<relativePath>../jim-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
@ -76,6 +76,18 @@
|
||||
<groupId>net.oschina.j2cache</groupId>
|
||||
<artifactId>j2cache-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -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<ChannelContext> userChannelContexts = ImAio.getChannelContextsByUserId(userId);
|
||||
if(Objects.isNull(userChannelContexts)) {
|
||||
return null;
|
||||
}
|
||||
ReadLock readLock = userChannelContexts.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> 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<ChannelContext> getChannelContextsByUserId(String userId){
|
||||
SetWithLock<ChannelContext> channelContexts = Aio.getChannelContextsByUserid(imConfig.getGroupContext(), userId);
|
||||
return channelContexts;
|
||||
}
|
||||
/**
|
||||
* 功能描述:[获取所有用户(在线+离线)]
|
||||
* @author:WChao 创建时间: 2017年9月18日 下午4:31:54
|
||||
* @return
|
||||
*/
|
||||
public static List<User> getAllUser(){
|
||||
List<User> users = new ArrayList<User>();
|
||||
SetWithLock<ChannelContext> allChannels = Aio.getAllChannelContexts(imConfig.getGroupContext());
|
||||
if(allChannels == null) {
|
||||
return users;
|
||||
}
|
||||
ReadLock readLock = allChannels.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> 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<User> getAllOnlineUser(){
|
||||
List<User> users = new ArrayList<User>();
|
||||
SetWithLock<ChannelContext> onlineChannels = Aio.getAllConnectedsChannelContexts(imConfig.getGroupContext());
|
||||
if(onlineChannels == null) {
|
||||
return users;
|
||||
}
|
||||
ReadLock readLock = onlineChannels.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> 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<User> getAllUserByGroup(String group){
|
||||
SetWithLock<ChannelContext> withLockChannels = Aio.getChannelContextsByGroup(imConfig.getGroupContext(), group);
|
||||
if(withLockChannels == null){
|
||||
return null;
|
||||
}
|
||||
ReadLock readLock = withLockChannels.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> channels = withLockChannels.getObj();
|
||||
if(CollectionUtils.isEmpty(channels)){
|
||||
return null;
|
||||
}
|
||||
List<User> users = new ArrayList<User>();
|
||||
Map<String,User> userMaps = new HashMap<String,User>();
|
||||
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<ChannelContext> 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<ChannelContext> 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<ChannelContext> 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<ChannelContext> 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<ChannelContext> 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<ChannelContext> setWithLock, ImPacket packet, ChannelContextFilter channelContextFilter, boolean isBlock){
|
||||
Lock lock = setWithLock.getLock().readLock();
|
||||
lock.lock();
|
||||
try {
|
||||
Set<ChannelContext> sets = (Set<ChannelContext>) setWithLock.getObj();
|
||||
for (ChannelContext channelContext : sets) {
|
||||
SetWithLock<ChannelContext> convertSet = new SetWithLock<ChannelContext>(new HashSet<ChannelContext>());
|
||||
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<ChannelContext> userChannelContexts = ImAio.getChannelContextsByUserId(userId);
|
||||
if(userChannelContexts == null || userChannelContexts.size() == 0) {
|
||||
return;
|
||||
}
|
||||
ReadLock readLock = userChannelContexts.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> 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<ChannelContext> userChannelContexts = ImAio.getChannelContextsByUserId(userId);
|
||||
if(userChannelContexts == null || userChannelContexts.size() == 0) {
|
||||
return;
|
||||
}
|
||||
ReadLock readLock = userChannelContexts.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> 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<ChannelContext> userChannelContexts = getChannelContextsByUserId(userId);
|
||||
if(userChannelContexts != null && userChannelContexts.size() > 0){
|
||||
ReadLock readLock = userChannelContexts.getLock().readLock();
|
||||
readLock.lock();
|
||||
try{
|
||||
Set<ChannelContext> 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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
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 CHARSET = "utf-8";
|
||||
interface Topic{
|
||||
String REDIS_CLUSTER_TOPIC_SUFFIX = "REDIS_";
|
||||
String JIM_CLUSTER_TOPIC = "JIM_CLUSTER";
|
||||
}
|
||||
|
||||
public static final String TO = "to";
|
||||
interface Protocol{
|
||||
/**
|
||||
* 心跳字节
|
||||
*/
|
||||
byte HEARTBEAT_BYTE = -128;
|
||||
|
||||
public static final String CHANNEL = "channel";
|
||||
/**
|
||||
* 握手字节
|
||||
*/
|
||||
byte HANDSHAKE_BYTE = -127;
|
||||
|
||||
public static final String PACKET = "packet";
|
||||
/**
|
||||
* 协议版本号
|
||||
*/
|
||||
byte VERSION = 0x01;
|
||||
|
||||
public static final String STATUS = "status";
|
||||
String WEB_SOCKET = "ws";
|
||||
|
||||
public static final String HTTP_REQUEST = "httpRequest";
|
||||
String HTTP = "http";
|
||||
|
||||
public static final String CHAT_QUEUE = "chat_queue";
|
||||
String TCP = "tcp";
|
||||
|
||||
public static final String STORE = "store";
|
||||
String COOKIE_NAME_FOR_SESSION = "jim-s";
|
||||
/**
|
||||
* 消息体最多为多少,只支持多少M数据
|
||||
*/
|
||||
int MAX_LENGTH_OF_BODY = (int) (1024 * 1024 * 2.1);
|
||||
|
||||
public static final String PUSH = "push";
|
||||
/**
|
||||
* 消息头最少为多少个字节,1+1+2+(2+4)
|
||||
*/
|
||||
int LEAST_HEADER_LENGTH = 4;
|
||||
|
||||
public static final String CHAT = "chat";
|
||||
/**
|
||||
* 加密标识位mask,1为加密,否则不加密
|
||||
*/
|
||||
byte FIRST_BYTE_MASK_ENCRYPT = -128;
|
||||
|
||||
public static final String GROUP = "group";
|
||||
/**
|
||||
* 压缩标识位mask,1为压缩,否则不压缩
|
||||
*/
|
||||
byte FIRST_BYTE_MASK_COMPRESS = 0B01000000;
|
||||
|
||||
public static final String USER = "user";
|
||||
/**
|
||||
* 是否有同步序列号标识位mask,如果有同步序列号,则消息头会带有同步序列号,否则不带
|
||||
*/
|
||||
byte FIRST_BYTE_MASK_HAS_SYNSEQ = 0B00100000;
|
||||
|
||||
public static final String TERMINAL = "terminal";
|
||||
/**
|
||||
* 是否是用4字节来表示消息体的长度
|
||||
*/
|
||||
byte FIRST_BYTE_MASK_4_BYTE_LENGTH = 0B00010000;
|
||||
|
||||
public static final String INFO = "info";
|
||||
/**
|
||||
* 版本号mask
|
||||
*/
|
||||
byte FIRST_BYTE_MASK_VERSION = 0B00001111;
|
||||
}
|
||||
|
||||
public static final String FRIENDS = "friends";
|
||||
interface Http{
|
||||
/**
|
||||
* 请求体的格式
|
||||
* @author wchao
|
||||
* 2017年6月28日 上午10:03:12
|
||||
*/
|
||||
enum RequestBodyFormat {
|
||||
URLENCODED, MULTIPART, TEXT
|
||||
}
|
||||
|
||||
public static final String ONLINE = "online";
|
||||
/**
|
||||
*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
|
||||
}
|
||||
|
||||
public static final String OFFLINE = "offline";
|
||||
/**
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
|
||||
public static final String ON = "on";
|
||||
//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();
|
||||
}
|
||||
}
|
||||
|
||||
public static final String OFF = "off";
|
||||
interface ResponseHeaderKey {
|
||||
String Set_Cookie = "Set-Cookie".toLowerCase(); //Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
|
||||
String Content_Length = "Content-Length".toLowerCase(); //65
|
||||
|
||||
public static final String JIM = "JIM";
|
||||
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();
|
||||
|
||||
public static final String CONVERTER = "converter";
|
||||
/**
|
||||
* 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头更加方便。
|
||||
|
||||
public static final String BASE_ASYNC_CHAT_MESSAGE_PROCESSOR = "base_async_chat_message_processor";
|
||||
注意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";
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
47
jim-common/src/main/java/org/jim/common/ImHandler.java
Normal file
47
jim-common/src/main/java/org/jim/common/ImHandler.java
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
/**
|
||||
@ -24,6 +25,8 @@ public class ImPacket extends Packet
|
||||
*/
|
||||
private Command command;
|
||||
|
||||
protected ImChannelContext imChannelContext;
|
||||
|
||||
public ImPacket(){}
|
||||
|
||||
public ImPacket(byte[] body){
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
/**
|
||||
* 通道所属协议处理器;
|
||||
*/
|
||||
private ServerAioHandler protocolHandler;
|
||||
|
||||
protected ImChannelContext imChannelContext;
|
||||
|
||||
protected String id;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
200
jim-common/src/main/java/org/jim/common/Jim.java
Normal file
200
jim-common/src/main/java/org/jim/common/Jim.java
Normal file
@ -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<ChannelContext> 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<ChannelContext> userChannels = Tio.getByUserid(tioConfig, userId);
|
||||
Set<ChannelContext> 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<ChannelContext> userChannelContexts = Tio.getByUserid(imConfig.getTioConfig(), userId);
|
||||
Set<ChannelContext> 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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ package org.jim.common;
|
||||
*/
|
||||
public interface Status {
|
||||
|
||||
public int getCode();
|
||||
int getCode();
|
||||
|
||||
public String getMsg();
|
||||
String getMsg();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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<ImClusterVo>() {
|
||||
@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() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
278
jim-common/src/main/java/org/jim/common/config/ImConfig.java
Normal file
278
jim-common/src/main/java/org/jim/common/config/ImConfig.java
Normal file
@ -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<Runnable> 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 extends ImConfig> C get(){
|
||||
return (C) global;
|
||||
}
|
||||
|
||||
public static <C extends ImConfig> C set(C c){
|
||||
global = (ImConfig) c;
|
||||
return (C) global;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class Builder<T extends ImConfig, B extends ImConfig.Builder<T,B>> {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
@ -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(IHttpRequestHandler httpRequestHandler, IHttpServerListener httpServerListener){
|
||||
setHttpRequestHandler(httpRequestHandler);
|
||||
setHttpServerListener(httpServerListener);
|
||||
}
|
||||
|
||||
public HttpConfig() {}
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author wchao
|
||||
* 静态资源缓存时间,如果小于等于0则不缓存,单位:秒
|
||||
*/
|
||||
public HttpConfig(Integer bindPort, Long sessionTimeout) {
|
||||
this.bindPort = bindPort;
|
||||
if (sessionTimeout != null) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<String> lines, Header header, ChannelContext channelContext) throws AioDecodeException {
|
||||
public static void parseHeader(List<String> 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);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
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)
|
||||
{
|
||||
channelContext.setAttribute(new HttpSession());
|
||||
ImUtils.setClient(channelContext);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConvertProtocolPacket converter() {
|
||||
return new HttpConvertPacket();
|
||||
}
|
||||
|
||||
@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;
|
||||
|
@ -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<String, Cookie> 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<String, String> headers) {
|
||||
|
@ -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<String, String> 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<String, Object[]> params, String paramsStr, String charset, ChannelContext channelContext) {
|
||||
public static void decodeParams(Map<String, Object[]> 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<String, String> 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);
|
||||
|
@ -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<Cookie> 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<String, String> headers = httpResponse.getHeaders();
|
||||
if (headers != null && headers.size() > 0) {
|
||||
headers.put(HttpConst.ResponseHeaderKey.Content_Length, bodyLength + "");
|
||||
headers.put(Http.ResponseHeaderKey.Content_Length, bodyLength + "");
|
||||
Set<Entry<String, String>> set = headers.entrySet();
|
||||
for (Entry<String, String> entry : set) {
|
||||
sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n");
|
||||
@ -68,7 +67,7 @@ public class HttpResponseEncoder {
|
||||
List<Cookie> 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()) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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<String, Serializable> 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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{
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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("-", "");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
return true;
|
||||
protected void init(ImChannelContext imChannelContext) {
|
||||
imChannelContext.setSessionContext(new TcpSessionContext(imChannelContext));
|
||||
ImUtils.setClient(imChannelContext);
|
||||
}
|
||||
if(buffer != null){
|
||||
//获取第一个字节协议版本号;
|
||||
byte version = buffer.get();
|
||||
//TCP协议;
|
||||
if(version == Protocol.VERSION){
|
||||
channelContext.setAttribute(new TcpSessionContext());
|
||||
ImUtils.setClient(channelContext);
|
||||
|
||||
@Override
|
||||
public boolean validateProtocol(ImSessionContext imSessionContext) throws ImException {
|
||||
if(imSessionContext instanceof TcpSessionContext){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConvertProtocolPacket converter() {
|
||||
return new TcpConvertPacket();
|
||||
public boolean validateProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException {
|
||||
//获取第一个字节协议版本号,TCP协议;
|
||||
if(buffer.get() == Protocol.VERSION){
|
||||
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 TcpPacket){
|
||||
Object sessionContext = channelContext.getAttribute();
|
||||
if(sessionContext == null){
|
||||
channelContext.setAttribute(new TcpSessionContext());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<ChannelContext> toChannelContexts = ImAio.getChannelContextsByUserId(userId);
|
||||
SetWithLock<ChannelContext> toChannelContexts = Jim.getChannelContextsByUserId(userId);
|
||||
if(toChannelContexts != null && toChannelContexts.size() > 0){
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -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<String,AbProtocol> protocols = new HashMap<String,AbProtocol>();
|
||||
|
||||
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<String,AbProtocol> 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<String,AbProtocol> 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<String,AbProtocol> 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,15 +44,7 @@ public class ImKit {
|
||||
* @return
|
||||
*/
|
||||
public static byte[] toImStatusBody(ImStatus status){
|
||||
return JsonKit.toJsonBytes(new RespBody().setCode(status.getCode()).setMsg(status.getDescription()+" "+status.getText()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有协议判断器,目前内置(HttpProtocol、WebSocketProtocol、HttpProtocol)
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, AbProtocol> getProtocols() {
|
||||
return protocols;
|
||||
return JsonKit.toJsonBytes(new RespBody(status).setMsg(status.getDescription()+" "+status.getText()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
71
jim-common/src/main/java/org/jim/common/ws/WsConfig.java
Normal file
71
jim-common/src/main/java/org/jim/common/ws/WsConfig.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateProtocol(ByteBuffer buffer, ImChannelContext imChannelContext) throws ImException {
|
||||
//第一次连接;
|
||||
if(buffer != null){
|
||||
HttpRequest request = HttpRequestDecoder.decode(buffer, channelContext,false);
|
||||
if(request.getHeaders().get(HttpConst.RequestHeaderKey.Sec_WebSocket_Key) != null)
|
||||
HttpRequest request = HttpRequestDecoder.decode(buffer, imChannelContext,false);
|
||||
if(request.getHeaders().get(Http.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;
|
||||
}
|
||||
public boolean validateProtocol(ImPacket imPacket) throws ImException {
|
||||
if(imPacket instanceof WsPacket){
|
||||
Object sessionContext = channelContext.getAttribute();
|
||||
if(sessionContext == null){
|
||||
channelContext.setAttribute(new WsSessionContext());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<byte[]> 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<br>
|
||||
* 感谢开源作者的付出
|
||||
* @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<String, String> 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<String, String> 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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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<byte[]> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@
|
||||
<artifactId>jim-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>2.6.0.v20190114-RELEASE</version>
|
||||
<version>3.0.0.v20200101-RELEASE</version>
|
||||
<description>Jim-parent is the dependent parent project of J-IM communication establishment.</description>
|
||||
<url>http://www.j-im.org/</url>
|
||||
<licenses>
|
||||
@ -34,9 +34,9 @@
|
||||
<module>../jim-server-demo</module>
|
||||
</modules>
|
||||
<properties>
|
||||
<jim.version>2.6.0.v20190114-RELEASE</jim.version>
|
||||
<tio-core.version>2.4.0.v20180508-RELEASE</tio-core.version>
|
||||
<tio-utils.version>2.4.0.v20180508-RELEASE</tio-utils.version>
|
||||
<jim.version>3.0.0.v20200101-RELEASE</jim.version>
|
||||
<tio-core.version>3.5.8.v20191228-RELEASE</tio-core.version>
|
||||
<tio-utils.version>3.5.8.v20191228-RELEASE</tio-utils.version>
|
||||
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
@ -62,6 +62,7 @@
|
||||
<jedis.version>2.7.3</jedis.version>
|
||||
<redisson.version>3.7.0</redisson.version>
|
||||
<j2cache.version>2.3.21-release</j2cache.version>
|
||||
<guava.version>23.0</guava.version>
|
||||
</properties>
|
||||
<repositories>
|
||||
|
||||
@ -250,7 +251,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>23.0</version>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nl.basjes.parse.useragent</groupId>
|
||||
@ -267,6 +268,11 @@
|
||||
<artifactId>j2cache-core</artifactId>
|
||||
<version>${j2cache.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<!-- 插件配置 -->
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.j-im</groupId>
|
||||
<artifactId>jim-parent</artifactId>
|
||||
<version>2.6.0.v20190114-RELEASE</version>
|
||||
<version>3.0.0.v20200101-RELEASE</version>
|
||||
<relativePath>../jim-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,28 @@
|
||||
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
|
||||
@ -22,12 +30,11 @@ public class ImDemoGroupListener extends ImGroupListener{
|
||||
* @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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.j-im</groupId>
|
||||
<artifactId>jim-parent</artifactId>
|
||||
<version>2.6.0.v20190114-RELEASE</version>
|
||||
<version>3.0.0.v20200101-RELEASE</version>
|
||||
<relativePath>../jim-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
|
@ -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;
|
||||
private static Logger log = LoggerFactory.getLogger(ImServerStarter.class);
|
||||
private TioServer tioServer = null;
|
||||
private ImServerConfig imServerConfig;
|
||||
|
||||
public ImServerStarter(ImConfig imConfig){
|
||||
this(imConfig,null);
|
||||
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(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());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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 <T> List<T> getProcessor(ChannelContext channelContext,Class<T> clazz){
|
||||
public <T> List<T> getProcessor(ImChannelContext imChannelContext, Class<T> clazz){
|
||||
List<T> processorList = null;
|
||||
for(Entry<String,CmdProcessor> 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<String,CmdProcessor> 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);
|
||||
@ -106,12 +99,8 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
@ -25,8 +25,6 @@ public class CommandManager{
|
||||
private static Map<Integer, AbstractCmdHandler> 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<Integer,AbstractCmdHandler> entry : handlerMap.entrySet()){
|
||||
try {
|
||||
entry.getValue().setImConfig(imConfig);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
public static ImConfig getImConfig() {
|
||||
return imConfig;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<ChatCmdProcessor> chatProcessors = this.getProcessorNotEqualName(Sets.newHashSet(ImConst.BASE_ASYNC_CHAT_MESSAGE_PROCESSOR),ChatCmdProcessor.class);
|
||||
/*List<ChatCmdProcessor> 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<HandshakeCmdProcessor> 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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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<GroupCmdProcessor> groupCmdProcessors = this.getProcessor(channelContext, GroupCmdProcessor.class);
|
||||
List<GroupCmdProcessor> 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
|
||||
|
@ -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<LoginCmdProcessor> loginProcessors = this.getProcessor(channelContext, LoginCmdProcessor.class);
|
||||
List<LoginCmdProcessor> 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<Group> 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<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<User> 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<User> copyUsers = new ArrayList<User>();
|
||||
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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user