Spring之stomp协议通信

背景

WebSocket协议概念

WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型的应用层。WebSocket协议在2011年由IETF标准化为RFC 6455,后由RFC 7936补充规范。Web IDL中的WebSocket API由W3C标准化。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

上面是维基百科对WebSocket协议的解释,简单的来说就是WebSocket协议与HTTP协议类似都是应用层的协议,只是WebSocket协议是用来解决应用层持久通信的问题。

Streaming Text Oriented Messaging Protocol协议,即STOMP协议。这就是WebSocket的一个子协议,主要就是简化标准的WebSocket开发而生的子协议。

Simple (or Streaming) Text Oriented Message Protocol (STOMP), formerly known as TTMP, is a simple text-based protocol, designed for working with message-oriented middleware (MOM). It provides an interoperable wire format that allows STOMP clients to talk with any message broker supporting the protocol.

STOMP协议从命名就可以看出只能传传简单的文本。

解决

Spring

Maven

pom.xml
主要依赖:

dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-websocketartifactId>
dependency>

WebSocketConfig.java

配置STOMP的对外端点,接入url等信息:

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 {
  @Value("${websocket.domain}")
  private String domain;

	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		// 启用的Broker
		config.enableSimpleBroker("/topic");
		// 设置客户端的发送消息前缀url
		config.setApplicationDestinationPrefixes("/app");
	}

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		// 对外的端点url
		registry.addEndpoint("/gs-guide-websocket").setAllowedOriginPatterns(String.format("https://*.%s", domain))withSockJS();
	}

}

需要注意这里的Origin策略控制设置,如果这里不设置你自己的域名,则会出现在https情况下403问题,而http情况下stomp协议能够正常使用的情况。

Java处理

主要有两种方式,一种是使用Spring注解,一种是Spring编程的方式向客户端发送消息。

GreetingController.java
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;

@Controller
public class GreetingController {

	// 接受客户端发送过来的url,即/app/hello
	@MessageMapping("/hello")
	// 客户端订阅主题
	@SendTo("/topic/greetings")
	public Greeting greeting(HelloMessage message) throws Exception {
		Thread.sleep(1000); // simulated delay
		return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
	}

}

再来看看编码方式的实现:

@Resource private SimpMessagingTemplate simpMessagingTemplate;

使用:

simpMessagingTemplate.convertAndSend("/topic/greetings", "Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");

编程方式主要就是使用SimpMessagingTemplate,编程方式应用的场景多一些。

Greeting.java
public class Greeting {

	private String content;

	public Greeting() {
	}

	public Greeting(String content) {
		this.content = content;
	}

	public String getContent() {
		return content;
	}

}
HelloMessage.java
public class HelloMessage {

	private String name;

	public HelloMessage() {
	}

	public HelloMessage(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

SockJS

在来看前端这边是怎么处理的:

function connect() {
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

function disconnect() {
    if (stompClient !== null) {
        stompClient.disconnect();
    }
    setConnected(false);
    console.log("Disconnected");
}

function sendName() {
    stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}

源代码地址

Spring的websocket stomp Demo项目地址

感受

在网上找了一大圈,也没有找到调试STOMP协议的好工具,调试WebSocket工具倒是有不少。

参考:

  • WebSocket
  • Streaming Text Oriented Messaging Protocol
  • Path variables in Spring WebSockets @SendTo mapping
  • Using WebSocket to build an interactive web application
  • Websocket in Spring Boot app - Getting 403 Forbidden

你可能感兴趣的:(Spring之stomp协议通信)