文章目录

前言:什么是WebSocket?Spring Boot中的WebSocket支持WebSocket和HTTP优劣势WebSocket的优势:1.实时性:2.较低的延迟:3.较小的数据传输量:4.更好的兼容性:

HTTP的优势:1.简单易用:2.更广泛的应用:3.更好的安全性:

示例版本依赖代码WebSocketConfigWebSocketServerWebSocketControllerwebSocket.html

测试打开2个页面都点击开启socket都点击发送

总结源码获取写在最后

前言:

在当今互联网时代,实时通信已经成为了许多应用程序的基本需求。

而WebSocket作为一种全双工通信协议,为开发者提供了一种简单、高效的实时通信解决方案。

本文将介绍如何使用Spring Boot框架来实现WebSocket的集成,快速搭建实时通信功能。

什么是WebSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP请求-响应模式不同,WebSocket允许服务器主动向客户端推送数据,实现了实时通信的功能。WebSocket协议基于HTTP协议,通过在握手阶段升级协议,使得服务器和客户端可以直接进行数据交换,而无需频繁的HTTP请求。

Spring Boot中的WebSocket支持

Spring Boot提供了对WebSocket的支持,通过集成Spring WebSocket模块,我们可以轻松地实现WebSocket功能。在Spring Boot中,我们可以使用注解来定义WebSocket的处理器和消息处理方法,从而实现实时通信。

WebSocket和HTTP优劣势

WebSocket的优势:

1.实时性:

​ WebSocket是一种全双工通信协议,可以实现服务器主动向客户端推送数据,实现实时通信。相比之下,HTTP是一种请求-响应模式 的协议,需要客户端主动发起请求才能获取数据。

2.较低的延迟:

​ 由于WebSocket使用单个TCP连接进行通信,避免了HTTP的握手和头部信息的重复传输,因此具有较低的延迟。

3.较小的数据传输量:

​ WebSocket使用二进制数据帧进行传输,相比于HTTP的文本数据传输,可以减少数据传输量,提高传输效率。

4.更好的兼容性:

​ WebSocket协议可以在多种浏览器和平台上使用,具有较好的兼容性。

HTTP的优势:

1.简单易用:

​ HTTP是一种简单的请求-响应协议,易于理解和使用。相比之下,WebSocket需要进行握手和协议升级等复杂操作。

2.更广泛的应用:

​ HTTP协议广泛应用于Web开发中,支持各种类型的请求和响应,可以用于传输文本、图片、视频等多种数据格式。

3.更好的安全性:

​ HTTP协议支持HTTPS加密传输,可以保证数据的安全性。

综上,WebSocket适用于需要实时通信和较低延迟的场景,而HTTP适用于传输各种类型的数据和简单的请求-响应模式。在实际应用中,可以根据具体需求选择合适的协议。

示例

版本依赖

模块版本SpringBoot3.1.0JDK17

代码

WebSocketConfig

@Configuration

public class WebSocketConfig {

@Bean

public ServerEndpointExporter serverEndpointExporter() {

return new ServerEndpointExporter();

}

}

WebSocketServer

@Component

@ServerEndpoint("/server/{uid}")

@Slf4j

public class WebSocketServer {

/**

* 记录当前在线连接数

*/

private static int onlineCount = 0;

/**

* 使用线程安全的ConcurrentHashMap来存放每个客户端对应的WebSocket对象

*/

private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap<>();

/**

* 与某个客户端的连接会话,需要通过它来给客户端发送数据

*/

private Session session;

/**

* 接收客户端消息的uid

*/

private String uid = "";

/**

* 连接建立成功调用的方法

* @param session

* @param uid

*/

@OnOpen

public void onOpen(Session session, @PathParam("uid") String uid) {

this.session = session;

this.uid = uid;

if (webSocketMap.containsKey(uid)) {

webSocketMap.remove(uid);

//加入到set中

webSocketMap.put(uid, this);

} else {

//加入set中

webSocketMap.put(uid, this);

//在线数加1

addOnlineCount();

}

log.info("用户【" + uid + "】连接成功,当前在线人数为:" + getOnlineCount());

try {

sendMsg("连接成功");

} catch (IOException e) {

log.error("用户【" + uid + "】网络异常!", e);

}

}

/**

* 连接关闭调用的方法

*/

@OnClose

public void onClose() {

if (webSocketMap.containsKey(uid)) {

webSocketMap.remove(uid);

//从set中删除

subOnlineCount();

}

log.info("用户【" + uid + "】退出,当前在线人数为:" + getOnlineCount());

}

/**

* 收到客户端消息后调用的方法

* @param message 客户端发送过来的消息

* @param session 会话

*/

@OnMessage

public void onMessage(String message, Session session) {

log.info("用户【" + uid + "】发送报文:" + message);

//群发消息

//消息保存到数据库或者redis

if (StringUtils.isNotBlank(message)) {

try {

//解析发送的报文

ObjectMapper objectMapper = new ObjectMapper();

Map map = objectMapper.readValue(message, new TypeReference>(){});

//追加发送人(防止串改)

map.put("fromUID", this.uid);

String toUID = map.get("toUID");

//传送给对应的toUserId用户的WebSocket

if (StringUtils.isNotBlank(toUID) && webSocketMap.containsKey(toUID)) {

webSocketMap.get(toUID).sendMsg(objectMapper.writeValueAsString(map));

} else {

//若果不在这个服务器上,可以考虑发送到mysql或者redis

log.error("请求目标用户【" + toUID + "】不在该服务器上");

}

} catch (Exception e) {

log.error("用户【" + uid + "】发送消息异常!", e);

}

}

}

/**

* 处理错误

* @param session

* @param error

*/

@OnError

public void onError(Session session, Throwable error) {

log.error("用户【" + this.uid + "】处理消息错误,原因:" + error.getMessage());

error.printStackTrace();

}

/**

* 实现服务器主动推送

* @param msg

* @throws IOException

*/

private void sendMsg(String msg) throws IOException {

this.session.getBasicRemote().sendText(msg);

}

/**

* 发送自定义消息

* @param message

* @param uid

* @throws IOException

*/

public static void sendInfo(String message, @PathParam("uid") String uid) throws IOException {

log.info("发送消息到用户【" + uid + "】发送的报文:" + message);

if (!StringUtils.isEmpty(uid) && webSocketMap.containsKey(uid)) {

webSocketMap.get(uid).sendMsg(message);

} else {

log.error("用户【" + uid + "】不在线!");

}

}

private static synchronized int getOnlineCount() {

return onlineCount;

}

private static synchronized void addOnlineCount() {

WebSocketServer.onlineCount++;

}

private static synchronized void subOnlineCount() {

WebSocketServer.onlineCount--;

}

}

WebSocketController

@RestController

public class WebSocketController {

@GetMapping("/page")

public ModelAndView page() {

return new ModelAndView("webSocket");

}

@RequestMapping("/push/{toUID}")

public ResponseEntity pushToClient(String message, @PathVariable String toUID) throws Exception {

WebSocketServer.sendInfo(message, toUID);

return ResponseEntity.ok("Send Success!");

}

}

webSocket.html

WebSocket消息通知

【uid】:

【toUID】:

【Msg】:

【第一步操作:】:

【第二步操作:】:

测试

打开2个页面

第一个:

http://localhost:8080/socket/page

第二个:

http://localhost:8080/socket/page

都点击开启socket

都点击发送

至此示例发送完成

总结

通过本文的介绍,我们了解了Spring Boot中如何集成WebSocket,实现实时通信的功能。

WebSocket作为一种高效的实时通信协议,为开发者提供了更好的用户体验和交互性。

希望本文能够帮助快速掌握Spring Boot整合WebSocket的方法,为应用程序添加实时通信功能。

源码获取

如果需要完整源码请关注公众号"架构殿堂" ,回复 "SpringBoot+WebSocket"即可获得

写在最后

感谢您的支持和鼓励! 

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

参考阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。