有小伙伴需要源码,该文章中的代码年代久远,重新弄了一个seven-im,请移步
轮询:简单粗暴,过多的请求,服务器表示压力很大
长连接:发送请求到服务器,有消息时才返回,长时间占用资源
websocket:基于tcp新的协议,双向通信
废话少说,上代码(部分关键代码)!
交流平台
发送
var Chat = {};
Chat.socket = null;
Chat.connect = (function(host){
if ('WebSocket' in window) {
Chat.socket = new WebSocket(host);
} else if ('MozWebSocket' in window) {
Chat.socket = new MozWebSocket(host);
} else {
Console.log('Error: WebSocket is not supported by this browser.');
return;
}
//websocket连接打开时
Chat.socket.onopen = function () {
document.getElementById('chat').onkeydown = function(event) {
if (event.keyCode == 13) {
Chat.sendMessage();
event.returnValue = false;
event.preventDefault();
}
};
};
//websocket连接关闭时
Chat.socket.onclose = function () {
document.getElementById('chat').onkeydown = null;
};
//websocket连接有消息时
Chat.socket.onmessage = function (message) {
var data = eval('(' + message.data + ')');
//data即为后台发送的数据,在此根据数据内容进行判断属于Chat.info | Chat.self | Chat.other
}
});
//初始化
Chat.initialize = function() {
if (window.location.protocol == 'http:') {
Chat.connect('ws://' + window.location.host + '/websocket/chat');
} else {
Chat.connect('wss://' + window.location.host + '/websocket/chat');
}
};
//发送的方法
Chat.sendMessage = (function() {
var message = document.getElementById('chat').value;
if (message != '') {
var data = {
'from':'',
'to':'',
'groupId':'',
'type':'',
'message':message
}//from,to,type为后期私聊,群里
var msg = JSON.stringify(data);
Chat.socket.send(msg);
document.getElementById('chat').value = '';
}
});
var Console = {};//聊天主窗体
//负责展现系统提示,例如 小明进入
Console.info = (function(message) {
var h = ''+ message +'';
$('#center').append(h);
});
//负责展现自己发送的消息,显示在右边
Console.self=(function(data){
var h = '';
//将data解析为html片段
$('#center').append(h);
});
//负责展现其他人发送的消息,显示在左边
Console.other=(function(data){
var h = '';
//将data解析为html片段
$('#center').append(h);
});
Chat.initialize();
websocket连接/关闭/收发消息的整个过程
@ServerEndpoint(value = "/websocket/chat", configurator = GetHttpSessionConfigurator.class, encoders = ServerEncoder.class)
public class ChatWebSocket {
//存储所有的websocket连接
private static final Map CONNECTIONS = new LinkedHashMap();
private User user;
private Session session;
/**
* 当websocket握手成功时触发
* 该方法参数是可选的,session指的是websocket的session,不是httpSession.
* 获取httpSession需要通过EndpointConfig类,而EndpointConfig类是由@ServerEndpoin()中的configurator进行设置
*/
@OnOpen
public void start(Session session, EndpointConfig config){
this.session = session;
HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
WebSocketMessage webSocketMessage = new WebSocketMessage();
if(httpSession == null){
webSocketMessage.setMessage("您未登录系统");
ChatWebSocket.sendToOne(this,webSocketMessage);
try {
this.session.close();
} catch (IOException e) {
e.printStackTrace();
}
}else{
//获取httpSession中登录的用户
User user = (User) httpSession.getAttribute("currentUser");
if(user == null){
webSocketMessage.setMessage("登录错误,未知用户");
ChatWebSocket.sendToOne(this,webSocketMessage);
try {
this.session.close();
} catch (IOException e) {
e.printStackTrace();
}
}else{
this.user = user;
CONNECTIONS.put(this.user.getId(), this);
webSocketMessage.setUserId(this.user.getId());
ChatWebSocket.sendToOne(this,webSocketMessage);
String msg = this.user.getName() + " 进入";
ChatWebSocket.broadcastOnline(msg);
}
}
}
//当websocket握手关闭时触发
@OnClose
public void end(){
CONNECTIONS.remove(this.user.getId());
String msg = this.user.getName() + " 离开";
ChatWebSocket.broadcastOnline(msg);
}
//当收到消息时
@OnMessage
public void incoming(String message){
WebSocketMessage webSocketMessage = new WebSocketMessage();
webSocketMessage.setUserId(this.user.getId());
webSocketMessage.setUserName(this.user.getName());
webSocketMessage.setMessage(message);
webSocketMessage.setSendDate(new Date());
ChatWebSocket.broadcast(webSocketMessage);
}
//发送至单独用户
private static void sendToOne(ChatWebSocket chatWebSocket,
WebSocketMessage webSocketMessage) {
chatWebSocket.session.getAsyncRemote().sendObject(webSocketMessage);
}
//广播
private static void broadcast(WebSocketMessage webSocketMessage) {
Set keys = CONNECTIONS.keySet();
for (String key : keys) {
ChatWebSocket chatWebSocket = CONNECTIONS.get(key);
synchronized (chatWebSocket) {
ChatWebSocket.sendToOne(chatWebSocket, webSocketMessage);
}
}
}
//广播在线用户
private static void broadcastOnline(String msg) {
Set keys = CONNECTIONS.keySet();
WebSocketMessage webSocketMessage = new WebSocketMessage();
webSocketMessage.setType(WebSocketMessage.WEBSOCKETMESSAGE_TYPE_ALL);
webSocketMessage.setMessage(msg);
List userList = new ArrayList();
for (String key : keys) {
ChatWebSocket chatWebSocket = CONNECTIONS.get(key);
userList.add(chatWebSocket.user);
}
webSocketMessage.getAttributes().put("user", userList);
for (String key : keys) {
ChatWebSocket chatWebSocket = CONNECTIONS.get(key);
synchronized (chatWebSocket) {
ChatWebSocket.sendToOne(chatWebSocket, webSocketMessage);
}
}
}
}
发送消息的载体
public class WebSocketMessage {
private String userId;
private String userName;
private string from;
private string to;
private string groupId;
...
private String message;
private Date sendDate;
private String type;
private Map attributes = new HashMap();
public WebSocketMessage(){
super();
}
public WebSocketMessage(String userName,String message,Date sendDate) {
this.userName = userName;
this.sendDate = sendDate;
this.message = message;
}
//getter and setter ...
}
将消息进行编码转json设置
public class ServerEncoder implements Encoder.Text {
@Override
public void init(EndpointConfig paramEndpointConfig) {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public String encode(WebSocketMessage paramT) throws EncodeException {
//将WebSocketMessage转为json
return JsonMapper.buildNormalMapper().toJson(paramT);
}
}
获取httpSession
public class GetHttpSessionConfigurator extends Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec,
HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession=(HttpSession) request.getHttpSession();
if(httpSession!=null){
sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}
}
以上只是部分关键代码,简单的实现了即时通讯,若需要私聊,群聊,分组等功能,则需改造WebSocketMessage.java和前端js中Chat.socket.onmessage()
有小伙伴需要源码,该文章中的代码年代久远,重新弄了一个seven-im,请移步