【史上最简单webSocket】SpringBoot+webSocket 聊天室【服务端】

基于SpringBoot搭建聊天室服务端【一对多】

引入依赖

 <!-- WebSocket依赖 -->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-websocket</artifactId>
 </dependency>

首先肯定是引入我们需要的依赖,将【spring-boot-starter-websocket】依赖先引入pom.xml文件中

编写配置类

创建一个类,名字随意,这里起名WebSocketConfig.java,在该类中编写我们的wenSocket配置信息。

@Configuration  // 声明这是一个配置类
public class WebSocketConfig {

	// 为什么要配置这个信息呢?
	// 因为:这个Bean会自动注册使用@ServerEndpoint注解声明的websocket
	// 后续前后端之间的收发消息都能直接对应的到指定的方法,不需要自己配置地址
    @Bean  
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

这点不理解的可以先放一放,看到后面回来重新看即可明白

编写具体webSocket类

创建一个类,名字随意,这里起名:WebSocket
首先,编写该类,有一些需要注意的点:【下面内容可结合代码】

    • 类的注解
  • 方法
    • 方法的注解
    • 方法的参数
  • 变量
@Component // 声明这是一个需要被扫描的类
@ServerEndpoint("/webSocket/{uuid}") // 这个注解需要上面配置类的存在才能实现
public class WebSocket {
    Logger logger = LoggerFactory.getLogger("WebSocket");
    // 统计在线人数的【采用原子性的AtomicInteger,避免多用户同时写入出现线程安全问题】
    private static AtomicInteger onlineCount = new AtomicInteger(0); 
    private static Map<String, WebSocket> loginMap = new ConcurrentHashMap<String, WebSocket>(); // 存储在线人数,与用户的信息
    private String uuid; // 用户id
    public Session session; 

    /**
     * 打开连接
     * @param
     * @param session
     * @throws IOException
     */
    @OnOpen  // 在前端申请连接访问 .../webSocket/{uuid}时,就会自动调用该注解的方法
    public void onOpen(@PathParam("uuid") String uuid,Session session) throws IOException {
    	//在这里初始化数据,登记连接人员等操作
        this.uuid = uuid;
        this.session = session;

        logger.info("{} 加入了群聊 ",uuid);
        loginMap.put(uuid, this);

        addOnlineCount();//本来用统计在线人数的
        logger.info("有新的用户加入群聊,目前群聊人数为:{}",onlineCount);
    }

    /**
     * 删除
     * @throws IOException
     */
    @OnClose // 在前端断开连接后,会自动调用有该注解的方法
    public void onClose() throws IOException {
    	// 用户处理断开连接人员的删除
        if (!uuid.equals("")) {
            loginMap.remove(uuid);
            subOnlineCount(); //本来用统计在线人数的
            logger.info(uuid+"退出群聊,目前群聊人数为:"+onlineCount);
        }
    }

    /**
     * 错误信息
     */
    @OnError //当连接或者webSocket出现问题时,就会调用该注解的方法
    public void onError(Session session, Throwable error) {
    	// 可以在这里进行错误信息打印与错误处理
        logger.error("错误信息:"+session);
        error.printStackTrace();
    }


    /**
     * 接收数据
     * @throws IOException
     */
    @OnMessage //当前端调用发送消息方法时,后端该注解的方法就会被调用,并且消息会以参数的方式传入
    public void onMessage(String message) throws IOException {
    	//注意!!!参数为String!!是固定的,如果需要转JSON,就需要进行处理
    	// 这里通常用于处理心跳或者处理信息
        if (message.equals("心一跳")){
            logger.info("【{}】发来心跳:{}",uuid,message);
        }else {
            logger.info("【{}】发来信息:{}",uuid,message);
            // 将接收的消息发送给所有人
            sendMessageLoginTo(message);
        }
    }

    /**
     * 发给所有人
     * @param message
     * @throws IOException
     */
     // 这里是一个自定义的方法,用于发送消息给其他人,注意!!没有注解!!!
    public void sendMessageLoginTo(String message) throws IOException {
        //session.getBasicRemote().sendText(message); // 同步发送,会阻塞
        //session.getAsyncRemote().sendText(message); // 异步发送,不会阻塞

		//这里为 将信息发送给!!所有人!!
        if (loginMap != null) {
        	// 遍历目前还连接着的所有人员
            for(String key:loginMap.keySet()){
    			// 拿到他们的WebSocket
                WebSocket item = loginMap.get(key);
                this.logger.info("发送消息给{}",key);
                // 采用异步的方法发送消息  注意!sendText的参数是String类型的!!
                item.session.getAsyncRemote().sendText(message);
            }
        }
    }


    /**
     * 发给指定一个人
     * @param message
     * @throws IOException
     */
     // 这里是一个自定义的方法,用于发送消息给其他人,注意!!没有注解!!!
    public void sendMessageToOne(String message,String uid) throws IOException {
		//这里为 将信息发送给!!指定一个人!!
        if (loginMap != null) {
        	// 遍历目前还连接着的所有人员
            for(String key:loginMap.keySet()){
            	if(key==uid){
            		// 这里循环到了指定用户
            		WebSocket item = loginMap.get(key);
            		this.logger.info("发送消息给{}",key);
            		// 采用异步发送
            		item.session.getAsyncRemote().sendText(message);
            	}
                // 没有指定对象,可进行另外的逻辑编写
            }
        }
    }

	// 增加在线人数,因为涉及到多线程问题,这里采用原子性的AtomicInteger进行记录
    public static void addOnlineCount() {
        WebSocket.onlineCount.getAndIncrement();
    }
	// 减少在线人数
    public static void subOnlineCount() {
        WebSocket.onlineCount.getAndDecrement();
    }
	// 返回目前在线人数的所有信息
    public static synchronized Map<String, WebSocket> getLoginMap() {
        return loginMap;
    }

}

后续将会更新前端部分的代码解析,如有需要webSocket理论的解读,可在评论区提出,我会尽快提上日程,满足各位大伙的知识需求

到此,聊天室的服务端基本功能就搭建完毕了,如果有疑问的地方,可以在评论进行提问。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值