Java SpringBoot整合WebSocket 实现实时聊天,消息指定推送

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/mrwangyifei/article/details/102755100

Java SpringBoot整合WebSocket 实现实时聊天,消息指定推送

代码中都是有相关的注释

首先需要配置 WebSocket 的配置类,进行相关信息的配置。

package com.njtswl.springboot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket //启用websocket
public class WebSocketConfig implements WebSocketConfigurer{
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry.addHandler(getHandler(),"/websocket/*").addInterceptors(new ChatIntercepter()).setAllowedOrigins("*");   
//一开始没有在放上拦截器的后面加上 setAllowedOrigins("*") 打开链接直接链接超时 403
    }

    @Bean
    public TextMessageHandler getHandler(){
        return new TextMessageHandler();
    }
}

接下来需要配置WebSocket 的拦截器

package com.njtswl.springboot.config;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.Map;
/**
 * websocket握手的拦截器,检查握手请求和响应,对websockethandler传递属性,用于区别websocket
 * */
public class ChatIntercepter extends HttpSessionHandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        //我们为了区别链接之前是不是通过用户名来区别是谁的,此处我们还是一样的逻辑通过名字区分
        //现在我们获取到用户的名字,因为我们的地址是使用的rest风格,定义的地址是最后以为是名字,所以此处我们只需要找到请求地址拿到最后一位就行
        System.out.println("握手之前");
        String url = request.getURI().toString();
        //如果此处 url.lastIndexOf 后面没有 +1 则会带上 /
        String name = url.substring(url.lastIndexOf("/") + 1);
        //给当前链接设置名字
        attributes.put("name",name);//建议将name抽取为静态常量
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, @Nullable Exception ex) {

        System.out.println("握手之后");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

配置建立链接时的处理,以及 WebSocket 的信息发送

package com.njtswl.springboot.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class TextMessageHandler extends TextWebSocketHandler {

    //用于存放所有建立链接的对象
    private Map<String,WebSocketSession> allClients = new HashMap<>();


    /**
     * 处理文本消息
     * session   当前发送消息的用户的链接
     * message   发送的消息是什么
     * */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        JSONObject jsonObject = JSON.parseObject(new String(message.asBytes()));
        String to = jsonObject.getString("toUser");  //找到接收者
        String toMessage = jsonObject.getString("toMessage"); //获取到发送的内容
        String  fromUser = (String) session.getAttributes().get("name");  //获取到当前发送消息的用户姓名
        String content = "收到来自"+fromUser+"的消息,内容是:"+toMessage; //拼接的字符串
        TextMessage toTextMessage = new TextMessage(content);//创建消息对象
        sendMessage(to,toTextMessage);  //一个封装的方法,进行点对点的发送数据
    }

	//发送消息的封装方法
    public void sendMessage(String toUser,TextMessage message){
        //获取到对方的链接
        WebSocketSession session = allClients.get(toUser);//获取到对方的链接
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(message);//发送消息
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 当链接建立的时候调用
     * */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String name = (String) session.getAttributes().get("name");//获取到拦截器中设置的name
        if (name != null) {
            allClients.put(name,session);//保存当前用户和链接的关系
        }
    }

    /**
     * 当链接关闭的时候
     * 这里没有做相关的代码处理
     * */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
    }
}

最后是客户端的代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
	</head>
	<script type="text/javascript">
		var websocket = null;
		function connection(){
			var username = document.getElementById("name").value;
			if('WebSocket' in window){//支持不支持websocket
				websocket = new WebSocket("ws://localhost:8080/websocket/"+username);
			}else{
				alert('什么破电脑不支持WebSocket,砸了吧');
			}
			
			websocket.onopen = function(){
				document.getElementById("message").innerHTML = "建立链接了";
			}
			websocket.onmessage = function(event){
				var data = event.data;
				document.getElementById("message").innerHTML = data;
			}
			websocket.onerror = function(){
				document.getElementById("message").innerHTML = "出现异常了";
			}
			websocket.onclose = function(){
				document.getElementById("message").innerHTML = "链接关闭了";
			}
			window.onbeforeunload = function(){ //当浏览器的页面窗口关闭的时候,此处应该关闭链接防止服务器出现异常
				if(websocket!=null){
					websocket.close();
				}
			}
			
			
		}
		
		function sendMessage(){
			//获取到发送给谁
			var toUser = document.getElementById("toUser").value;
			//获取到发送的内容
			var toMessage = document.getElementById("toMessage").value;
			if(websocket!=null){
				var message = '{"toUser":"'+toUser+'","toMessage":"'+toMessage+'"}';
				websocket.send(message);
			}
		}
	</script>
	<body>
		<input type="text" name="name" id="name"/><button onclick="connection()">链接</button><br/>
		接收者名字:<input type="text" name="toUser" id="toUser"/><br/>
		内容:<input type="text" name="toMessage" id="toMessage"/><button type="button" onclick="sendMessage()">发送</button>
		<span id="message"></span>
	</body>
</html>

尽量边理解边敲,思考程序的执行顺序,在了解顺序之后,再思考每一步是怎么做的,了解到每一步怎么做的,再思考怎么实现的,最后为什么这样实现。
最后希望我这篇学习的文档能够帮助到你们。

这边加上用到的依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-websocket -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-websocket</artifactId>
			<version>5.2.0.RELEASE</version>
		</dependency>

猜你喜欢

转载自blog.csdn.net/mrwangyifei/article/details/102755100