springboot整合WebSocket,实现聊天室功能!

springboot整合WebSocket,实现聊天室功能!
一、增加WebSocket依赖

<!-- springboot整合WebSocket进行全双工通信(1) -->
<!-- websocket相关依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 前端库,使用jar包的形式对前端库进行统一管理,使用webjar添加到项目中的前端库,在springboot项目中已经默认添加了静态资源过滤,因此可以直接使用 -->
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>sockjs-client</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>stomp-websocket</artifactId>
    <version>2.3.3</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1</version>
</dependency>

二、定义配置类,实现WebSocketMessageBrokerConfigurer接口,设定消息代理的前缀及支持sockjs的代码

package com.steno.propertiestest.common;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * springboot整合WebSocket进行全双工通信(2)
 * 自定义类实现WebSocketMessageBrokerConfigurer接口,实现特定方法
 */
@Configuration  //定义配置类
@EnableWebSocketMessageBroker   //开启WebSocket消息代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * @param registry 消息代理注册
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        /*
         * 设置消息代理的前缀,即:如果消息的前缀是"/topic"就会将消息转发给消息代理(broker),
         * 再由消息代理降消息广播给当前连接的客户端
         */
        registry.enableSimpleBroker("/topic");
        /*
         * 配置一个或多个前缀,通过这些前缀过滤出需要被注解方法处理的消息!
         * 如:前缀为"/app"的destionation(目的地)可以通过@MessageMapping注解的方法处理,
         *     而其他destionnation(如"/topic"、"/queue")将被直接交给broker(消息代理)处理。
         */
        registry.setApplicationDestinationPrefixes("/app");
    }

    /**
     * @param registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        /*
         * 定义一个前缀为"/chat"的endPoint(终点),并开启sockjs支持,sockjs可以解决浏览器对WebSocket的兼容新问题,
         * 客户端将通过这里配置的url来建立WebSocket连接。
         */
        registry.addEndpoint("/chat").withSockJS();
    }
}

三、定义Controller实现页面跳转和消息接收后处理的功能

package com.steno.propertiestest.controller;

import com.steno.propertiestest.vo.WebSocketMessage;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Date;
import java.util.UUID;

/**
 * springboot整合WebSocket进行全双工通信(4)
 * 处理接收到的消息类
 */
@Controller
public class WebSocketHandReceivedMesController {

    /**
     * 由于项目集成了Shiro安全验证,因此登录后做跳转
     * @return
     */
    @GetMapping("/getWebSocketTestPage")
    public ModelAndView getWebSocketTestPage(){
        return new ModelAndView("chat");
    }

    /**
     * 接收"/app/handleMessage"路径的请求发送来的消息,并对消息进行手动处理后,
     * 再把消息发送到SendTo定义的路径上,而SendTo路径是一个"/topic"的路径,因此
     * 该消息将被交给broker(消息代理),再由borker进行广播。
     * @param message
     * @return
     */
    @MessageMapping("/handleMessage")
    @SendTo("/topic/handleMessages")
    public WebSocketMessage handleMessage(WebSocketMessage message){
        //服务器端对接收到的消息的额外处理
        message.setMessageid(UUID.randomUUID().toString());
        message.setCreatedate(new Date());
        return message;
    }

}

四、新建消息聊天内容输入页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>springboot整合WebSocket进行全双工通信(5)---群聊功能页面展示</title>
    <!-- 引入外部的JS库,该JS库是从pom.xml文件中通过依赖加入捡来的 -->
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <!-- 因此自定义的JS,实现Stomp.js的socket连接设定 -->
    <script src="/js/chat.js"></script>
</head>
<body>
    <div>
        <label for="name">请输入用户名:</label>
        <input type="text" id="name" placeholder="用户名">
    </div>
    <div>
        <button id="connect" type="button">连接</button>
        <button id="disconnect" type="button" disabled="disabled">断开连接</button>
    </div>
    <div id="chat" style="display:none">
        <div>
            <label for="name">请输入聊天内容:</label>
            <input type="text" id="content" placeholder="聊天内容">
        </div>
        <button id="send" type="button">发送</button>
        <div id="greetings">
            <div id="conversation" style="dispaly:none">群聊进行中....</div>
        </div>
    </div>
</body>
</html>

五、前端JS使用Stomp进行websocket连接和消息内容获取

var stompClient = null;
function setConnected(connected){
    $("#connect").prop("disabled", connected);
    $("#disconnect").prop("disabled", !connected);
    if(connected){
        $("#conversation").show();
        $("#chat").show();
    }else{
        $("#conversation").hide();
        $("#chat").hide();
    }
    $("#greetings").html("");
}

/**
 * 建立一个WebSocket连接,在建立连接时,用户必须先输入用户名,然后才可以建立连接!
 */
function connect(){
    if(!$("#name").val()){
        return;
    }
    //使用SockJS建立连接
    var socket = new SockJS('/chat');
    //创建一个Stomp实例发起连接请求,在连接成功的回调方法中,执行特定方法处理
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function(frame){
        //页面设置
        setConnected(true);
        //调用subscribe方法订阅服务端发送回来的消息,并将服务端发送来的消息展示出来
        stompClient.subscribe('/topic/handleMessages', function(result){
            //展示消息
            showGreeting(JSON.parse(result.body));
        });
    });
}

/**
 * 发送用户名和消息内容给服务器端处理
 */
function sendName(){
    stompClient.send("/app/handleMessage", {}, JSON.stringify({'name' : $("#name").val(), 'content' : $("#content").val()}));
}

function showGreeting(message){
    $("#greetings").append("
" +"

消息名称:"+message.name+"
"
+" 消息内容:"+message.content+"
"
+" 消息创建时间:"+message.createdate+"
"
+" 消息的id:"+message.messageid+"

"
+"
--------------------华丽的分割线---------------------------
"
); } /** * 断开一个WebSocket连接 */ function disconnect(){ if(stompClient != null){ stompClient.disconnect(); } setConnected(false); } $(document).ready(function(){ $("#connect").click(function(){ connect() }); $("#disconnect").click(function(){ disconnect(); }); $("#send").click(function(){ sendName(); }); });

六、浏览器访问测试
(1)Chrome浏览器访问:
http://localhost:8081/getWebSocketTestPage
springboot整合WebSocket,实现聊天室功能!_第1张图片
(2)其他浏览器访问:
springboot整合WebSocket,实现聊天室功能!_第2张图片
注意:
访问页面时注意websocket连接,其中ws对应HTTP,wss对应HTTPS,请求头中有2个特殊字段,Connection: upgrade表示客户端想要对协议进行升级;Upgrade: websocket表示客户端想要将请求协议升为websocket协议,这两个字段共同告诉服务器要将连接升级为websocket这样一种全双工协议,如果服务器端同意协议升级,那么在握手完成之后,文本消息和其他二进制消息就可以同时在两个方向上进行发送,而不需要关闭和重建连接。此时客户端和服务端是对等的,可以互相向对方主动发送消息。
springboot整合WebSocket,实现聊天室功能!_第3张图片
(3)不同浏览器输入不同的用户名,用于区分不同人发送的消息
可以看到:在左侧的浏览器点击发送消息后,右侧的浏览器也接收到消息并显示内容了!
springboot整合WebSocket,实现聊天室功能!_第4张图片
在右侧的浏览器点击发送消息后,左侧的浏览器也接收到消息并显示内容了!
springboot整合WebSocket,实现聊天室功能!_第5张图片
七、浏览器控制台详细输出:
springboot整合WebSocket,实现聊天室功能!_第6张图片

Opening Web Socket...
stomp.min.js:8 Web Socket Opened...
stomp.min.js:8 >>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,1000
------------------------------------------------------------------------
<<< CONNECTED
version:1.1
heart-beat:0,0
user-name:admin
------------------------------------------------------------------------
>>> SUBSCRIBE
id:sub-0
destination:/topic/handleMessages
------------------------------------------------------------------------
>>> SEND
destination:/app/handleMessage
content-length:54

{"name":"小哥哥","content":"小姐姐你好啊!"}
------------------------------------------------------------------------
<<< MESSAGE
destination:/topic/handleMessages
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:qls3311i-0
content-length:149

{"messageid":"6e8e8b2c-28a3-4b89-a8fc-0c36a06a5e8b","name":"小哥哥","content":"小姐姐你好啊!","createdate":"2020-05-27T09:32:28.589+0000"}
------------------------------------------------------------------------
<<< MESSAGE
destination:/topic/handleMessages
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:qls3311i-2
content-length:146

{"messageid":"f496dd16-a8f6-4388-be4c-0f3c57a8d469","name":"小姐姐","content":"小哥哥好啊!","createdate":"2020-05-27T09:34:04.164+0000"}

你可能感兴趣的:(springboot,websocket,websocket,spring,boot)