Java-WebSocket实现前后端即时通讯(聊天室即时通讯)

介绍

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信–允许服务器主动发送信息给客户端。

前端代码

实现连接后端,接收发送消息(私发,群发)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CharBox</title>
</head>
<body>
    <div id="connection">
        <!--建立连接-->
        <input type="text" name="username">
        <button id="connBtn">Connection</button>
    </div>
    <div id="sendAll">
        <!--群发消息-->
        <input id="allMsg" type="text" name="msg">
        <button id="allBtn">SendAll</button>
    </div>
    <div id="sendTo">
        <!--私发消息-->
        <input id="toMsg" type="text" name="lineMsg">
        <select id="userList">
            <option>请选择</option>
        </select>
        <button id="toBtn">SendTo</button>
    </div>
    <!--消息展示-->
	<div class="content">
		<div class="name"></div>
		<div class="info"></div>
	</div>
	<!--引入JQuery-->
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
    <!--实现WebSocket-->
	<script type="text/javascript">
		var webSocket = null
        var userList = []
		var url = "ws://localhost:8080/char/"

		// 寻找服务器建立连接
		$("#connBtn").on('click', function(){
			// 获取要连接的用户
			var username = $("input[name='username']").val()
			// 添加私人
			userList.push(username)
			$("#userList").empty()
			$.each(userList, function(index, item){
				$("#userList").append("<option>"+item+"</option>")
			})
			if ("WebSocket" in window) {
				// 浏览器支持WebSocket
				var ws = new WebSocket(url+username)
				console.log("连接创建成功")
				webSocket = ws
				// 服务端的返回
				webSocket.onmessage = function(cvt) {
					var rec_msg = cvt.data    // Json格式
					var jsonMsg = JSON.parse(rec_msg)
					var msg = jsonMsg.msg
					switch (msg) {
						case "sendAll":
							sendAll(jsonMsg);
							break;
						case "sendTo":
							sendTo(jsonMsg);
							break;
						case "onLineUsers":
							onLineUsers(jsonMsg);
							break;
					}
					
				}
			} else {
				// 浏览器不支持WebSocket
				console.log("浏览器不支持WebSocket")
			}
		})
		
		 var content = $(".content");
		
		function sendAll(jsonMsg) {
			// 接受到服务器的群发消息,把消息显示到聊天窗口
			var jsonObj = JSON.parse(jsonMsg.data);
			console.log(jsonObj)
			var infoContent = jsonObj.info;
			var infoFromUser = jsonObj.fromUser;
			var infoTime = jsonObj.time;
			
			var contentDiv = content.clone();//又多了一个div class=info
			
			contentDiv.find(".name").text(infoFromUser+" "+infoTime);
			contentDiv.find(".info").text(infoContent);
			$(".content").parent().append(contentDiv);
		}
		function sendTo(jsonMsg) {
			var jsonObj = JSON.parse(jsonMsg.data)
			console.log(jsonObj)
			var infoContent = jsonObj.info;
			var infoFromUser = jsonObj.fromUser;
			var infoTime = jsonObj.time;
			
			var contentDiv = content.clone();//又多了一个div class=info
			
			contentDiv.find(".name").text(infoFromUser+" "+infoTime);
			contentDiv.find(".info").text(infoContent);
			// 再添加一个DIV
			$(".content").parent().append(contentDiv);
		}
		function onLineUsers(jsonMsg) {
			var users = JSON.parse(jsonMsg.data);
			
			$("#userList").empty();
			
			$.each(users, function(index, item){
				$("#userList").append("<option>"+item+"</option>")
			})
		}
		// 群发消息
		$("#allBtn").on('click', function(){
			var info = $("input[name='msg']").val()
			var sendMsg = {
				"msg": "sendAll",
				"data": info
			}
			webSocket.send(JSON.stringify(sendMsg))
			console.log("消息发送")
		})
		// 私发消息
		$("#toBtn").on('click', function(){
			var info = $("input[name='lineMsg']").val()
			var toUser = $("#userList").val()
			var sendMsg = {
				"msg": "sendTo",
				"data": {
					"toUser": toUser,
					"info": info
				}
			}
			webSocket.send(JSON.stringify(sendMsg))
			console.log("消息私发")
		})
	</script>
</body>
</html>

后端代码

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

//连接地址
@ServerEndpoint("/char/{username}")
public class CharServer2 {
    // 群聊服务器

    private Session session;  // 客户端连接 产生多个会话 多个session
    private String username;   //

    // 通过类变量 存储通话对象
    private static Map<String, CharServer2> clients = new ConcurrentHashMap<String, CharServer2>();   // 存储会话对象
    private static int onlineCount = 0;  // 会话个数

    private Set<String> clientsName = null;

    @OnOpen
    public void onOpen(@PathParam(value = "username")String username, Session session) throws IOException {
        this.session = session;
        System.out.println("建立连接:" + username);
        this.username = username;

        // 有客户端连接 将客户端会话对象存储到clients对象里
        clients.put(username, this);
        // 会话个数添加
        addOnlineCount();

        // 更新用户列表 将clients对象里的用户转发到说有客户端去渲染展示
        sendUserList();
    }

    public static synchronized void addOnlineCount() {
        // 会话数增加
        CharServer2.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        // 会话数减少
        CharServer2.onlineCount--;
    }

    // 发送用户列表
    public void sendUserList() {
        Set<String> userSet = this.clients.keySet();
        Commond sendMsg = new Commond();
        sendMsg.setMsg("onLineUsers");
        sendMsg.setData(JSON.toJSONString(userSet));
        // 循环给每个对话发送会话用户列表
        for (CharServer2 item: clients.values()) {
            item.session.getAsyncRemote().sendText(JSON.toJSONString(sendMsg));
        }
    }

    @OnMessage
    // 转发信息
    public void onMessage(@PathParam(value="username")String username,String message) throws IOException {
        // 解析message 转成JSON格式
        System.out.println(message);
        JSONObject jsonTo = JSON.parseObject(message);
        // 获取msg的值
        String msg = jsonTo.getString("msg");
        // 获取data的值
        String data = jsonTo.getString("data");
        if("sendAll".equals(msg)){
            // 群发
            sendMessageAll(data);
        }else if("sendTo".equals(msg)){
            // 私发
            sendMessageTo(data);
        }
    }
    // 私发
    public void sendMessageTo(String data) throws IOException {
        // 创建返回信息对象
        Commond sendMsg = new Commond();
        // 设置群发或者私发
        sendMsg.setMsg("sendTo");
        // 将传来的数据转为JSON格式
        JSONObject jsonObj = JSON.parseObject(data);
        // 创建JSON对象
        JSONObject obj = new JSONObject();
        // 添加私发的信息
        obj.put("info",jsonObj.getString("info"));
        // 添加发送者
        obj.put("fromUser",this.username);
        // 添加发送时间
        obj.put("time",new Date());
        // JSON对象设置为Commond的data
        sendMsg.setData(JSON.toJSONString(obj));
        // 私发信息 对话服务器存储的会话去做循环 找到要发送的人的会话 发送信息过去
        for (CharServer2 item : clients.values()) {
            // 如果会话对象中存在要发送信息的用户toUser 则发送信息
            if (item.username.equals(jsonObj.getString("toUser")) )
                item.session.getAsyncRemote().sendText(JSON.toJSONString(sendMsg));
        }
    }
    // 群发
    public void sendMessageAll(String message) throws IOException {
        // 创建会话对象
        Commond sendMsg = new Commond();
        // 设置群发或者私发
        sendMsg.setMsg("sendAll");
        // 创建JSON对象
        JSONObject obj = new JSONObject();
        // 设置相关信息
        obj.put("info",message);
        obj.put("fromUser",this.username);
        obj.put("time",new Date());
        sendMsg.setData(JSON.toJSONString(obj));
        // 循环发送信息给会话里存在的对象
        for (CharServer2 item : clients.values()) {
            item.session.getAsyncRemote().sendText(JSON.toJSONString(sendMsg));
        }
    }

    @OnClose
    public void onClose(@PathParam(value="username")String username){
        System.out.println("连接下线");
        // 移除下线的用户
        clients.remove(username);
        // 在线会话数减一
        subOnlineCount();
    }

    @OnError
    public void onError(Throwable t){
        System.out.println("连接错误");
    }
}


// 返回数据对象
class Commond{
    String code;  // 码
    String msg;   // 验证信息
    String data;  // 返回信息

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public Commond(String code, String msg, String data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Commond() {
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值