(一)springboot结合websocket之使用STOMP协议推送消息

前言

有时候前端需要实时的获取后端的信息,比如订单的消息,发货之类的通知,实时的服务器信息,股票信息等。有一种方法是ajax轮训,就是间隔一段时间查询服务器一次,但是这种方式对服务器不太友好。所以,还有另一种方法,websocket。

一、引入websocket

pom文件引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

二、配置

写一个配置类,继承AbstractWebSocketMessageBrokerConfigurer,这个类配置的是关于STOMP协议。前端使用的是stomp.js,关于stomp.js可以看一下这一篇博客:https://www.cnblogs.com/goloving/p/10746378.html 。stomp.js 具体的使用方法下面会写。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {

	/**
     * 注册stomp的端点,发布或者订阅消息时需要连接此端点
     */
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/endpoint").setAllowedOrigins("*").withSockJS();
		
	}
	
	/**
     * 配置信息代理(中介转发)
     */
	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		
		// 订阅Broker名称
		registry.enableSimpleBroker("/queue","/topic","/chat");
		// 全局使用的消息前缀(客户端订阅路径上会体现出来)
		registry.setApplicationDestinationPrefixes("/app");
		
	}
	
}

三、使用

首先定义两个传输数据的对象

public class InMessage {
	
	private String from;
	
	private String to;
	
	private LocalDateTime time = LocalDateTime.now();
	
	private String content;
    
    //省略setter和getter
}
public class OutMessage {
	
	private String from;
	
	private LocalDateTime time = LocalDateTime.now();
	
	private String content;
    
    //省略setter和getter
}

使用起来也是很简单,有两种方法。

1、使用@SendTo注解来转发数据

value属性值的第一值 /topic 必须在enableSimpleBroker中配置,@MessageMapping和@RequestMapping的作用类似。

@Controller
public class GameInfoController {

	@MessageMapping("/v1/game_chat")
	@SendTo("/topic/game_chat")
	public OutMessage gameInfo(InMessage message){
		
		return new OutMessage("",message.getContent());
	}
	
}

2、注入SimpMessagingTemplate推送消息

destination的第一个值必须在上面 的enableSimpleBroker中配置,与@SendTo的value使用方法一致。

@Component
public class WebSocketService {

	@Autowired
	private SimpMessagingTemplate template;
	
	public void sengTextMsg(String destination,Object message){
		
		template.convertAndSend(destination,message);
		
	}

}
@Controller
public class GameInfoV2Controller {
	
	@Autowired
	private WebSocketService webSocketService;
	
	@MessageMapping("/v2/chat")
	public void gameInfo(InMessage message){
		
		webSocketService.sendTopicMessage("/topic/game_rank", message);
	}
	
}

这两种方法的主要区别在于@SendTo的路径是写死的,SimpMessagingTemplate的路径可以动态设置。

3、给特定的人推送消息

以上都是群发消息,我们可以在路径上绑定id信息,这样就可以给特定的人推送消息了。在WebSocketService 中添加以下方法。

	public void sendChatMessage(InMessage message) {

		template.convertAndSend("/chat/single/"+message.getTo(),new OutMessage(message.getFrom(),message.getContent()));
		
	}
@Controller
public class ChatRoomV3Controller {

	@Autowired
	private WebSocketService webSocketService;
	
	@MessageMapping("v3/single/chat")
	public void singleChat(InMessage message){
		
		webSocketService.sendChatMessage(message);
		
	}
	
}

4、实时数据推送

我们可以使用@Scheduled注解来实现实时的数据推送,先在启用类上添加@EnableScheduling注解

再添加一个方法

	public void sendServerInfo() {
		
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime now = LocalDateTime.now();
		
		template.convertAndSend("/topic/server_info",new OutMessage(now.format(df)));
		
	}

然后直接使用@Scheduled注解一个方法就可以了,每秒推送一次数据

@Controller
public class ServerInfoV4Controller {
	
	@Autowired
	private WebSocketService webSocketService;
	
	@Scheduled(fixedRate = 1000)
	public void sendServerInfo(){
		
		webSocketService.sendServerInfo();
		
	}

}

四、stomp.js 的使用

使用起来也是挺简单的。看注释应该就明白了。要注意的是 subscribe的地址在后台要有,也就是和@SendTo、destination的值对应。

<!DOCTYPE html>
<html>
  <head>
	<meta charset="UTF-8">
	<title>Insert title here</title>
	<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
	<script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
	<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
	<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
	
	<script type="text/javascript">
	    // 建立连接对象(还未发起连接)
	    var socket = new SockJS("http://localhost:8080/endpoint");
	    // 获取 STOMP 子协议的客户端对象
	    var stompClient = Stomp.over(socket);
	    stompClient.debug = null;
	    // 向服务器发起websocket连接并发送CONNECT帧
	    stompClient.connect({},
	    	function connectCallback(frame) {
	            // 连接成功时(服务器响应 CONNECTED 帧)的回调方法
	            setMessageInnerHTML("连接成功");
	            stompClient.subscribe('/topic/server_info', function (res) {
	                re = JSON.parse(res.body);
	                console.log(re);
	                setMessageInnerHTML("")
	                setMessageInnerHTML("你接收到的消息为:" + re.content);
	            });
	        },
	        function errorCallBack(error) {
	            // 连接失败时(服务器响应 ERROR 帧)的回调方法
	            setMessageInnerHTML("连接失败");
	        }
	    );
	
	    //发送消息
	    function send() {
	        var message = $("#content").val();
	        var messageJson = JSON.stringify({ "content": message });
	        stompClient.send("/app/v2/chat", {}, messageJson);
	        sendMessageInnerHTML("/app/v2/chat 你发送的消息:" + message);
	    }
	    
	    //将消息显示在网页上
	    function setMessageInnerHTML(innerHTML) {
	        $("#in").html(innerHTML + '<br/>');
	    }
	    
	    function sendMessageInnerHTML(innerHTML) {
	        $("#out").append(innerHTML + '<br/>');
	    }
	    
		$(function(){
			$("#btn").click(function(){
				send();
			});
			
		})
	</script>

  </head>
<body>
	<input id="content" class="form-control">
	<button id="btn" class="btn btn-info">发送</button>
	<div id="in"></div>
	<div id="out"></div>
</body>
</html>

写在后面的话

还有基于H5的websocket,后面会再写

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值