利用websocket实现群聊以及单聊
作者:互联网
利用websocket实现群聊以及单聊
在这里提供一下思路,正常情况下我们登陆进去之后就应该打开一个ws连接,以便和服务器进行通信,将打开的管道用一个set容器进行存储,并将用户名或者其他能唯一标示用户的字段作为key,把与之对应的管道作为value存储到一个map集合中。
那么怎么实现广播的方法呢?其实很简单,这需要对set容器中的每一个管道进行遍历并执sendText()方法,就可以将消息传递给了集合中每个管道(前提是在每个用户进行登陆时将用户存储到一个集合中)。
接下来首先实现群聊,通过jquery获得输入框的内容,然后通过onmessage()方法向后端传递消息,在调用广播方法就可以实现群聊了。
接下来就是单聊,单聊的实现原理就是得到被单聊的人的用户名,然后在map集合中的得到与之对应的管道,然后调用sendText()方法就可以将消息发送给对应的人了。
话不多说,直接上图上代码
项目结构
实现代码
DemoConfig.java
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
public class DemoConfig implements ServerApplicationConfig {
@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scan) {
// TODO Auto-generated method stub
System.out.println("config................"+scan.size());
//可以提供过滤作用
return scan;
}
@Override
public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> arg0) {
// TODO Auto-generated method stub
return null;
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!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>
</head>
<body>
<form action="LoginServlet">
姓名:<input id="username" name="username" />
<input type="submit" />
</form>
</body>
</html>
ChatRoom.jsp
<%@page import="java.io.PrintWriter"%>
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!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="jquery-1.4.2.min.js"></script>
<script type="text/javascript">
var username="${sessionScope.username}";
var ws;//一个ws对象就是一个管道
var target="ws://localhost:8080/web_war_exploded/chatSocket?username="+username;
window.onload=function(){
//登录进入ChatRoom就打开socket通道
if ('WebSocket' in window) {
ws = new WebSocket(target);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(target);
} else {
alert('WebSocket is not supported by this browser.');
return;
}
ws.onmessage=function(event){
eval("var msg="+event.data+";");
if(undefined!=msg.welcome)
$("#content").append(msg.welcome+"<br/>");
if(undefined!=msg.usernames){
$("#userList").html("");
$(msg.usernames).each(
function(){
$("#userList").append("<input type=checkbox value='"+this+"'/>"
+ this + "<br/>");
});
}
if(undefined!=content){
$("#content").append(msg.content+"<br/>");
console.info(msg);
}
}
}
function subSend() {
//判断是否选中
var ss=$("#userList :checked");
var val = $("#msg").val();
console.info(ss.size());
//如果未选中
var obj=null;
if(ss.size()==0){
var obj={
msg:val,
type:1 //1广播 2单聊
}
}else {
var to = $("#userList :checked").val();
obj={
to:to,
msg:val,
type:2 //1广播 2单聊
}
}
var str = JSON.stringify(obj);
/* $("msg").val("");
var obj={
to:to,
msg:val,
type:1 //1广播 2单聊
} */
ws.send(str);
}
</script>
</head>
<body>
<div id="container" style="border:1px solid black;width:400px;height:400px;float:left;">
<div id="content" style="height:350px;"></div>
</div>
<div style="border-top:1px solid black;width:400px;height:50px;">
<input id="msg" /><button onclick="subSend();">send</button>
</div>
<div id="userList" style="border:1px solid black;width:400px;height:400px;float:left;">
</div>
</body>
</html>
LoginServlet.java
package com.hys.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
request.getSession().setAttribute("username", username);
/*System.out.println(username);*/
response.sendRedirect("ChatRoom.jsp");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
ChatSocket.java
package com.hys.socket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;
import com.hys.vo.ContentVo;
import com.hys.vo.Message;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
@ServerEndpoint(value = "/chatSocket")
public class ChatSocket {
private String username;
private Session session;
private static Map<String, Session> map=new HashMap<String, Session>();/*将管道与用户名绑定*/
private static Set<ChatSocket> sockets=new HashSet<ChatSocket>();/*管道道的集合*/
private static List<String> names = new ArrayList<String>();/*用户的集合*/
private Gson gson = new Gson();
@OnOpen
public void open(Session session) {
//当前的websocket的session不是之前的session
//获取username
//将当前的管道加入到管道的集合中去
this.session = session;
this.sockets.add(this);
//将当前的username与session绑定
String queryname = session.getQueryString();
/*System.out.println(queryname);*/
username=queryname.split("=")[1];
this.names.add(username);
this.map.put(this.username, this.session);
/*System.out.println(username);*/
String msg = "欢迎"+this.username+"进入聊天室";
Message message=new Message();
message.setWelcome(msg);
message.setUsernames(this.names);
this.broadcast(sockets,message.toJson());
}
@OnClose
public void close(Session session) {
this.sockets.remove(this);
this.names.remove(this.username);
String msg = this.username+"离开聊天室";
Message message=new Message();
message.setWelcome(msg);
message.setUsernames(this.names);
broadcast(sockets,message.toJson());
}
// private static Gson gson=new Gson();
@OnMessage
public void onmessage(Session session,String json) {
ContentVo vo=gson.fromJson(json, ContentVo.class);
if(vo.getType()==1) {
//广播
Message message=new Message();
message.setContent(this.username, vo.getMsg());
this.broadcast(sockets,message.toJson());
}else {
//单聊
//单聊过程与广播类似,
/*分析前台传过来的消息的type如果是2的话
就在map(存放的是key是用户名,value是socket)中通过getTo来取得接收信息的socket
并通过to_session.getBasicRemote().sendText(gson.toJson(message))
将消息传递给前台*/
/*举个不太恰当的例子,我想将一个苹果(消息)放到小明的冰箱(小明的前端页面),
然后就我又不想动,我就想找小明
然后我就喊小明的名字,小明(相当于服务器)听到我喊他的名字(从map集合中找到对应的session)
然后小明就将苹果放入到了他的冰箱(对应的session调用sendText()方法传递消息)
放到冰箱里(前台)
* */
String to=vo.getTo();
Session to_session = this.map.get(to);
System.out.println(to);
System.out.println(to_session);
Message message=new Message();
message.setContent(this.username, vo.getMsg());
try {
to_session.getBasicRemote().sendText(gson.toJson(message));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//广播消息
public void broadcast(Set<ChatSocket>sockets ,String msg){
//遍历当前所有的连接管道,将通知信息发送给每一个管道
for(ChatSocket socket : sockets){
try {
//通过session发送信息
socket.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ContentVo.java
package com.hys.vo;
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;
}
}
Message.java
package com.hys.vo;
import java.util.Date;
import java.util.List;
import com.google.gson.Gson;
public class Message {
private String welcome;
private List<String> usernames;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public void setContent(String name,String msg) {
this.content = name+""+new Date().toLocaleString()+":<br/>"+msg+":<br/>";
}
public String getWelcome() {
return welcome;
}
public void setWelcome(String welcome) {
this.welcome = welcome;
}
public List<String> getUsernames() {
return usernames;
}
public void setUsernames(List<String> usernames) {
this.usernames = usernames;
}
public String toJson() {
return gson.toJson(this);
}
public static Gson gson=new Gson();
}
运行截图
##注意
如果使用eclipse的话,可以建立相应的目录结构将代码粘贴进去,导入jar包即可
标签:username,websocket,String,群聊,session,单聊,msg,import,public 来源: https://blog.csdn.net/qq_37793966/article/details/90522037