springboot java websocket ws 快速入门

学而不思则罔,思而不学则殆。

一、背景介绍

java 大部分都是在做服务端,主要的流程也都是客户端发起一个http请求,服务端接收请求,然后响应数据
在这里插入图片描述
如果这个时候服务端想往客户端发送数据,比较常见的就是有

  • 轮序: 也就是客户端一直往服务端请求获取要的数据,这样服务端压力大
  • 长连接: 用 iframe 的方式 保持一个持久的连接,对服务端压力也大.
  • webSocket: 这个就是这篇文章要讲的,以TCP的方式 建立连接之后就可以双向通信了
    在这里插入图片描述

二、最佳实践

2.1 引入依赖

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

2.2 启动类上添加注解 @EnableWebSocket 和注入ServerEndpointExporter

@SpringBootApplication
@EnableWebSocket
@MapperScan("com.example.demo.dao")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
	
	 /**
     * 初始化Bean,它会自动注册使用了 @ServerEndpoint 注解声明的 WebSocket endpoint
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
 }

2.3 编写服务端实例

package com.example.demo.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Classname WebSocketTest
 * @Description webSocket 测试类
 * @Date 2020/11/27 13:23
 * @Created by dongzhiwei
 */
@ServerEndpoint(value="/websocket/{id}")
@Slf4j
@Component
public class WebSocketTest {

    private static int onlineCount = 0;
    private static Map<String, WebSocketTest> webSocketMap = new ConcurrentHashMap<>();
    private Session session;
    private String id;

    /**
     * 用户第一次建立连接的时候执行的方法
     * @param id
     * @param session
     */
    @OnOpen
    public void onOpen(@PathParam("id") String id, Session session){
        this.id = id;
        this.session = session;
        if (!webSocketMap.containsKey(id)) {
            //没有建立连接的
            webSocketMap.put(id, this);
            //注意并发
            addOnlineCount();
        }
        log.info("用户"+id+"连接上webSocket,当前连接人数为"+getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(this.id)){
            webSocketMap.remove(this.id);
            //从set中删除
            subOnlineCount();
        }
        log.info("用户退出:"+id+",当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("用户"+this.id+"发送信息:"+message);
    }

    /**
     * 发生错误的时候调用的方法
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:"+this.id+",原因:"+error.getMessage());
        error.printStackTrace();
    }

    /**
     * 向执行某个任务的客户端发送消息
     */
    public void sendMessage(String message){
        this.session.getAsyncRemote().sendText(message);
    }

    /**
     * 向用户id为userId的用户推送消息
     * */
    public static void sendInfo(String message,String id){
        log.info("发送消息到:"+id+",报文:"+message);
        if(id != null && webSocketMap.containsKey(id)){
            webSocketMap.get(id).sendMessage(message);
        }else{
            log.error("用户"+id+",不在线!");
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketTest.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketTest.onlineCount--;
    }


}

2.4 测试连接

启动服务,根据ip地址和端口建立socket 连接, 点这里在线网站测试
在这里插入图片描述

三、总结

其实在一个http服务端上面再部署一下ws 也是没有问题的访问也没有任何问题 他们就是两个不同的协议 一个http协议 一个websocket协议.我们可以在类似于聊天室和浏览器实时获取最新消息的时候用到这个ws协议.无论怎么用都只是一个工具,在这个场景下是否适用罢了。

猜你喜欢

转载自blog.csdn.net/hgdzw/article/details/110231603