我有一个使用Stomp over Websocket进行Spring启动的示例。当我将代理注册从SimpleBrokerRegistration更改为StompBrokerRelayRegistration时,它无法正常工作。
这是我的Websocket配置:
subQuery.lessThanOrEqualTo("endDate", convertDate);
subQuery.greaterThanOrEqualTo("createdAt", convertDate);
subQuery.equalTo("type","free");
和ArtemisConfig:
@Configuration
@EnableWebSocketMessageBroker
@ConfigurationProperties(prefix = "spring.artemis")
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
//...
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// If STOMP broker not configured, create an simple fallback
if (!StringUtil.isEmpty(host) || port > 0) {
config.enableStompBrokerRelay("/topic", "/queue")
.setRelayHost(host)
.setRelayPort(port);
} else {
config.enableSimpleBroker("/topic", "/queue");
}
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello")
.withSockJS();
}
//...
}
然后,我使用javascript连接:
@Configuration
@ConfigurationProperties(prefix = "spring.artemis")
public class JmsConfig implements ArtemisConfigurationCustomizer {
private static final String DEFAULT_TRANSPORT_PROTOCOLS = "STOMP";
private String host;
private int port;
private String protocols;
// ...
@Override
public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) {
host = StringUtil.hasText(host)?host:TransportConstants.DEFAULT_HOST;
port = port > 0? port:TransportConstants.DEFAULT_PORT;
protocols = StringUtil.hasText(protocols)?protocols:DEFAULT_TRANSPORT_PROTOCOLS;
Set<TransportConfiguration> acceptors = configuration.getAcceptorConfigurations();
Map<String, Object> params = new HashMap<>();
params.put(TransportConstants.HOST_PROP_NAME, host);
params.put(TransportConstants.PORT_PROP_NAME, port);
params.put(TransportConstants.PROTOCOLS_PROP_NAME, protocols);
TransportConfiguration tc = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
acceptors.add(tc);
}
//...
}
它说无法找到队列/主题/问候
当我像这样使用SimpMessagingTemplate时:
var socket = new SockJS('/hello');
stompClient = Stomp.over(socket);
stompClient.connect('guest', 'guest', function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function(greeting){
showGreeting(greeting.body);
});
});
它抛出一个错误:
messagingTemplate.convertAndSend("/topic/greetings", "WARN: " + warningString());
我不知道为什么它不能用作SimpleBroker。
答案 0 :(得分:1)
您是否事先在Artemis broker.xml中创建了此目的地?与ActiveMQ不同,您必须这样做,或者在地址设置块中指定自动创建,如下所示:
<!--default for catch all-->
<address-setting match="#">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<expiry-address>jms.queue.ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
<max-size-bytes>10485760</max-size-bytes>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
<address-full-policy>BLOCK</address-full-policy>
<auto-create-jms-queues>true</auto-create-jms-queues>
</address-setting>
在这种情况下,将创建任何目的地。但是,这里有一个问题。定义队列时,如下所示:
<queue name="selectorQueue">
<entry name="/queue/selectorQueue"/>
<selector string="color='red'"/>
<durable>true</durable>
</queue>
它实际上将遵循jms命名约定,并且实际名称为jms.queue.selectorQueue
。您也可以尝试映射到该名称。
答案 1 :(得分:0)
由于我不知道的某些原因,Artemis(使用Stomp协议)似乎期望主题名称以jms.topic.
开头,队列名称jms.queue.
因此,请将您的主题重命名为jms.topic.greetings
,并确保您还将StompBrokerRelay配置更改为:
config.enableStompBrokerRelay("jms.topic", "jms.queue")
在此设置中,将在需要时自动创建队列/主题。
(我使用的是Artemis 1.3。)
答案 2 :(得分:0)
对于在 2021 年寻找如何使用 Spring 的 SimpMessageSendingOperations
(STOMP) 和嵌入式 ActiveMQ Artemis 的人?花了半天时间,我可以告诉你。
添加以下依赖(因为目前有依赖冲突,自己找最新版本)。由于某种原因,spring 目前需要 reactor-netty
,您可以尝试在没有它的情况下运行。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-server</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-stomp-protocol</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</dependency>
创建以下配置类。这是将嵌入式 artemis 服务器暴露给外部虚拟机连接所必需的。据我所知,默认情况下只使用虚拟机内连接,我还没有找到一种方法来利用这些与 stomp 中继。
@Configuration
public class ArenaArtemisConfiguration {
private final ArtemisProperties artemisProperties;
public ArenaArtemisConfiguration(ArtemisProperties artemisProperties) {
this.artemisProperties = artemisProperties;
}
@Bean
public ArtemisConfigurationCustomizer customizer() {
return configuration -> {
try {
configuration.addAcceptorConfiguration(
"netty", "tcp://" + artemisProperties.getHost() + ":" + artemisProperties.getPort()
);
} catch (Exception e) {
throw new IllegalStateException(e);
}
};
}
}
将以下内容添加到您的 application.yml
spring.artemis:
mode: embedded
host: localhost
port: 61616
通过中继配置一个 webSocket 消息代理(在我们的例子中是 artemis)
@Configuration
public class WebSocketConfiguration extends DelegatingWebSocketMessageBrokerConfiguration {
private final ArtemisProperties artemisProperties;
public WebSocketConfiguration(ArtemisProperties artemisProperties) {
this.artemisProperties = artemisProperties;
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableStompBrokerRelay("/your-topics")
.setRelayHost(artemisProperties.getHost())
.setRelayPort(artemisProperties.getPort());
}
}
其余的应该与 enableSimpleBroker
相同。