前言
在上一篇文章中讲了如何在 SpringBoot
中配置 WebSocket
模拟实现群发消息的功能,本文则将进一步讲解如何在 SpringBoot
中配置基于 wss
协议和 STOMP
的 WebSocket
,本文假设你对 STOMP
协议有一定的了解,否则建议你先了解一下 STOMP
协议,可以参考这篇文章,此外不同于上一篇的代码示例比较复杂,本文将用尽可能少的代码为你展示效果,同样本文的完整代码已上传到GitHub,下面就正式开始。
效果展示
同上一篇一样,在展示具体的代码配置之前,先展示一下最终的效果:
下面是整个项目的目录结构:
├─main
│ ├─java
│ │ └─com
│ │ └─zjw
│ │ └─stomp
│ │ │ StompApplication.java
│ │ │
│ │ ├─config
│ │ │ TomcatConfiguration.java
│ │ │ WebSocketConfig.java
│ │ │
│ │ └─controller
│ │ BroadcastController.java
│ │ HTMLController.java
│ │
│ └─resources
│ │ application.yaml
│ │ keystore.jks
│ │
│ └─templates
│ greet.html
│ index.html
│
└─test
└─java
└─com
└─zjw
└─stomp
StompApplicationTests.java
Tips
想要生成以上目录树的结构,只需要在命令行使用 tree /f 文件夹名
即可,如果不想展示具体的文件,去掉 /f
参数即可。
具体配置
wss
配置
想要设置 wss
协议只需要 SpringBoot
配置 https
即可,下面就讲解具体的步骤:
-
生成签名证书
在
cmd
中输入以下命令,这里的D:\develop\keystore.jks
即证书的生成路径,自己根据自己的情况修改即可,之后回车,根据提示输入自己的信息,即可在设置的路径下生成证书文件。keytool -genkeypair -alias tomcat -keyalg RSA -keystore D:\develop\keystore.jks
-
项目配置
首先复制刚才生成的
keystore.jks
文件,然后粘贴到resources
文件夹下,完成后,修改application.yaml(yml)
文件:server: port: 443 ssl.key-store: classpath:keystore.jks ssl.key-store-password: 123456 ssl.key-password: 123456 ssl.key-alias: tomcat
如果是
properties
文件,改成下列形式即可:server.port=443 server.ssl.key-store=classpath:keystore.jks server.ssl.key-store-password=123456 server.ssl.key-password=123456 server.ssl.key-alias=tomcat
-
Tomcat
配置import org.apache.catalina.connector.Connector; import org.apache.tomcat.websocket.server.WsSci; import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfiguration { @Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addAdditionalTomcatConnectors(createSslConnector()); return tomcat; } private Connector createSslConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(8080); connector.setSecure(false); // 监听8080端口转发到443端口 connector.setRedirectPort(443); return connector; } @Bean public TomcatContextCustomizer tomcatContextCustomizer() { return context -> context.addServletContainerInitializer(new WsSci(), null); } }
-
浏览器测试
完成以上步骤后,在浏览器中的地址栏中输入
https://localhost/
,只要能地址栏处显示不安全,就说明https
配置成功:
STOMP
配置
完成了 wss
也等于是 https
的配置后,就可以开始进行 STOMP
的配置了:
-
引入依赖
首先需要引入以下必要的依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.34</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>stomp-websocket</artifactId> <version>2.3.3</version> </dependency>
-
配置广播的
Controller
import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.web.bind.annotation.RestController; @RestController public class BroadcastController { // 这里的 @MessageMapping 可以当成 @RequestMapping, // 当有信息(broardcast 方法中的 msg 参数即为客服端发送的信息)发送到 /sendMsg 时, // broadcast 方法的返回的数据就会发送到所有订阅了 /broadcast/greet 的客户端 // 关于如何订阅 /broadcast/greet 会在之后的客户端代码看到 @MessageMapping("/sendMsg") @SendTo("/broadcast/greet") public String broadcast(String msg) { return msg; } }
-
配置
WebSocket
消息代理import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { // 开启一个简单的基于内存的消息代理 // 将消息返回到订阅了带 /broadcast 前缀的目的客户端 // 上述的 @SendTo 中的地址需要带有 /broadcast 前缀 config.enableSimpleBroker("/broadcast"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 注册一个 /websocket 的 WebSocket 终端 registry.addEndpoint("/websocket"); } }
-
视图解析
Controller
为了方便,项目在
templates
文件夹下建了index.html
和greet.html
,这里需要配置一下视图解析:import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HTMLController { @RequestMapping("/index") public String index() { return "index"; } @RequestMapping("/greet") public String greet() { return "greet"; } }
-
主页代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主页</title> <script src="/webjars/stomp-websocket/stomp.min.js"></script> </head> <body> <div id="greet"></div> <script> // 设置 WebSocket 的连接地址 wss://localhost/websocket let socket = new WebSocket('wss://localhost/websocket') let stompClient = Stomp.over(socket) stompClient.connect({}, function () { // 订阅到 /broadcast/greet, 即 @SendTo 内配置的地址 stompClient.subscribe('/broadcast/greet', function (frame) { // 获取消息帧的 body 内容, 显示到 <div id="greet"></div> 中 showGreeting(`收到信息: ${frame.body}`) }) }) function showGreeting(clientMessage) { document.getElementById("greet").innerText += `${clientMessage}\n` } </script> </body> </html>
-
发送消息界面的代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>群发信息</title> <script src="/webjars/stomp-websocket/stomp.min.js"></script> </head> <body> <label><input type="text" id="msg"/></label> <button onclick="sendMsg()">发送</button> <script> // 设置 WebSocket 的连接地址 wss://localhost/websocket let socket = new WebSocket('wss://localhost/websocket') let stompClient = Stomp.over(socket); function sendMsg() { const msg = document.getElementById('msg').value // 发送输入框内的信息, /sendMsg 即为 @MessageMapping 中配置的地址 stompClient.send("/sendMsg", {}, msg) alert('发送成功') } </script> </body> </html>
完成以上配置后,即可实现效果展示中的效果。
总结
本文通过一个简单 demo
,展示了如何使用集成了 wss
和 STOMP
的 WebSocket
,希望能够对你有所帮助,之后还会再通过一些更具体完整的示例代码,来讲解 WebSocket
的具体应用。