实际效果展示
核心代码块
SocketServiceLoader.java
package com.linksaint.web.socket.service;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class SocketServiceLoader implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent arg0) {
//启动Socketio服务
Socketio socketio = new Socketio();
socketio.startServer();
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
//关闭Socketio服务
Socketio socketio = new Socketio();
socketio.stopSocketio();
}
}
Socketio.java
package com.linksaint.web.socket.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.ContextLoader;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import com.linksaint.system.po.SysUser;
import com.linksaint.system.service.SysMaxIdService;
import com.linksaint.system.service.SysUserService;
import com.linksaint.util.DateUtils;
import com.linksaint.web.socket.listener.CharteventListener;
import com.linksaint.web.socket.listener.ChatConnectListenner;
import com.linksaint.web.socket.po.ChatConnect;
import com.linksaint.web.socket.po.ChatInfo;
import com.linksaint.web.socket.po.ChatRoom;
import com.linksaint.web.socket.po.ClientInfo;
import com.linksaint.web.socket.po.Room_user_rel;
/*
* netty-socketio工具类
* 启动、添加客户端
* 消息推送
* 关闭服务
*/
public class Socketio {
@Autowired
private ClientInfoService clientInfoService;
@Autowired
private ChatInfoService chatInfoService;
@Autowired
private ChatRoomService chatRoomService;
@Autowired
private SysUserService sysUserService;
@Autowired
private Room_user_relService room_user_relService;
@Autowired
private SysMaxIdService sysMaxIdService;
static SocketIOServer socketIOServer;
/*
* 添加客户端
*/
public void startSocketio() throws InterruptedException {
//配置
Configuration conf = new Configuration();
//指定要主机ip地址,这个和页面请求ip地址一致
// conf.setHostname("192.168.0.67");
conf.setHostname("192.168.0.129");
//指定端口号
conf.setPort(9092);
//设置最大的WebSocket帧内容长度限制
conf.setMaxFramePayloadLength(1024*1024);
//设置最大HTTP内容长度限制
conf.setMaxHttpContentLength(1024 * 1024);
socketIOServer = new SocketIOServer(conf);
System.out.println("服务器已经建立,,等待客户端连接。。");
clientInfoService=(ClientInfoService) ContextLoader.getCurrentWebApplicationContext().getBean("clientInfoService");
chatInfoService=(ChatInfoService) ContextLoader.getCurrentWebApplicationContext().getBean("chatInfoService");
sysUserService=(SysUserService) ContextLoader.getCurrentWebApplicationContext().getBean("sysUserService");
room_user_relService=(Room_user_relService) ContextLoader.getCurrentWebApplicationContext().getBean("room_user_relService");
sysMaxIdService=(SysMaxIdService) ContextLoader.getCurrentWebApplicationContext().getBean("sysMaxIdService");
chatRoomService=(ChatRoomService) ContextLoader.getCurrentWebApplicationContext().getBean("chatRoomService");
/**
* 添加连接监听事件,监听是否与客户端连接到服务器
*/
socketIOServer.addConnectListener(new ConnectListener() {
@Override
public void onConnect(SocketIOClient client) {
// 判断是否有客户端连接
if (client != null) {
System.out.println("链接成功。。。");
} else {
System.err.println("暂无人员链接。。。");
}
System.err.println(client.getSessionId().toString());
}
});
/**
* 添加连接监听事件,监听是否与客户端连接到服务器
*/
socketIOServer.addDisconnectListener(new DisconnectListener() {
@Override
public void onDisconnect(SocketIOClient client) {
// 判断是否有客户端连接
if (client != null) {
System.out.println("断开连接。。。");
//根据客户端sessionID获取用户与client缓存中的信息
ClientInfo cInfo = clientInfoService.getClientInfoBycId(client.getSessionId().toString());
if(null!=cInfo){
cInfo.setConnected((short) 0);
clientInfoService.updateClient(cInfo);
}
} else {
System.err.println("暂无人员断开连接。。。");
}
System.err.println(client.getSessionId().toString());
}
});
// 握手请求
socketIOServer.addEventListener("helloevent", ChatConnect.class, new ChatConnectListenner() {
@Override
public void onData(final SocketIOClient client, ChatConnect data, AckRequest ackRequest) {
// 握手
String s=data.getType()==0?"移动端":"web端";
System.out.println("握手接收到"+s+"客户端"+data.getUserId()+"握手请求");
long userId = data.getUserId();
int type = data.getType();
long roomId=data.getRoomId();
//更加roomid类型,判断是群聊,群聊聊天室不存在就自动向注入此用户
ChatRoom room=chatRoomService.selectChatRoomIdInfo(roomId);
if(null!=room&&room.getType()==1){//群聊
List rels= room_user_relService.getRelInfosByRoomId(roomId,userId);
if(null!=rels&&rels.size()>0){
System.out.println("此用户已绑定到该群聊聊天室!");
}else{
Room_user_rel rel=new Room_user_rel();
rel.setRoomid(roomId);
rel.setUserid(userId);
rel.setTargetid(0L);
room_user_relService.addChatRel(rel);
}
}
ClientInfo clientInfo=null;
if(userId>0&&type>-1){
clientInfo = clientInfoService.getClientInfoByUserId(userId,type) ;
}
if (clientInfo != null)
{
clientInfo.setClientid(client.getSessionId().toString());
clientInfo.setConnected((short)1);
clientInfo.setMostsignbits(client.getSessionId().getMostSignificantBits());
clientInfo.setLeastsignbits(client.getSessionId().getLeastSignificantBits());
clientInfo.setLastconnecteddate(DateUtils.getNowDate());
clientInfo.setUserId(userId);
clientInfo.setType(type);
clientInfo.setRoomId(roomId);
clientInfoService.updateClient(clientInfo);
}else{
ClientInfo info = new ClientInfo();
info.setClientid(client.getSessionId().toString());
info.setConnected((short)1);
info.setMostsignbits(client.getSessionId().getMostSignificantBits());
info.setLeastsignbits(client.getSessionId().getLeastSignificantBits());
info.setLastconnecteddate(DateUtils.getNowDate());
info.setUserId(userId);
info.setType(type);
info.setRoomId(roomId);
clientInfoService.addClient(info);
}
}
});
//私信
socketIOServer.addEventListener("message", ChatInfo.class, new CharteventListener() {
@Override
public void onData(SocketIOClient client, ChatInfo data,
AckRequest ackSender) throws Exception {
SysUser user=sysUserService.GetUserById(data.getSourceUserId());
System.out.println("私聊房间号:"+data.getRoomid()+"--"+user.getUserName()+":" + data.getMessage());
//向客户端发送消息
long chatid = sysMaxIdService.selectSysMaxId("chatMessage");
data.setMessageId(chatid);
data.setMessage(data.getMessage());
data.setState(0);//初始状态未发送
data.setSenddate(DateUtils.getNowDate());
//获得消息所在房间
List rels= room_user_relService.getRelInfosByRoomId(data.getRoomid());
ChatRoom room=new ChatRoom();
room.setId(data.getRoomid());
room.setDate(DateUtils.getNowDate());
room.setType(2);
chatRoomService.updateChatRoom(room);
for (Room_user_rel rel : rels) {
if(rel.getTargetid()>0){//单聊聊天记录
data.setTargetUserId(rel.getTargetid());
long id=chatInfoService.insertChatInfo(data);
}else{//群聊聊天记录
if(!rel.getUserid().equals(data.getSourceUserId())){
data.setTargetUserId(rel.getUserid());
long id=chatInfoService.insertChatInfo(data);
}
}
}
Collection clients = socketIOServer.getAllClients();
//发送给聊天室在线人员(不包括自己)
List cons=clientInfoService.getClientInfosByRoomId(data.getRoomid(),data.getSourceUserId());
for (ClientInfo info : cons) {
System.out.println("数据库中:"+info.getClientid());
for (SocketIOClient c : clients) {
System.out.println("socket服务中:"+c.getSessionId().toString());
if(c.getSessionId().toString().equals(info.getClientid())){
c.sendEvent("message",data);
//如果客户端在线,更新消息发送状态为已发送
//判断用户活跃聊天室是否为当前消息聊天室
if(info.getRoomId()==data.getRoomid()){
chatInfoService.updateSendStateByclient(data.getRoomid(), data.getSourceUserId(), info.getUserId());
}
}
}
}
}
});
//群聊
socketIOServer.addEventListener("chat", ChatInfo.class, new CharteventListener() {
@Override
public void onData(SocketIOClient client, ChatInfo data,
AckRequest ackSender) throws Exception {
SysUser user=sysUserService.GetUserById(data.getSourceUserId());
System.out.println("群聊房间号:"+data.getRoomid()+"--"+user.getUserName()+":" + data.getMessage());
//向客户端发送消息
long chatid = sysMaxIdService.selectSysMaxId("chatMessage");
data.setMessageId(chatid);
data.setMessage(data.getMessage());
data.setState(0);//初始状态未发送
data.setSenddate(DateUtils.getNowDate());
//获得消息所在房间
List rels= room_user_relService.getRelInfosByRoomId(data.getRoomid());
List list=new ArrayList();
if(null!=rels&&rels.size()==1){
data.setTargetUserId(0);
long id=chatInfoService.insertChatInfo(data);
data.setId(id);
}else{
for (Room_user_rel rel : rels) {
//群聊聊天记录
if(!rel.getUserid().equals(data.getSourceUserId())){
data.setTargetUserId(rel.getUserid());
long id=chatInfoService.insertChatInfo(data);
list.add(id);
}
}
}
//获取群聊信息最小id一条数据
if(list.size()>0){
data.setId(list.get(0));
}
Collection clients = socketIOServer.getAllClients();
//发送给聊天室在线人员(包括自己)
List cons=clientInfoService.getAllClientInfosByRoomId(data.getRoomid());
for (ClientInfo info : cons) {
System.out.println("数据库中:"+info.getClientid());
for (SocketIOClient c : clients) {
System.out.println("socket服务中:"+c.getSessionId().toString());
if(c.getSessionId().toString().equals(info.getClientid())){
c.sendEvent("chat",data);
}
}
}
}
});
//各客户端同步群聊标记重点
socketIOServer.addEventListener("sign", ChatInfo.class, new CharteventListener() {
@Override
public void onData(SocketIOClient client, ChatInfo data,
AckRequest ackSender) throws Exception {
SysUser user=sysUserService.GetUserById(data.getSourceUserId());
System.out.println("群聊房间号:"+data.getRoomid()+"-被标记重点Id-"+data.getId()+";是否标记(0:取消标记,1:标记):" + data.getStatus());
Collection clients = socketIOServer.getAllClients();
//发送给聊天室在线人员该条记录的标记次数(包括自己)
List cons=clientInfoService.getAllClientInfosByRoomId(data.getRoomid());
for (ClientInfo info : cons) {
// System.out.println("数据库中:"+info.getClientid());
for (SocketIOClient c : clients) {
// System.out.println("socket服务中:"+c.getSessionId().toString());
if(c.getSessionId().toString().equals(info.getClientid())){
c.sendEvent("sign",data);
}
}
}
}
});
socketIOServer.start();
//设置超时时间
Thread.sleep(Integer.MAX_VALUE);
socketIOServer.stop();
}
/**
* 给所有连接客户端推送消息
* @param eventType 推送的事件类型
* @param message 推送的内容
*/
public static void sendMessageToAllClient(String eventType,ChatInfo message){
//返回默认名称空间中的所有客户端实例。
Collection clients = socketIOServer.getAllClients();
//getBroadcastOperations() 返回默认名称空间的所有实例组成的广播对象。
//getRoomOperations() 返回所有命名空间中指定房间的广播对象,如果命名空间只有一个,该方法到可以大胆使用。
//getClient(uid) 返回默认名称空间的指定客户端。
//getNamespace() 返回指定名称的命名空间。
for(SocketIOClient client: clients){
System.out.println(client.getSessionId().toString());
client.sendEvent(eventType,message);
}
}
/*
* 启动服务
*/
public void startServer() {
if (socketIOServer == null) {
new Thread(new Runnable() {
@Override
public void run() {
try {
startSocketio();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
/*
* 停止服务
*/
public void stopSocketio() {
if (socketIOServer != null) {
socketIOServer.stop();
socketIOServer = null;
}
}
}