一》用户端
<%@ page language="java" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>客户端</title>
<link rel="stylesheet" type="text/css" href="${BasePath }/css/web/chatClt.css" />
<script type="text/javascript" src="${BasePath }/js/jquery-3.2.0.min.js"></script>
<script type="text/javascript" src="${BasePath }/js/web/chatClt.js"></script>
</head>
<body class="keBody">
<div class="kePublic">
<!--效果html开始-->
<div class="content">
<div class="chatBox">
<div class="chatLeft">
<div class="chat01">
<div class="chat01_title">
<ul class="talkTo">
<li><a href="javascript:;">游客</a></li></ul>
</div>
<div class="chat01_content">
<div class="message_box mes3" style="display: block;">
<!-- 聊天记录开始 -->
<c:forEach items="${chat}" var="ch">
<!--主动发信人 客户 -->
<c:if test="${ch.send_type==1}">
<div class='message clearfix' >
<div class='user-logo'>
<img width='45px' src="${BasePath}/images/ico1.jpg"/>
</div>
<div class='wrap-text'>
<h5 class='clearfix'>游客</h5>
<div>${ch.chat_content}</div>
</div>
<div class='wrap-ri'>
<div clsss='clearfix'><span>
<fmt:parseDate value="${ch.send_time}" var="time"></fmt:parseDate>
<fmt:formatDate value="${time}" pattern="yyyy-MM-dd HH:mm:ss"/>
</span></div>
</div>
<div style='clear:both;'></div></div><div style='clear:both;'></div>
</c:if>
<!--主动发信人 客服 -->
<c:if test="${ch.send_type==2}">
<div class='messages clearfix' >
<div class='user-logo'>
<img width='45px' src='${BasePath}/images/svr.gif'/>
</div>
<div class='wrap-text'>
<h5 class='clearfix'>客服</h5>
<div>${ch.chat_content}</div>
</div>
<div class='wrap-ri'>
<div clsss='clearfix'>
<span>
<fmt:parseDate value="${ch.send_time}" var="time"></fmt:parseDate>
<fmt:formatDate value="${time}" pattern="yyyy-MM-dd HH:mm:ss"/></span>
</div>
</div>
<div style='clear:both;'></div></div><div style='clear:both;'></div>
</c:if>
</c:forEach>
<!-- 聊天记录结束 -->
</div>
</div>
</div>
<div class="chat02">
<div class="chat02_title">
<a class="chat02_title_btn ctb01" href="javascript:;"></a>
<div style="float: right;position:relative;top:5px;">
<a class="" href="${BasePath}/web/delCltrecord.do" onclick="return confirm('确定要删除吗')">
<span style="color:#3A5FCD">删除聊天记录</span></a></div>
<div class="wl_faces_box">
<div class="wl_faces_content">
<div class="title">
<ul>
<li class="title_name">常用表情</li>
<li class="wl_faces_close"><span> </span></li>
</ul>
</div>
<div class="wl_faces_main">
<jsp:include page="/include/webSocket/img.jsp"></jsp:include>
</div>
</div>
<div class="wlf_icon">
</div>
</div>
</div>
<div class="chat02_content">
<textarea id="textarea" ></textarea>
</div>
<div class="chat02_bar">
<ul>
<li style="left: 20px; top: 10px; padding-left: 30px;">来源:
<a href="http://www.internetke.com/" target="_blank" id="haha">宜家</a>
</li>
<li style="right: 5px; top: 5px;">
<img src="${BasePath }/images/img/send_btn.jpg">
</li>
</ul>
</div>
</div>
</div>
<!-- 获取后台自己的uuid -->
<input type="hidden" id="uuid" value="${uuid }">
<c:forEach items="${webSet}" var ="w">
<input type="hidden" id="svrUuid" value="${w.uuid}">
</c:forEach>
<div style="clear:both;"> </div>
</div>
</div>
<!--效果html结束-->
</div>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
var uuid="${uuid}";
websocket = new WebSocket("ws://192.168.6.26:8080/family/websocket?clt"+uuid );
} else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function() {
setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function() {
setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function(event) {
//setMessageInnerHTML(event.data);
var e=new Date,f="";
f+=e.getFullYear()+"-",
f+=e.getMonth()+1+"-",
f+=e.getDate()+" ",
f+=e.getHours()+":",
f+=e.getMinutes()+":",
f+=e.getSeconds();
//接收到的信息
var mess=event.data;
//信息要发送的uuid
var uuids=mess.substring(mess.length-36,mess.length);
//接收到的信息 真正要发送的内容
var sendmsg=mess.substring(36,mess.length-36);
var sssss="<div class='messages clearfix' ><div class='user-logo'><img width='45px' src='/family/images/svr.gif'/></div><div class='wrap-text'><h5 class='clearfix'>客服</h5><div>"+sendmsg+"</div></div><div class='wrap-ri'><div clsss='clearfix'><span>"+f+"</span></div></div><div style='clear:both;'></div></div><div style='clear:both;'></div>";
$(".mes3").append(sssss);
}
////连接关闭的回调方法
websocket.onclose = function() {
setMessageInnerHTML("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
closeWebSocket();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('haha').innerHTML +=innerHTML + '<br/>';
}
// 关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function send() {
var message = document.getElementById('textarea').value;
websocket.send("clt"+message);
}
//刷新上线人信息
function showLst(){
var url="${BasePath}/web/cltAjax.do";
$.post(url,function(str){
var strs=eval(str);
var lili="";
$("#ulul").html("");
for (var i= 0; i <strs.length; i++) {
lili+="<li><label ><input type='radio' name='xuanzhong' value='"+strs[i].uuid+"'> "+strs[i].uuid+"</label>";
}
$("#ulul").html(lili);
});
}
//setInterval("showLst()",10000);
</script>
</body>
</html>
二》客服端
<%@ page language="java" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>服务端</title>
<script type="text/javascript" src="${BasePath }/js/jquery-3.2.0.min.js"></script>
<link rel="stylesheet" type="text/css" href="${BasePath }/css/web/chatsvr.css" />
<script type="text/javascript" src="${BasePath }/js/web/chatsvr.js"></script>
</head>
<body class="keBody frameBody">
<div class="kePublic">
<!--效果html开始-->
<!-- 获取后台传来的自己的uuid -->
<input type="hidden" id="uuid" value="${uuid }">
<div class="content">
<div class="chatBox">
<div class="chatLeft">
<div class="chat01">
<div class="chat01_title">
<ul class="talkTo">
<li><a href="javascript:;">王旭</a></li></ul>
<a class="close_btn" href="javascript:;"></a>
</div>
<div class="chat01_content">
<div class="message_box mes3" style="display: block;"> </div>
</div>
</div>
<div class="chat02">
<div class="chat02_title">
<a class="chat02_title_btn ctb01" href="javascript:;"></a>
<div class="wl_faces_box">
<div class="wl_faces_content">
<div class="title">
<ul>
<li class="title_name">常用表情</li><li class="wl_faces_close"><span> </span></li></ul>
</div>
<div class="wl_faces_main">
<jsp:include page="/include/webSocket/img.jsp"></jsp:include>
</div>
</div>
<div class="wlf_icon">
</div>
</div>
</div>
<div class="chat02_content">
<textarea id="textarea"></textarea>
</div>
<div class="chat02_bar">
<ul>
<li style="left: 20px; top:10px; padding-left: 30px;">来源:
<a href="http://www.internetke.com/" target="_blank" id="haha">宜家</a></li>
<li style="right: 5px; top: 5px;">
<img src="${BasePath }/images/img/send_btn.jpg"></li>
</ul>
</div>
</div>
</div>
<div class="chatRight">
<div class="chat03">
<div class="chat03_title">
<label class="chat03_title_t"> 成员列表</label>
</div>
<div class="chat03_content">
<ul id="ulul">
<c:forEach items="${webSet}" var="w">
<li>
<label ><input type="radio" name="xuanzhong" value="${w.uuid}">${w.uuid}</label>
</li>
</c:forEach>
</ul>
</div>
</div>
</div>
<div style="clear:both;"> </div>
</div>
</div>
<!--效果html结束-->
</div>
</body>
<<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
var uuid="${uuid}";
var url="ws://192.168.6.26:8080/family/websocket?svr"+uuid;
websocket = new WebSocket(url);
} else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function() {
setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function() {
setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function(event) {
//setMessageInnerHTML(event.data);
var e=new Date,f="";
f+=e.getFullYear()+"-",
f+=e.getMonth()+1+"-",
f+=e.getDate()+" ",
f+=e.getHours()+":",
f+=e.getMinutes()+":",
f+=e.getSeconds();
var mess=event.data;
var uuids=mess.substring(mess.length-36,mess.length);
var sendmsg=mess.substring(0,mess.length-36);
var sssss="<div class='messages clearfix' ><div class='user-logo'><img width='45px' src='/family/images/ico1.jpg'/></div><div class='wrap-text'><h5 class='clearfix'>游客</h5><div>"+event.data+"</div></div><div class='wrap-ri'><div clsss='clearfix'><span>"+f+"</span></div></div><div style='clear:both;'></div></div><div style='clear:both;'></div>";
$(".mes3").append(sssss);
}
////连接关闭的回调方法
websocket.onclose = function() {
setMessageInnerHTML("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
closeWebSocket();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('haha').innerHTML +=innerHTML + '<br/>';
}
// 关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function send() {
var message = document.getElementById('textarea').value;
websocket.send("svr"+message);
}
/**
* 刷新在线人数
*/
function showLst(){
var url="${BasePath}/web/svrAjax.do";
$.post(url,function(str){
var strs=eval(str);
var lili="";
$("#ulul").html("");
for (var i= 0; i <strs.length; i++) {
lili+="<li><label ><input type='radio' name='xuanzhong' value='"+strs[i].uuid+"'> "+strs[i].uuid+"</label></li>";
}
$("#ulul").html(lili);
});
}
//setInterval("showLst()",10000);
</script>
</html>
三》服务器端
package com.wskj.app.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
/**
* @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
*/
@ServerEndpoint("/websocket")
public class WebSocketTest {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static List<WebSocketTest> cltSet = new ArrayList<WebSocketTest>();
private static List<WebSocketTest> svrSet = new ArrayList<WebSocketTest>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
//客户还是服务人员
private String type;
//昵称
private String nickName;
private String uuid;
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session){
///获取前台的url
String url=session.getRequestURI().toString();
//获取url字符串最后三位
String types=url.substring(url.length()-39, url.length()-36);
this.uuid=url.substring(url.length()-36, url.length());
this.type=types;
this.session = session;
//如果前台传来的是客户 存入 cltSet
//服务端 存入 svr
if(types.equals("svr")){
svrSet.add(this); //加入set中
}else if(types.equals("clt")){
cltSet.add(this); //加入set中
}
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()+"
"+getUuid());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
cltSet.remove(this); //从set中删除
svrSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage (String message, Session session) {
System.out.println("来自客户端的消息:" + message);
//群发消息
String types=message.substring(36,39);
//发信人的uuid
String uuids=message.substring(0,36);
//接信人的uuid
String beiUuids=message.substring(message.length()-36,message.length());
if(types.equals("clt")){
for(WebSocketTest itemSvr: svrSet){
if(itemSvr!=null && itemSvr.uuid.equals(beiUuids)){
try {
itemSvr.sendMessage(message.substring(3,message.length()-36)+uuids);
System.out.println(message.substring(3,message.length()-36)+uuids);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
}
//如果传过来的是服务人员 根据选择的uuid 发送消息
if(types.equals("svr")){
for(WebSocketTest itemClt: cltSet){
if(itemClt!=null && itemClt.uuid.equals(beiUuids)){
try {
itemClt.sendMessage(message.substring(3,message.length()-36)+uuids);
System.out.println(message.substring(3,message.length()-36)+uuids);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketTest.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketTest.onlineCount--;
}
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public static void setOnlineCount(int onlineCount) {
WebSocketTest.onlineCount = onlineCount;
}
public static List<WebSocketTest> getCltSet() {
return cltSet;
}
public static void setCltSet(List<WebSocketTest> cltSet) {
WebSocketTest.cltSet = cltSet;
}
public static List<WebSocketTest> getSvrSet() {
return svrSet;
}
public static void setSvrSet(List<WebSocketTest> svrSet) {
WebSocketTest.svrSet = svrSet;
}
}
四》pojo 文件
package com.wskj.app.pojo;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/svr1")
public class WebSocket {
// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
private static Set<WebSocket> socket = new HashSet<WebSocket>();
private Session session;
private String name;
/**
* 连接建立成功调用的方法
*
* @param session
* 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
socket.add(this); // 加入set中
onlineCount++; // 在线数加1
System.out.println("有新连接加入!当前在线人数为" + onlineCount);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
socket.remove(this); // 从set中删除
onlineCount--; // 在线数减1
System.out.println("有一连接关闭!当前在线人数为" + onlineCount);
}
/**
* 收到客户端消息后调用的方法
*
* @param message
* 客户端发送过来的消息
* @param session
* 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
// 群发消息
for (WebSocket item : socket) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session,Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
/*
* @OnMessage public void onMessage(String message, Session session) throws
* IOException, InterruptedException {
*
* // 打印出来客户端发来的消息 System.out.println("Received: " + message);
*
* // Send the first message to the client
* session.getAsyncRemote().sendText("这是第一条服务器端的消息");
*
*
* // Send 3 messages to the client every 5 seconds int sentMessages = 0;
* while(sentMessages < 3){ Thread.sleep(5000);
* session.getAsyncRemote().sendText("这是第二条服务器端的消息 "+sentMessages);
* sentMessages++; }
*
* // Send a final message to the client
* session.getAsyncRemote().sendText("这是最后一条服务器端的消息"); }
*/
}