SpringBoot+webSocket项目私信聊天功能实现

webSocket

        什么是ws?

         WS(WebSocket)是一种网络通信协议,它提供了在客户端和服务器之间进行双向、实时通信的能力。相比于传统的HTTP协议,WebSocket具有更低的延迟和更高的效率。

传统的HTTP协议是一种无状态的协议,每次通信都需要客户端发起请求,服务器响应后关闭连接,因此无法实现实时的双向通信。而WebSocket协议则在初始握手阶段首先通过HTTP协议建立连接,然后升级为双向通信的WebSocket连接。一旦建立了WebSocket连接,客户端和服务器就可以通过该连接进行实时的数据交换,而无需每次都重新建立连接。

WebSocket协议使用基于帧的消息传递机制,允许客户端和服务器以消息的形式进行通信。客户端可以发送消息给服务器,服务器也可以主动推送消息给客户端,实现了真正的双向通信。这种实时通信的特性使得WebSocket在许多场景下非常有用,例如在线聊天应用、实时数据监控和游戏等。

SpringBoot集成WebSocket

        在Java项目中的pom.xml文件中导入依赖wzbsocket依赖

   
        org.springframework.boot
        spring-boot-starter-websocket
    

     导入websocket配置文件注册成为一个工具类,交给ioc管理。加载websocket


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket支持
 * @author wzk
 */
@Configuration  
public class WebSocketConfig {  
	
    @Bean  
    public ServerEndpointExporter serverEndpointExporter() {  
        return new ServerEndpointExporter();  
    }  
  
} 

        加载业务逻辑

websocket方法:

      @ServerEndpoint(value = "/chat/{username}"):用于建立连接路径,username表示当前连接的用户(前端的连接 路径为:ws://localhost:端口号/chat/当前连接用户)

     @Component:当前类注入ioc管理对方

     @OnOpen:用户发送请求触发函数方法

     @PathParam("name"):将用户请求路径中的 参数注入到该方法的参数上面

     @OnError : 用户请求连接异常触发函数

     @OnMessage:用户客户端*(前端)项目服务端(后端)发送信息触发函数

     @OnClose : 用户关闭连接触发函数

      发送消息方法sendMessage :toSession.getBasicRemote().sendText(msg):通过toSessiongetBasicRemote()方法获取到与目标会话关联的RemoteEndpoint.Basic对象,通过调用sendText(msg)方法发送文本消息。sendText方法是WebSocket API提供的方法,用于发送文本消息至远程端点。


import com.alibaba.fastjson.JSON;
import com.hqyj.project.pojo.Message;
import com.hqyj.project.utils.ApplicationContextUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat/{username}")
@Component
@Slf4j
public class SocketServer {


    // 保存链接的session,key为用户名,value为对应的session名
    private static ConcurrentHashMap sessionMap = new ConcurrentHashMap<>();

    /**
     * 创建连接
     * 用于监听建立连接,当有客户端与该服务端点建立连接时,将会自回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String username) {
        log.info("用户{}已创建连接", username);
        String key = "webSocket:"+username;
        sessionMap.put(username,session);
        //获取redis对象
        RedisTemplate redisTemplate =(RedisTemplate)ApplicationContextUtil.getBean("redis");
        //判断是否为空
        List members = redisTemplate.opsForList().range(key,0,-1);
        if (null != members && !members.isEmpty()){
            for (String message : members) {
                Session toSession = sessionMap.get(username);
                  //发送缓存信息
                sendMessage(toSession,message);
            }
            //删除redis中的键
            redisTemplate.delete(key);
        }
    }


    /**
     * 用于监听客户端向服务端发送消息,当客户端与服务端发送消息时,将会回调该注解标注的方法
     * @param msg
     * @param username
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "username") String username){
        log.info("用户{}发来消息:{}",username,msg);
        //解析用户发送的信息,使用系列化,映射到Message类
        Message message = JSON.parseObject(msg, Message.class);
        //使用工具类获取redis缓存数据库
        RedisTemplate redisTemplate =(RedisTemplate)ApplicationContextUtil.getBean("redis");
        //根据message中的to属性获取接收消息的用户的session,利用其session将消息转发过
        if (null == sessionMap.get(message.getTo())){   //发送给的用户为空
            //存入redis
            redisTemplate.opsForList().rightPush("webSocket:"+message.getTo(),message.getMsg());
            return;
        }
        Session toSession = sessionMap.get(message.getTo());
        //发送信息给用户
        sendMessage(toSession, message.getMsg());
    }


    /**
     * 用于监听连接关闭,当客户端与该服务端点断开连接时,将会回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnClose
    public void onClose(Session session, @PathParam(value = "username") String username){
        log.info("用户{}已关闭连接", username);
        sessionMap.remove(username);
    }


    /**
     * 用于监听该连接上的任何错误,当客户端与该服务端点的连接发生任何异常,都将回调该注解标注的方法
     * 注意该方法的参数必选Throwable,可选Sessiion以及0-n个String参数,且String参数需要使用@PathParam注解标注
     * @param throwable
     * @param username
     */
    @OnError
    public void onError(Throwable throwable,@PathParam(value = "username") String username){
        log.error("用户{}连接发生异常", username);
    }


    /**
     * 用来发送消息的方法,参数分别为接收消息的用户的session,和对应的消息
     */
    private void sendMessage(Session toSession,String msg){
        try {
            toSession.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

前端Vue代码

        代码解析注释里面已经存在,就不过多阐述





成品图

        SpringBoot+webSocket项目私信聊天功能实现_第1张图片

SpringBoot+webSocket项目私信聊天功能实现_第2张图片

完成全双关双向通信

你可能感兴趣的:(websocket,网络协议,网络)