原著地址:https://blog.csdn.net/qq_36899469/article/details/78477217
最近小编又犯愁了,项目需求做一个实时的在线客服,小编又是上网各处找办法,最后锁定了一项技术WebSocket,但是对于小编来说这项技术只是听说过,从来没使用过,网上找的各种代码不是只有前端就是只有后端,简直要把我弄疯了,时隔三日我找到了如上链接里的代码,属实帮助到了我~关于WebSocket的定义我就不说了,网上百度一堆堆的,直接整代码吧~
1.首先来个登录页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>跳转人工客服</title>
<script type="text/javascript" src="js/jquery.js"></script>
</head>
<body>
<form name="ff" action="login" method="post" >
用户名:<input name="username" /><br/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
2.来个登录方法(我这里用的springMVC框架,原著用的是servlet,如果用的是servlet技术的童鞋请参照原著)
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ZjrgznController {
//首页跳转,判断浏览器跳转对应页面
@RequestMapping(value="")
public String getindex(){
return "/login";
}
//登录人工客服
@RequestMapping(value="/login")
public String login(String username,HttpServletRequest request){
request.getSession().setAttribute("username", username);
return "/chat";
}
}
3.来个聊天界面(我是刚刚使用就到这里贴代码了,前端样式根据需要自己自行修改)
注:var url = "ws://localhost:8080/chatSocket?username=${sessionScope.username}",此处路径根据你的项目实际情况写,不要完全粘贴,否则聊天功能不好使
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
var ws;
var userName = ${sessionScope.username};
//通过URL请求服务端(chat为项目名称)
var url = "ws://localhost:8080/chatSocket?username=${sessionScope.username}";
//进入聊天页面就是一个通信管道
window.onload = function() {
if ('WebSocket' in window) {
ws = new WebSocket(url);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(url);
} else {
alert('WebSocket is not supported by this browser.');
return;
}
//监听服务器发送过来的所有信息
ws.onmessage = function(event) {
eval("var result=" + event.data);
//如果后台发过来的alert不为空就显示出来
if (result.alert != undefined) {
$("#content").append(result.alert + "<br/>");
}
//如果用户列表不为空就显示
if (result.names != undefined) {
//刷新用户列表之前清空一下列表,免得会重复,因为后台只是单纯的添加
$("#userList").html("");
$(result.names).each(function(){
$("#userList").append("<input type=checkbox value='"+this+"'/>"+ this + "<br/>");
});
}
//将用户名字和当前时间以及发送的信息显示在页面上
if (result.from != undefined) {
$("#content").append(result.from + " " + result.date + " 说:<br/>"+ result.sendMsg + "<br/>");
}
};
};
//将消息发送给后台服务器
function send() {
//拿到需要单聊的用户名
//alert("当前登录用户为"+userName);
var ss = $("#userList :checked");
//alert("群聊还是私聊"+ss.size());
var to = $('#userList :checked').val();
if (to == userName) {
alert("你不能给自己发送消息啊");
return;
}
//根据勾选的人数确定是群聊还是单聊
var value = $("#msg").val();
//alert("消息内容为"+value);
var object = null;
if (ss.size() == 0) {
object = {
msg : value,
type : 1, //1 广播 2单聊
};
} else {
object = {
to : to,
msg : value,
type : 2, //1 广播 2单聊
};
}
//将object转成json字符串发送给服务端
var json = JSON.stringify(object);
//alert("str="+json);
ws.send(json);
//消息发送后将消息栏清空
$("#msg").val("");
}
</script>
</head>
<body>
<h3>欢迎 ${sessionScope.username}使用本聊天系统!</h3>
<div id="content" style="border: 1px solid black; width: 400px; height: 300px; float: left; color: #7f3f00;"></div>
<div id="userList" style="border: 1px solid black; width: 120px; height: 300px; float: left; color: #00ff00;"></div>
<div style="clear: both;" style="color:#00ff00">
<input id="msg" />
<button onclick="send();">发送消息</button>
</div>
</body>
</html>
4.启动类(个人感觉这个类要不要都可以,看个人实际需要)
package util;
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
public class ServerConfig implements ServerApplicationConfig {
//扫描src下所有类@ServerEndPoint注解的类
@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scan) {
System.out.println("扫描到"+scan.size()+"个服务端程序");
return scan;
}
//获取所有以接口方式配置的webSocket类
@Override
public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> point) {
System.out.println("实现EndPoint接口的类数量:"+point.size());
return null;
}
}
5.搞个实体类(用来显示在线人数,也可以弄个数据库把人员名单和信息存储起来以便以后用,小编这里先没用数据库)
public class ContentVo {
private String to;
private String msg;
private Integer type;
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}
import java.util.List;
public class Message {
private String alert;
private List<String> names;
private String sendMsg;
private String from;
private String date;
public String getAlert() {
return alert;
}
public void setAlert(String alert) {
this.alert = alert;
}
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
public String getSendMsg() {
return sendMsg;
}
public void setSendMsg(String sendMsg) {
this.sendMsg = sendMsg;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Message() {
super();
}
}
6.接下来就要实现服务端程序逻辑啦
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import ContentVo;
import Message;
@ServerEndpoint("/chatSocket")
public class ChatSocket {
//定义一个全局变量集合sockets,用户存放每个登录用户的通信管道
private static Set<ChatSocket> sockets=new HashSet<ChatSocket>();
//定义一个全局变量Session,用于存放登录用户的用户名
private Session session;
//定义一个全局变量map,key为用户名,该用户对应的session为value
private static Map<String, Session> map=new HashMap<String, Session>();
//定义一个数组,用于存放所有的登录用户,显示在聊天页面的用户列表栏中
private static List<String>names=new ArrayList<String>();
private String username;
private Gson gson=new Gson();
@OnOpen
public void open(Session session){
this.session = session;
//将当前连接上的用户session信息全部存到scokets中
sockets.add(this);
//拿到URL路径后面所有的参数信息
String queryString = session.getQueryString();
System.out.println();
//截取=后面的参数信息(用户名),将参数信息赋值给全局的用户名
this.username = queryString.substring(queryString.indexOf("=")+1);
//每登录一个用户,就将该用户名存入到names数组中,用于刷新好友列表
names.add(this.username);
//将当前登录用户以及对应的session存入到map中
this.map.put(this.username, this.session);
System.out.println("用户"+this.username+"进入聊天室");
Message message = new Message();
message.setAlert("用户"+this.username+"进入聊天室");
//将当前所有登录用户存入到message中,用于广播发送到聊天页面
message.setNames(names);
//将聊天信息广播给所有通信管道(sockets)
broadcast(sockets, gson.toJson(message) );
}
@OnClose
public void close(Session session){
//移除退出登录用户的通信管道
sockets.remove(this);
//将用户名从names中剔除,用于刷新好友列表
names.remove(this.username);
Message message = new Message();
System.out.println("用户"+this.username+"退出聊天室");
message.setAlert(this.username+"退出当前聊天室!!!");
//刷新好友列表
message.setNames(names);
broadcast(sockets, gson.toJson(message));
}
@OnMessage
public void receive(Session session,String msg) throws IOException{
//将客户端消息转成json对象
ContentVo vo = gson.fromJson(msg, ContentVo.class);
//如果是群聊,就像消息广播给所有人
if(vo.getType()==1){
Message message = new Message();
message.setDate(new Date().toLocaleString());
message.setFrom(this.username);
message.setSendMsg(vo.getMsg());
broadcast(sockets, gson.toJson(message));
}else{
Message message = new Message();
message.setDate(new Date().toLocaleString());
message.setFrom(this.username);
message.setAlert(vo.getMsg());
message.setSendMsg("<font color=red>正在私聊你:</font>"+vo.getMsg());
String to = vo.getTo();
//根据单聊对象的名称拿到要单聊对象的Session
Session to_session = this.map.get(to);
//如果是单聊,就将消息发送给对方
to_session.getBasicRemote().sendText(gson.toJson(message));
}
}
public void broadcast(Set<ChatSocket>sockets ,String msg){
//遍历当前所有的连接管道,将通知信息发送给每一个管道
for(ChatSocket socket : sockets){
try {
//通过session发送信息
socket.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
效果图就不上了,各位把代码运行起来效果自然出现~