springboot集成webSocket
1、前言
在很多业务场景中,对实时数据要求比较高,我们就不能采用轮训拉取的方式来获取数据了。就可以采用websocket的长链接的形式,实时有服务端或者客户端推送数据,已达到数据的实时展示。
2、websocket简介
SpringBoot官方推荐的基于STOMP实现,STOMP:即Simple Text Orientated Messaging Protocol
,它是一个简单的文本消息传输协议,属于 WebSocket 的子协议, 提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。STOMP协议由于设计简单, 易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。有点类似于Kafka的发布订阅模式。
3、环境
JDK8 + maven3.x + spring5.x
4、引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- socket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 客户端采用thymeleaf引擎模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
5、websocket配置类
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
// 设置socket连接
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/testSocket")
.setAllowedOrigins("*") //解决跨域问题
.withSockJS();
}
// 设置发布订阅的主题
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/top");
}
}
spring5.0以下,创建websocket的配置类的时候需要继承 AbstractWebSocketMessageBrokerConfigurer。
但是5.0以后该方法就过时了,5.0以后是基于JDK1.8,接口中支持默认方法,如图:
所以直接实现 WebSocketMessageBrokerConfigurer 这个接口,重新需要的方法即可。
6、创建消息发送的控制类
为了测试方便,我把普通的控制和消息发送的控制层写在了一个controller中:
@Controller
public class WebSocketController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/test")
@SendTo("/top/test")
@ResponseBody
public String call(String msg){
System.out.println(msg);
return msg;
}
@RequestMapping("/test01")
@ResponseBody
public String send() {
System.out.println("发送成功");
simpMessagingTemplate.convertAndSend("/top/test", "send.....");
return "调用成功!";
}
@RequestMapping("/socketPage")
public String socketPage(){
return "socket";
}
@SubscribeMapping("/top/test")
public String test02(){
String msg = " @SubscribeMapping";
System.out.println(msg);
return msg;
}
}
其中 @RequestMapping 代表普通控制层,而 @MessageMapping 代表websocket发送消息的映射。@SubscribeMapping 是客户端订阅的消息请求,当建立socket连接时,订阅的消息请求会通过 @SubscribeMapping 获取该方法下的消息,返回在客户端。
7、客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webSocket</title>
</head>
<body>
<div>
<h2>Socket 网络实时交互测试</h2>
<div>
<button id="connect" onclick="connect();">建立连接</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
</div>
<div id="conversationDiv">
<label>What is your name?</label>
<input type="text" id="name" />
<button id="sendName" onclick="sendName();">Send</button>
<p id="response"></p>
</div>
</div>
</body>
<script src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.min.js"></script>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
<script src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
var stompClient = null;
$(function(){
connect();
});
function setConnected(connected) {
$("#connect").attr("disabled", connected);
$("#disconnect").attr("disabled", !connected);
if (connected) {
$("#conversationDiv").show();
}else{
$("#conversationDiv").hide();
}
$("#response").html("");
}
//this line.
function connect() {
var socket = new SockJS("http://127.0.0.1/testSocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/top/test', function(frame){
//showGreeting(JSON.parse(greeting.body).content);
console.info(frame);
showGreeting(frame.body);
});
});
}
function sendName() {
var name = $("#name").val();
stompClient.send("/test", {}, name);
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function showGreeting(message) {
$("#response").append("<tr><td>" + message + "</td></tr>");
}
</script>
</html>
由于thymeleaf都采用的是默认的配置方式,所以就没有对应的.properitiesh或.yml文件。
8、启动结果
- 页面打开后简历连接, 就会自动订阅信息,通过@SubscribeMapping获取服务端的消息
- 客户端发送信息,打印公屏上
- 服务端直接调用,将消息发送给订阅者
核心方法:
9、参考文档
https://www.xncoding.com/2017/07/15/spring/sb-websocket.html
https://blog.csdn.net/weixin_44619017/article/details/100519951
官方文档:
https://spring.io/guides/gs/messaging-stomp-websocket/
推荐阅读
-
javaweb各种框架组合案例(六):springboot+spring data jpa(hibernate)+restful
-
微信小程序websocket实现聊天功能
-
SpringBoot+Elasticsearch
-
Vue+Jwt+SpringBoot+Ldap完成登录认证的示例代码
-
华为官宣麒麟990:9月6日德国IFA发布、集成达芬奇架构新NPU
-
ABP 结合 MongoDB 集成依赖注入
-
SpringBoot+Dubbo+Zookeeper整合搭建简单的分布式应用
-
三星发布Exynos 980:旗下首款集成5G基带手机SoC、8nm A77架构
-
高通官宣!骁龙7系处理器将集成5G基带 12家厂商齐发
-
对标高通Adreno!三星Exynos 9925曝光:集成AMD GPU