从网上找的,又经过了自己的改良,由于新手,技术残次,写这些也是为了起到笔记的作用,高手勿喷!
服务器端:
1.servlet继承WebSocketServlet,重写createWebSocketInbound方法。
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import com.websocket.servlet.impl.WebSocketMessageInbound;
@WebServlet(name = "ChatWebSocket", urlPatterns = "/Chat")
public class ChatWebSocket extends WebSocketServlet {
private static final long serialVersionUID = -1058445282919079067L;
@Override
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest request) {
return new WebSocketMessageInbound(request);
}
}
2.WebSocketMessageInbound继承MessageInbound,重写onOpen(打开连接)、onClose(关闭连接)、onBinaryMessage、onTextMessage(发送消息),带了个request是想从其中获取参数,比如和谁聊天等
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;
import org.apache.log4j.Logger;
import com.chat.model.ChatDataModel;
import com.chat.service.ChatService;
import com.chat.service.impl.ChatServiceImpl;
import com.websocket.xml.WebSocketToString;
public class WebSocketMessageInbound extends MessageInbound {
private static Map<Integer, WebSocketMessageInbound> connections = new HashMap<Integer, WebSocketMessageInbound>();
private static Integer count = 0;
Logger logger = Logger.getLogger(getClass());
private Integer iUserId;
private Integer iFid;
public WebSocketMessageInbound(HttpServletRequest request){
String sUserId = request.getParameter("uid");
this.iUserId = Integer.valueOf(sUserId);
String sFid = request.getParameter("fid");
this.iFid = Integer.valueOf(sFid);
}
public Integer getUser(){
return this.iUserId;
}
public Integer getFid(){
return this.iFid;
}
//连接websocket,并获取缓存中的对话
@Override
protected void onOpen(WsOutbound outbound) {
connections.put(iUserId, this);
logger.info("用户---" + iUserId + "---加入聊天");
count++;
logger.info("在线人数:--" + count + "--人");
ChatData chatData= new ChatData();
Map<Integer, List<ChatDataModel>> chatToMeMap = chatData.getChatNumByUserId(iUserId);
if(chatToMeMap != null){
try {
String strResponse = WebSocketToString.receiveChatToString(chatToMeMap);
this.getWsOutbound().writeTextMessage(CharBuffer.wrap(strResponse));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
protected void onClose(int status) {
connections.remove(iUserId);
logger.info("用户---" + iUserId + "---退出聊天");
count--;
logger.info("在线人数:--" + count + "--人");
}
@Override
protected void onBinaryMessage(ByteBuffer buffer) throws IOException {
// TODO Auto-generated method stub
}
//发送聊天内容, 如果在线直接通过websocket发送, 不过不在线存到缓存
@Override
protected void onTextMessage(CharBuffer message) throws IOException {
//得到对方connection
WebSocketMessageInbound inbound = connections.get(iFid);
ChatDataModel chatDataModel = new ChatDataModel();
chatDataModel.setSend_id(iUserId);
chatDataModel.setRecieive_id(iFid);
chatDataModel.setContent(message.toString());
long time = new Date().getTime();
chatDataModel.setTime(time);
StringBuffer sInfo = new StringBuffer();
//如果对方在线
if(inbound != null){
logger.info(iFid + " 在线");
inbound.getWsOutbound().writeTextMessage(CharBuffer.wrap(chatDataModel.toString()));
logger.info(iUserId+" 对 "+iFid+"说:"+chatDataModel.getContent());
sInfo.append("发送成功");
//如果对方不在线
}else{
logger.info(iFid +" 不在线");
ChatData chatData= new ChatData();
chatData.setChatById(iUserId, iFid, chatDataModel);
logger.info(iUserId+" 对 "+iFid+"说:"+chatDataModel.getContent());
logger.info("已经放入缓存");
sInfo.append("对方暂时没有收到消息,已经保存到服务器");
}
this.getWsOutbound().writeTextMessage(CharBuffer.wrap(sInfo.toString()));
}
}
其中chatServiceImpl类里面提供的方法是用来保存不在线用户的聊天记录的,当用户上线的时候先获取缓存中的记录。
3.ChatData如下
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import com.chat.model.ChatDataModel;
public class ChatData {
static Logger logger = Logger.getLogger(ChatData.class);
static Map<Integer, Map<Integer, List<ChatDataModel>>> mapChat = new Hashtable<Integer, Map<Integer, List<ChatDataModel>>>();
public static Map<Integer, List<ChatDataModel>> mapChatToMeNum(Integer iUserId){
return ChatData.mapChat.get(iUserId);
}
/**
* 接收到的
* */
public static List<ChatDataModel> getChatById(Integer iUserId, Integer iPlayerId) {
// 这个是所有发给我的
Map<Integer, List<ChatDataModel>> mapReceive = mapChat.get(iUserId);
logger.debug(mapReceive);
if (mapReceive == null) {
return null;
} else {
// listReceive = new ArrayList();
// 这个是Player发给我的
List<ChatDataModel> listReceive = mapReceive.get(iPlayerId);
// 取出点对点聊天信息列表后从内存中删除
mapReceive.remove(iPlayerId);
return listReceive;
}
}
/**
* 发送的
* */
public static boolean setChatById(Integer iUserId, Integer iPlayerId, ChatDataModel chatDataModel) {
// 从内存获得对方收到的我发的聊天信息列表
List<ChatDataModel> listSend = getChatById(iPlayerId, iUserId);
if (listSend == null) {
listSend = new ArrayList<ChatDataModel>();
}
// 列表中加入聊天信息
listSend.add(chatDataModel);
// 这个是指定的Player收到的
Map<Integer, List<ChatDataModel>> mapSend = mapChat.get(iPlayerId);
if (mapSend == null) {
mapSend = new HashMap<Integer, List<ChatDataModel>>();
}
mapSend.put(iUserId, listSend);
// 这个是Player接收的所有的
mapChat.put(iPlayerId, mapSend);
logger.debug("<setChatById>" + mapChat);
return true;
}
//消息个数
public static int getChatMapCount(Integer iUserId){
int count = 0;
for(Entry<Integer, Map<Integer, List<ChatDataModel>>> entry : mapChat.entrySet()){
if(entry.getKey() == iUserId.intValue()){
Map<Integer, List<ChatDataModel>> m = entry.getValue();
System.out.println(m);
if(m==null){
break;
}
for(Entry<Integer, List<ChatDataModel>> en : m.entrySet()){
List<ChatDataModel> li = en.getValue();
count +=li.size();
}
}
}
return count;
}
}
4.model如下
public class ChatDataModel {
private int chat_id;
private Integer send_id;
private Integer recieive_id;
private String content;
private String time;
public int getChat_id() {
return chat_id;
}
public void setChat_id(int chat_id) {
this.chat_id = chat_id;
}
public Integer getSend_id() {
return send_id;
}
public void setSend_id(Integer send_id) {
this.send_id = send_id;
}
public Integer getRecieive_id() {
return recieive_id;
}
public void setRecieive_id(Integer recieive_id) {
this.recieive_id = recieive_id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
@Override
public String toString(){
StringBuffer sb = new StringBuffer();
String hr = "#|property|#";
sb.append(getSend_id());
sb.append(hr);
sb.append(getTime());
sb.append(hr);
sb.append(getContent());
return sb.toString();
}
}
客户端:
由于没有登录,所以我把jsp写死了,固定为111对222说话
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.lang.*"%>
<%
String path = request.getContextPath();
String WsBasePath = "ws://" + request.getServerName() + ":"
+ request.getServerPort() + path + "/";
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>websocket聊天室</title>
<style type="text/css">
#chat {
text-align: left;
width: 600px;
height: 500px;
width: 600px;
}
#up {
text-align: left;
width: 100%;
height: 400px;
border: 1px solid green;
OVERFLOW-Y: auto;
}
#down {
text-align: left;
height: 100px;
width: 100%;
}
</style>
</head>
<body>
<h2 align="center">基于HTML5的聊天室</h2>
<div align="center" style="width: 100%; height: 700px;">
<div id="chat">
<div id="up"></div>
<div id="down">
<textarea style="width: 602px; height: 100%;" id="send"></textarea>
</div>
</div>
<br/>
<input type="button" value="连接" οnclick="chat(this);"> <input
type="button" value="发送" οnclick="send(this);" disabled="disabled"
id="send_btn" title="Ctrl+Enter发送">
</div>
</body>
<script type="text/javascript">
var socket;
var receive_text = document.getElementById("up");
var send_text = document.getElementById("send");
function addText(msg) {
receive_text.innerHTML += "<br/>" + msg;
receive_text.scrollTop = receive_text.scrollHeight;
}
var chat = function(obj) {
obj.disabled = "disabled";
try{
socket = new WebSocket('<%=WsBasePath + "Chat?uid=111&fid=222"%>');
receive_text.innerHTML += "<font color=green>正在连接服务器……</font>";
}catch(e){
receive_text.innerHTML += "<font color=red>抱歉,您的浏览器不支持html5,请使用IE10或者最新版本的谷歌、火狐等浏览器!</font>";
}
//打开Socket
socket.onopen = function(event) {
falg=false;
addText("<font color=green>连接成功!</font>");
document.getElementById("send_btn").disabled = false;
send_text.focus();
document.onkeydown = function(event) {
if (event.keyCode == 13 && event.ctrlKey) {
send();
}
};
};
socket.onmessage = function(event) {
addText(event.data);
};
socket.onclose = function(event) {
addText("<font color=red>连接断开!</font>");
obj.disabled = "";
};
};
var send = function(obj) {
if (send_text.value == "") {
return;
}
socket.send(send_text.value);
send_text.value = "";
send_text.focus();
};
</script>
</html>