在软件开发过程中,经常需要获取服务器端数据来展示给用户,对于数据的及时性有要求的场景,我们可能会采用长轮询等方式,来以一定的频率向服务器发起请求拉取数据,轮询方式会持续占用系统资源,效率较低,那么有没有一种解决方案,能做到服务器端有数据更新,及时通知客户端呢?通过使用websocket技术,我们可以做到客户端与服务器端的全双工通信,两端都可以实时的发送数据给对方~,下面就给大家介绍下SpringBoot中怎么整合websocket技术
- SpringBoot版本 2.4.5
使用方式
1.修改SpringBoot工程中的pom.xml配置,增加websocket的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.修改SpringBoot工程启动类,添加@EnableWebSocket注解来启用websocket能力支持
3.添加websocket配置
完整代码参考:https://github.com/netbuffer/spring-boot-websocket-demo/blob/master/src/main/java/cn/netbuffer/springboot/websocket/demo/config/SpringWebSocketConfig.java
@Configuration
public class SpringWebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//添加通信地址路径
registry.addHandler(buildTextHandler(), "/ws").setAllowedOrigins("*");
}
@Bean
public WebSocketHandler buildTextHandler() {
//添加消息处理器
return new TextHandler();
}
}
4.实现自己的消息处理器
完整代码参考:https://github.com/netbuffer/spring-boot-websocket-demo/blob/master/src/main/java/cn/netbuffer/springboot/websocket/demo/websocket/handler/TextHandler.java
@Slf4j
public class TextHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
if (session.isOpen()) {
log.info("receive websocket message:{} session:{}", message, session.getId());
TextMessage returnMessage = new TextMessage(message.getPayload() + " received at server");
session.sendMessage(returnMessage);
}
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
//建立连接后保存WebSocketSession会话
SessionManager.put(session.getId(), session);
log.info("session[{}] afterConnectionEstablished", session.getId());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
log.info("session[{}] afterConnectionClosed", session.getId());
//释放连接后移除WebSocketSession会话
SessionManager.remove(session.getId());
}
}
5.建立Controller控制器层映射方法,来测试主动推送消息到客户端
完整代码参考:https://github.com/netbuffer/spring-boot-websocket-demo/blob/master/src/main/java/cn/netbuffer/springboot/websocket/demo/controller/WebsocketController.java
@RestController
@RequestMapping("/ws")
public class WebsocketController {
@GetMapping("{session}/send")
public void send(@PathVariable("session") String session, String msg) {
WebSocketMessage webSocketMessage = new TextMessage(msg);
try {
SessionManager.get(session).sendMessage(webSocketMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.编写客户端html代码验证websocket能力
完整代码参考:https://github.com/netbuffer/UItest/blob/master/websocket/index.html
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:17000/ws");
ws.onopen = function () {
console.log("Connection open ...");
};
ws.onmessage = function (r) {
console.log("Received Message: " + r.data);
};
ws.onclose = function () {
console.log("Connection closed.");
};
</script>
<input name="text" placeholder="请输入文本内容" /><button onclick="ws.send(document.querySelector('input[name=\'text\']').value)">send</button> <button onclick="ws.close()">close</button>
运行效果
启动SpringBoot工程,再使用chrome浏览器访问客户端页面,打开开发者工具
观察开发者工具控制台已经打印出连接的日志,服务器端控制台也已经打印出连接日志
现在通过客户端页面发送一些消息,来查看服务器端日志是否有输出~
观察结果可以看到服务器端已经收到对应内容,并写回响应消息给客户端了
再测试下服务器主动推送消息给客户端的效果,使用Postman工具访问我们编写的接口来发送一些消息给客户端,注意session字符串可以从服务器日志打印中找到
GET /ws/73f67e83-79f5-a238-844f-c80f6926a429/send?msg=你好 HTTP/1.1
Host: localhost:17000
观察结果可以看到服务器已经能实时推送相应的内容给客户端了~
完整测试工程参考:https://github.com/netbuffer/spring-boot-websocket-demo