Springboot:SpringBoot2.0整合WebSocket,实现后端数据实时推送!
阅读原文时间:2023年07月10日阅读:1

一、什么是WebSocket?

B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链接,但不容易直接完成实时的消息推送功能,如聊天室、后台信息提示、实时更新数据等功能,但通过polling、Long polling、长连接、Flash Socket以及HTML5中定义的WebSocket能完成该功能需要。

WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据,在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。Socket的英文原义是“孔”或“插座”,作为UNIX的进程通信机制。Socket可以实现应用程序间网络通信。

Socket可以使用TCP/IP协议或UDP协议。

TCP/IP协议

TCP/IP协议是目前应用最为广泛的协议,是构成Internet国际互联网协议的最为基础的协议,由TCP和IP协议组成:
TCP协议:面向连接的、可靠的、基于字节流的传输层通信协议,负责数据的可靠性传输的问题。

IP协议:用于报文交换网络的一种面向数据的协议,主要负责给每台网络设备一个网络地址,保证数据传输到正确的目的地。

UDP协议

UDP特点:无连接、不可靠、基于报文的传输层协议,优点是发送后不用管,速度比TCP快。

二、SpringBoot整合WebSocket

新建一个spring boot项目spring-boot-websocket,按照下面步骤操作。

1.pom.xml引入jar包

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

2.新建WebSocket的配置类

这个配置类检测带注解@ServerEndpoint的bean并注册它们,配置类代码如下:

@Configuration
public class WebSocketConfig {
/**
* 给spring容器注入这个ServerEndpointExporter对象
* 相当于xml:
* * *
*


* 检测所有带有@serverEndpoint注解的bean并注册他们。
*
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
System.out.println("我被注入了");
return new ServerEndpointExporter();
}
}

3.新建WebSocket的处理类

这个处理类需要使用@ServerEndpoint,这个类里监听连接的建立关闭、消息的接收等,具体代码如下:

@ServerEndpoint(value = "/ws/asset")
@Component
public class WebSocketServer {

@PostConstruct  
public void init() {  
    System.out.println("websocket 加载");  
}  
private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);  
private static final AtomicInteger OnlineCount = new AtomicInteger(0);  
// concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。  
private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();

/\*\*  
 \* 连接建立成功调用的方法  
 \*/  
@OnOpen  
public void onOpen(Session session) {  
    SessionSet.add(session);  
    int cnt = OnlineCount.incrementAndGet(); // 在线数加1  
    log.info("有连接加入,当前连接数为:{}", cnt);  
    SendMessage(session, "连接成功");  
}

/\*\*  
 \* 连接关闭调用的方法  
 \*/  
@OnClose  
public void onClose(Session session) {  
    SessionSet.remove(session);  
    int cnt = OnlineCount.decrementAndGet();  
    log.info("有连接关闭,当前连接数为:{}", cnt);  
}

/\*\*  
 \* 收到客户端消息后调用的方法  
 \*  
 \* @param message  
 \*            客户端发送过来的消息  
 \*/  
@OnMessage  
public void onMessage(String message, Session session) {  
    log.info("来自客户端的消息:{}",message);  
    SendMessage(session, "收到消息,消息内容:"+message);

}

/\*\*  
 \* 出现错误  
 \* @param session  
 \* @param error  
 \*/  
@OnError  
public void onError(Session session, Throwable error) {  
    log.error("发生错误:{},Session ID: {}",error.getMessage(),session.getId());  
    error.printStackTrace();  
}

/\*\*  
 \* 发送消息,实践表明,每次浏览器刷新,session会发生变化。  
 \* @param session  
 \* @param message  
 \*/  
public static void SendMessage(Session session, String message) {  
    try {  

// session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId()));
session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.error("发送消息出错:{}", e.getMessage());
e.printStackTrace();
}
}

/\*\*  
 \* 群发消息  
 \* @param message  
 \* @throws IOException  
 \*/  
public static void BroadCastInfo(String message) throws IOException {  
    for (Session session : SessionSet) {  
        if(session.isOpen()){  
            SendMessage(session, message);  
        }  
    }  
}

/\*\*  
 \* 指定Session发送消息  
 \* @param sessionId  
 \* @param message  
 \* @throws IOException  
 \*/  
public static void SendMessage(String message,String sessionId) throws IOException {  
    Session session = null;  
    for (Session s : SessionSet) {  
        if(s.getId().equals(sessionId)){  
            session = s;  
            break;  
        }  
    }  
    if(session!=null){  
        SendMessage(session, message);  
    }  
    else{  
        log.warn("没有找到你指定ID的会话:{}",sessionId);  
    }  
}  

}

4.Html编写方式

目前大部分浏览器支持WebSocket,比如Chrome, Mozilla,Opera和Safari,在html页面进行websocket的连接建立、收消息的监听,页面代码如下:


websocket测试

WebSocket测试,客户端接收到的消息如下:


三、业务调用

WebSocket ws = new WebSocket();
JSONObject jo = new JSONObject();
jo.put("message", "这个比密码不对还想登录!");
jo.put("To", "admin");// 给用户名为admin的用户推送
try {
ws.onMessage(jo.toString());
} catch (IOException e) {
e.printStackTrace();
}

四、 查看运行效果

启动SpringBoot项目

1.打开首页

本地浏览器打开首页http://localhost:8080/,出现WebSocket测试页面,同时后台打印连接的日志。

有连接加入,当前连接数为:1,sessionId=0

2.往客户端发送消息

通过上面日志可以看到客户端连接连接的sessionId,我测试时候sessionId是0,然后浏览器访问下面接口即可往客户端发送消息。

//参数说明: id:sessionID
//参数说明: message:消息内容
http://localhost:8080/api/ws/sendOne?id=0&message=你好Java碎碎念

到此SpringBoot整合WebSocket的功能已经全部实现。

完整源码地址: https://github.com/suisui2019/springboot-study

文章转载至:https://www.cnblogs.com/haha12/p/11933310.html