如何在Spring服务器中关闭STOMP WebSocket

8
我正在使用spring-websocket和spring-messaging(版本4.2.2.RELEASE)实现带有完整功能代理的STOMP over websockets(Apache ActiveMQ 5.10.0)。我的客户端只能订阅目标,即它们不应该能够发送消息。此外,我想对客户端可以订阅的目标进行更严格的控制。无论哪种情况(即当客户端尝试发送消息或订阅无效目标时),我都希望能够:
  1. 发送适当的错误信息,和/或
  2. 关闭websocket连接
请注意,我所有的目标都被转发到ActiveMQ。我认为我可以在入站通道上实现 ChannelInterceptor,但是查看API后,我无法弄清如何实现我想要的功能。这是否可能?验证客户端请求的最佳方法是什么?我的websocket配置如下:
<websocket:message-broker
    application-destination-prefix="/app">
    <websocket:stomp-endpoint path="/pushchannel"/>
    <websocket:stomp-broker-relay relay-host="localhost"
        relay-port="61613" prefix="/topic"
        heartbeat-receive-interval="300000" heartbeat-send-interval="300000" />
    <websocket:client-inbound-channel>
        <websocket:interceptors>
            <bean class="MyClientMessageInterceptor"/>
        </websocket:interceptors>
    </websocket:client-inbound-channel>
</websocket:message-broker>
1个回答

0
你可以编写一个入站拦截器并向客户端发送适当的错误信息。
public class ClientInboundChannelInterceptor extends ChannelInterceptorAdapter {

@Autowired
private SimpMessagingTemplate simpMessagingTemplate;

@Override
public Message<?> preSend(Message message, MessageChannel channel) throws IllegalArgumentException{
    StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
    logger.debug("logging command " + headerAccessor.getCommand());
    try {
          //write your logic here
        } catch (Exception e){
            throw new MyCustomException();
        }
    }

}

更新:

1)当您从ClientInboundChannelInterceptor抛出任何异常时,它将作为ERROR帧发送,您无需进行任何特殊处理。

2)我不确定如何关闭连接,但是执行类似于创建DISCONNECT头并发送它的操作应该可以(我将尝试测试并更新答案)。

SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.DISCONNECT);
headerAccessor.setSessionId(sessionId);
headerAccessor.setLeaveMutable(true);

template.convertAndSendToUser(destination,new HashMap<>(),headerAccessor.getMessageHeaders());

在订阅时发送错误,您有以下两个选项:

1)从ClientInboundChannelInterceptor中抛出异常。

2)在您的Handler/Controller中添加@SubscribeMapping并返回帧。

@SubscribeMapping("your destination")
public ConnectMessage handleSubscriptions(@DestinationVariable String userID, org.springframework.messaging.Message message){
    // this is my custom class
    ConnectMessage frame= new ConnectMessage();
    // write your logic here
    return frame;
}

frame 将直接发送给客户端。


这是一个好主意,但是,1)你如何使用SimpMessagingTemplate发送STOMP ERROR帧?2)你如何撕掉/关闭websocket? - Nenad
@Nenad 更新了答案,请尝试第二部分并告诉我是否有效。 - Karthik
@Kathrik 如果我抛出异常,那么我将放弃线程的控制权,并且无法进行断开连接。你知道是否有一种方法可以发送ERROR帧而不抛出异常吗? - Nenad
看了你的示例和API,似乎可以发送一个ERROR帧而不抛出异常:你可以使用StompHeaderAccessor.create(StompCommand.ERROR),然后使用SimpMessagingTemplate发送它。我会看看这是否可行... - Nenad
在你的回答更新中的第2点中,你将destination设置为什么?我的理解是destination是客户端订阅的STOMP目标。那么当发送一个无效的订阅请求的ERROR帧时,我应该使用什么作为目标呢? - Nenad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接