SpringBoot--使用socket搭建聊天室

1、添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

2、添加工具类

package com.example.demo.utils;

import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public final class WebSocketUtils {
    /**
     * 模拟存储websocket session
     */
    public static final Map<String, Session> LIVING_SESSION_CACHE = new ConcurrentHashMap();

    public static void sendMessageAll(String message){
        LIVING_SESSION_CACHE.forEach((sessionId,session) -> sendMessage(session,message));
    }

    /**
     * 发送给指定用户
     * @param session
     * @param message
     */
    public static void sendMessage(Session session, String message){
        if(session == null){
            return;
        }
        final RemoteEndpoint.Basic basic = session.getBasicRemote();
        if(basic == null){
            return;
        }
        try {
            basic.sendText(message);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3、添加服务站点

主要使用注解如下:

  @ServerEndpoint:聊天室访问地址

  @OnOpen: 建立 WebSocket 连接时触发

  @OnMessage:客户端监听服务端事件,当服务端向客户端推送消息时会被监听到

  @OnClose:关闭 WebSocket 连接时触发

  @OnError:发生错误时触发

  @GetMapping:接收消息请求地址

  其中@ServerEndpoint 中的内容就是 WebSocket 协议的地址,其实仔细看会发现与 @RequestMapping 也是异曲同工的… HTTP 协议:http://localhost:8080/path WebSocket 协议:ws://localhost:8080/path

package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import static com.example.demo.utils.WebSocketUtils.LIVING_SESSION_CACHE;
import static com.example.demo.utils.WebSocketUtils.sendMessage;
import static com.example.demo.utils.WebSocketUtils.sendMessageAll;

@RestController
@ServerEndpoint("/chat-room/{username}")
public class SocketController {
    private static final Logger log = LoggerFactory.getLogger(SocketController.class);

    @OnOpen
    public void openSession(@PathParam("username") String name, Session session){
        LIVING_SESSION_CACHE.put(name,session);
        String message = "欢迎用户["+ name + "]来到朦胧的夜聊天室";
        log.info(message);
        sendMessageAll(message);
    }

    @OnMessage
    public void onMessage(@PathParam("username") String username, String message){
        log.info(message);
        sendMessageAll("用户["+username+"]:" + message);
    }

    @OnClose
    public void onClose(@PathParam("username") String username, Session session){
        //移除session
        LIVING_SESSION_CACHE.remove(username);
        //通知他人
        sendMessageAll("用户["+username+"]已经离开朦胧的夜聊天室");
        try {
            session.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @OnError
    public void onError(Session session,Throwable throwable){
        try {
            session.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }

    @GetMapping("/chat-room/{sender}/to/{receive}")
    public void onMessage(@PathVariable("sender") String sender,@PathVariable("receive") String receive, String message){
        sendMessage(LIVING_SESSION_CACHE.get(receive),"["+sender+"]:"+message);
    }
}

4、添加聊天室html

  此处注意一点,要添加引入jquery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>battcn websocket</title>
    <script src="/jquery-3.4.1.min.js" ></script>
</head>
<body>

<label for="message_content">聊&nbsp;&nbsp;天&nbsp;&nbsp;室&nbsp;</label><textarea id="message_content" readonly="readonly" cols="57" rows="10">

</textarea>

<br/>


<label for="in_user_name">用户姓名 &nbsp;</label><input id="in_user_name" value=""/>
<button id="btn_join">加入聊天室</button>
<button id="btn_exit">离开聊天室</button>

<br/><br/>

<label for="in_room_msg">群发消息 &nbsp;</label><input id="in_room_msg" value=""/>
<button id="btn_send_all">发送消息</button>


<br/><br/><br/>

好友聊天
<br/>
<label for="in_sender">发送者 &nbsp;</label><input id="in_sender" value=""/><br/>
<label for="in_receive">接受者 &nbsp;</label><input id="in_receive" value=""/><br/>
<label for="in_point_message">消息体 &nbsp;</label><input id="in_point_message" value=""/><button id="btn_send_point">发送消息</button>

</body>

<script type="text/javascript">
    $(document).ready(function(){
        var urlPrefix ='ws://localhost:8080/chat-room/';
        var ws = null;
        $('#btn_join').click(function(){
            var username = $('#in_user_name').val();
            var url = urlPrefix + username;
            ws = new WebSocket(url);
            ws.onopen = function () {
                console.log("建立 websocket 连接...");
            };
            ws.onmessage = function(event){
                //服务端发送的消息
                $('#message_content').append(event.data+'\n');
            };
            ws.onclose = function(){
                $('#message_content').append('用户['+username+'] 已经离开聊天室!');
                console.log("关闭 websocket 连接...");
            }
        });
        //客户端发送消息到服务器
        $('#btn_send_all').click(function(){
            var msg = $('#in_room_msg').val();
            if(ws){
                ws.send(msg);
            }
        });
        // 退出聊天室
        $('#btn_exit').click(function(){
            if(ws){
                ws.close();
            }
        });

        $("#btn_send_point").click(function() {
            var sender = $("#in_sender").val();
            var receive = $("#in_receive").val();
            var message = $("#in_point_message").val();
            $.get("/chat-room/"+sender+"/to/"+receive+"?message="+message,function() {
                alert("发送成功...")
            })
        })

    })
</script>

</html>

5、主函数

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

6、添加入口方法

    @GetMapping(value ="/sockethtml")
    public String sockethtml(){
            return "lliaotianshi";
    }

7、测试

http://localhost:8080/test/sockethtml

 

posted @ 2019-10-24 21:26  李聪龙  阅读(1269)  评论(3编辑  收藏  举报