springboot webSocket实现群聊/单聊

springboot webSocket实现群聊/单聊

webSocket简介:
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

代码:
1.maven依赖:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        
        <!--下面两个事非必须的,我这里用thymeleaf管理前端页面-->
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        

2.WebSocket配置类,注入ServerEndpointExporter

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3.实现群聊或者单聊,其实就是要让某个固定的客户端收发(个人粗鄙理解,不知道对不对),所以新建个实体类,用来接收并判断发送机制

public class MessageSok {
    private int type;//单发/群发
    private String sender;//发送
    private String geter;//接收
    private String msg;//信息
    get/set方法
}

4.WebSocket服务(个人叫法)

@ServerEndpoint("/websocket/{name}")
@RestController
public class WebSocketServer {

    //存储客户端的连接对象,每个客户端连接都会产生一个连接对象
//    private static ConcurrentHashMap<String,WebSocketServer> map=new ConcurrentHashMap();
    private static CopyOnWriteArraySet<WebSocketServer> socketSet = new CopyOnWriteArraySet<WebSocketServer>();
    private static Map<String,Session> mapsok = new HashMap<String, Session>();
    //每个连接都会有自己的会话
    private Session session;
    private String name;
    @OnOpen
    public void open(@PathParam("name") String name, Session session){
        this.session=session;
        this.name=name;
        mapsok.put(session.getId(),session);
        socketSet.add(this);
        System.out.println(session.getId());
        System.out.println("有新连接加入:"+name+",当前在线人数为" + socketSet.size());
        this.session.getAsyncRemote().sendText("提示:"+name+"成功连接上WebSocket(其频道号:"+session.getId()+")当前在线人数为:"+socketSet.size());
//        System.out.println(name+"连接服务器成功");
//        System.out.println("客户端连接个数:"+getConnetNum());


    }
    @OnClose
    public void close(){
        socketSet.remove(name);
        System.out.println(name+"断开了服务器连接");
    }
    @OnError
    public void error(Throwable error){
        error.printStackTrace();
        System.out.println(name+"出现了异常");
    }
    @OnMessage
    public void getMessage(String message) throws IOException {
        System.out.println("来自客户端的消息-->"+name+": " + message);

        //从客户端传过来的数据是json数据,所以这里使用jackson进行转换为SocketMsg对象,
        // 然后通过socketMsg的type进行判断是单聊还是群聊,进行相应的处理:
        //这里借鉴了https://blog.csdn.net/qq_41603102/article/details/82492040这位大神的博客
        ObjectMapper objectMapper = new ObjectMapper();
        MessageSok messageSok;

        try {
            messageSok = objectMapper.readValue(message, MessageSok.class);
            if(messageSok.getType() == 1){
                //单聊.需要找到发送者和接受者.

                messageSok.setSender(session.getId());//发送者.
                Session sendSession = mapsok.get(messageSok.getSender());
                Session getSession = mapsok.get(messageSok.getGeter());
                //发送给接受者.
                if(getSession != null){
                    //收者发送,个人觉得自己就不用收了
                    getSession.getAsyncRemote().sendText(name+":"+messageSok.getMsg());
                }else{
                    //发送给发送者.
                    sendSession.getAsyncRemote().sendText("系统消息:对方不在线或者您输入的频道号不对");
        }
        }else{
        //群发消息
        broadcast(name+": "+messageSok.getMsg());
        }

        } catch (JsonParseException e) {
        e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void broadcast(String message) {
        for (WebSocketServer item : socketSet) {
            //this.session.getBasicRemote().sendText(message);
            //这里是群发,但是给自己发是不对的,所以如果是本身就不发
            if(!item.session.getId().equals(session.getId())){
                item.session.getAsyncRemote().sendText(message);//异步发送消息.
            }

        }
    }

}

5.html页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>老年唠嗑室</title>
    <style type="text/css">
        .box{
            width:300px;
            height:500px;
            border:1px solid blue;
            margin:0 auto;
        }
        .inTer{
            width:280px;
            height:280px;
            border:1px solid deeppink;
            margin:0 auto;
            margin-top:10px;
            overflow-y:auto;
        }
        textarea{
            display:block;
            width: 276px;
            height:65px;
            margin:0 auto;
            margin-top:5px;
        }
        #btn{
            display:block;
            float:right;
            margin-right:10px;
            margin-top:5px;
        }
        p{
            display:inline-block;
            border-radius:5px;
            background:#dcdcdc;
            font-size:12px;
            padding:5px 5px;
            margin:5px 0;
            margin-left:5px;
            max-width:140px;
            word-wrap: break-word;
        }
    </style>
</head>
<body>
<div class="box">
    用户名: <input type="text" name="name" id="usname">
    频道号:<input id="geter" type="text" />
    <button onclick="conectWebSocket()">连接WebSocket</button>
    <div class="inTer" id="father">

    </div>
    <textarea style="resize: none;" id="txt">
 </textarea>
    <input type="button" id="btn" value="发送" />
</div>
</body>
</html>
<script>

    var nickname=null;
    var btn = document.getElementById("btn");
    var txt = document.getElementById("txt");
    var father = document.getElementById("father")
    var p = document.getElementsByTagName("p");
    var websocket=null;
    function conectWebSocket() {
        nickname=document.getElementById("usname").value;
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            websocket = new WebSocket("ws:3w19699285.goho.co/websocket/"+nickname);
        } else {
            alert("浏览器不支持");
        }

        // if('WebSocket' in window){
        //     websocket=new WebSocket("ws:192.168.101.103:8082/websocket/"+name);
        // }else {
        //
        //
        // }
        websocket.onopen = function () {
            console.log("webscoket已经连接成功");
            addMessage("webscoket已经连接成功");

        };
        websocket.onclose = function () {
            console.log("webscoket连接失败");
            addMessage("webscoket连接失败");
        };
        websocket.onmessage = function (event) {
            addMessage(event.data);
        };
        websocket.onerror = function () {
            console.log("webscoket连接失败");
            addMessage("webscoket连接失败");
        };
    }


    btn.onclick=function(){
        if(txt.value==""){
            alert("请勿发送空内容");
        }
        else{
            var son = document.createElement("p");
            son.style.backgroundColor="yellowgreen";
            son.style.clear="both";
            son.style.float="right";
            son.style.marginRight="5px";
            son.innerText=txt.value;
            // websocket.send(nickname+":"+txt.value);
            father.appendChild(son);
            send(txt.value);
            txt.value="";
            son.scrollIntoView();
        }

    }
    document.onkeydown=function(evt){
        var e = evt || event;
        e.keyCode=e.which=e.charCode;
        if(e.keyCode==13 || e.keyCode==10){
            if(txt.value==""){
                alert("请勿发送空内容");
            }
            else{
                var son = document.createElement("p");
                son.style.backgroundColor="yellowgreen";
                son.style.clear="both";
                son.style.float="right";
                son.style.marginRight="5px";
                son.innerText=txt.value;
                // websocket.send(nickname+":"+txt.value);
                send(txt.value);
                father.appendChild(son);
                txt.value="";
                son.scrollIntoView();
            }
        }
    }

    function addMessage(message) {
        var son = document.createElement("p");
        son.style.backgroundColor="yellowgreen";
        son.style.clear="both";
        son.style.float="left";
        son.style.marginRight="5px";
        son.innerText=message;
        father.appendChild(son);
        son.scrollIntoView();
    }

    function send(messagetxt) {
        //获取输入的文本信息进行发送
        var message = messagetxt;
        var geter = document.getElementById('geter').value;
        var messageSoc = {msg:message,geter:geter};
        if(geter == ''){
            //群聊.
            messageSoc.type = 0;
        }else{
            //单聊.
            messageSoc.type = 1;
        }
        websocket.send(JSON.stringify(messageSoc));
    }

</script>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里是先连接,然后试试群发
楷哥发,除了楷哥其他人都接收
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

然后私发:
阳仔问候楷哥,楷哥回应,需要给对应的频道号,这里是sessionid,然后结果,东哥是没有消息的:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
结语
其实实现websocket的方式还有很多,比如还有订阅主题什么的,还有通过security方式管理用户,大家可以做个了结

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值