Spring Boot 的学习持续进行中。前面两篇博客我们介绍了如何使用 Spring Boot 容器搭建 web 项目 () 以及怎样为我们的 Project 添加 HTTPS 的支持(),在这两篇文章的基础上,我们今天来看看如何在 Spring Boot 中使用 WebSocket。
WebSocket 为浏览器和服务器之间提供了双工异步通信功能,也就是说我们可以利用浏览器给服务器发送消息,服务器也可以给浏览器发送消息,目前主流浏览器的主流版本对 WebSocket 的支持都算是比较好的,但是在实际开发中使用 WebSocket 工作量会略大,而且增加了浏览器的兼容问题,这种时候我们更多的是使用 WebSocket 的一个子协议 stomp,利用它来快速实现我们的功能。OK,关于 WebSocket 我这里就不再多说,我们主要看如何使用,如果小伙伴们有兴趣可以查看这个回答来了解更多关于 WebSocket 的信息。
使用 WebSocket 需要我们先创建一个 Project,这个 Project 的创建方式和我们前文 () 说的一样,不同的是在选择依赖的时候选择 Thymeleaf 和 WebSocket 依赖,如下图:
Project 创建成功之后,我们先来配置 WebSocket,创建如下类:
- @Configuration
- @EnableWebSocketMessageBroker
- public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
- @Override
- public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
- stompEndpointRegistry.addEndpoint("/endpointSang").withSockJS();
- }
- @Override
- public void configureMessageBroker(MessageBrokerRegistry registry) {
- registry.enableSimpleBroker("/topic");
- }
- }
关于这个类我说如下几点:
浏览器发送来的消息用这个类来接收:
- public class RequestMessage {
- private String name;
- public String getName() {
- return name;
- }
- }
服务器返回给浏览器的消息由这个类来承载:
- public class ResponseMessage {
- private String responseMessage;
- public ResponseMessage(String responseMessage) {
- this.responseMessage = responseMessage;
- }
- public String getResponseMessage() {
- return responseMessage;
- }
- }
- @Controller
- public class WsController {
- @MessageMapping("/welcome")
- @SendTo("/topic/getResponse")
- public ResponseMessage say(RequestMessage message) {
- System.out.println(message.getName());
- return new ResponseMessage("welcome," + message.getName() + " !");
- }
- }
关于这个控制器,,�@RequestMapping 类似。
注解表示当服务器有消息需要推送的时候,
- @SendTo
我们这个案例需要三个 js 脚本文件,分别是 STOMP 协议的客户端脚本 stomp.js、SockJS 的客户端脚本 sock.js 以及 jQuery,这三个 js 文件拷贝到 src/main/resources/static/js 目录下。OK,这三个 js 文件我已经为小伙伴们准备好了,可以直接在文末下载案例,案例中有,也可以自行下载这三个 js 文件。
在写这个 html 页面之前,我想先说我们要实现的效果是什么样子的。当我的 Project 启动之后,在浏览器访问消息发送页面,在该页面发送一条消息,当服务端收到这条消息之后给所有的连接上了服务器的浏览器都发送一条消息。OK,我们在 src/main/resources/templates 目录下新建一个 ws.html 页面,内容如下:
- <html lang="en" xmlns:th="http://www.thymeleaf.org">
- <head>
- <meta charset="UTF-8" />
- <title>
- 广播式WebSocket
- </title>
- <script th:src="@{js/sockjs.min.js}">
- </script>
- <script th:src="@{js/stomp.js}">
- </script>
- <script th:src="@{js/jquery-3.1.1.js}">
- </script>
- </head>
- <body onload="disconnect()">
- <noscript>
- <h2 style="color: #e80b0a;">
- Sorry,浏览器不支持WebSocket
- </h2>
- </noscript>
- <div>
- <div>
- <button id="connect" onclick="connect();">
- 连接
- </button>
- <button id="disconnect" disabled="disabled" onclick="disconnect();">
- 断开连接
- </button>
- </div>
- <div id="conversationDiv">
- <label>
- 输入你的名字
- </label>
- <input type="text" id="name" />
- <button id="sendName" onclick="sendName();">
- 发送
- </button>
- <p id="response">
- </p>
- </div>
- </div>
- <script type="text/javascript">
- var stompClient = null;
- function setConnected(connected) {
- document.getElementById("connect").disabled = connected;
- document.getElementById("disconnect").disabled = !connected;
- document.getElementById("conversationDiv").style.visibility = connected ? 'visible': 'hidden';
- // $("#connect").disabled = connected;
- // $("#disconnect").disabled = !connected;
- $("#response").html();
- }
- function connect() {
- var socket = new SockJS(' / endpointSang');
- stompClient = Stomp.over(socket);
- stompClient.connect({},
- function(frame) {
- setConnected(true);
- console.log('Connected: ' + frame);
- stompClient.subscribe(' / topic / getResponse',
- function(response) {
- showResponse(JSON.parse(response.body).responseMessage);
- })
- });
- }
- function disconnect() {
- if (stompClient != null) {
- stompClient.disconnect();
- }
- setConnected(false);
- console.log('Disconnected');
- }
- function sendName() {
- var name = $('#name').val();
- console.log('name: ' + name);
- stompClient.send("/welcome", {},
- JSON.stringify({'name': name
- }));
- }
- function showResponse(message) {
- $("#response").html(message);
- }
- </script>
- </body>
- </html>
这里虽然代码略多,但是仔细分析一下却也很简单。首先 js 文件引入的那一部分我就不再多说,这里如果又不理解的可以参考。然后我们的页面上先有两个按钮,一个是连接,一个是断开连接,两个按钮分别对应不同的点击事件,在这两个按钮下方有一个输入框,就是我们要发送的内容,然后还有一个发送按钮,发送按钮对应了一个发送消息的点击事件。这是整个页面的元素,很简单,我们这里重点来看一下 js 逻辑代码。connect 方法是当我点击连接按钮的时候执行的,
表示连接的 SockJS 的 endpoint 名称为 / endpointSang,
- var socket = new SockJS('/endpointSang');
表示使用 STOMP 来创建 WebSocket 客户端。然后调用 stompClient 中的 connect 方法来连接服务端,连接成功之后调用
- stompClient = Stomp.over(socket);
方法,该隐藏的隐藏,该显示的显示。然后再通过调用 stompClient 中的 subscribe 方法来订阅 / topic/getResponse 发送来的消息,�到服务端,其他的都是常规的 js 用法我就不再赘述。
- setConnected
接下来就是要为 ws.html 提供路径映射:
- @Configuration
- public class WebMvcConfig extends WebMvcConfigurerAdapter {
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/ws").setViewName("/ws");
- }
- }
OK,做完这一切之后我们就可以运行项目了,我同时打开多个浏览器,然后在其中一个上发送消息,我们来看看结果:
我在最上面的浏览器上发送消息,其他两个浏览器都能收到我的消息。
OK ,以上就是我们在 Spring Boot 框架下使用 WebSocket 实现消息推送的全过程。
本案例下载地址:
以上。
参考资料:
《JavaEE 开发的颠覆者 Spring Boot 实战》第七章
来源: