注意:请参见问题底部的更新内容,了解我最终得出的结论。
我需要通过Web套接字向发送请求消息的客户端发送多个响应,第一个响应需要快速返回,其他响应需要在数据验证后(大约在10到60秒之间,来自多个并行线程)发送。
我遇到了一些问题,无法将后续响应仅发送到初始Web套接字。我该如何做才能让它们只发送到初始Web套接字?或者,我应该使用Spring STOMP以外的东西(因为说实话,我只想要将消息路由到各种函数,我不需要也不想要广播到其他Web套接字,所以我认为我可以编写自己的消息分发器,即使这是重新发明轮子)。
我没有使用Spring身份验证(这是针对旧代码进行的改进)。
在初始返回消息中,我可以使用@SendToUser,即使我们没有用户,Spring也只会将返回值发送到发送消息的Web套接字。(请参见this question)。
尽管响应速度较慢,我认为我需要使用SimpMessagingTemplate.convertAndSendToUser(user, destination, message),但是我不能这样做,因为我必须传递用户,而我无法弄清楚@SendToUser使用了哪个用户。我尝试按照此问题中的步骤进行操作,但在未经身份验证时无法使其工作(此时principal.getName()返回null)。
为了原型设计,我已大大简化了此过程,因此不必担心线程同步或其他任何事情。我只想让Web套接字正常工作。
以下是我的控制器:
我需要通过Web套接字向发送请求消息的客户端发送多个响应,第一个响应需要快速返回,其他响应需要在数据验证后(大约在10到60秒之间,来自多个并行线程)发送。
我遇到了一些问题,无法将后续响应仅发送到初始Web套接字。我该如何做才能让它们只发送到初始Web套接字?或者,我应该使用Spring STOMP以外的东西(因为说实话,我只想要将消息路由到各种函数,我不需要也不想要广播到其他Web套接字,所以我认为我可以编写自己的消息分发器,即使这是重新发明轮子)。
我没有使用Spring身份验证(这是针对旧代码进行的改进)。
在初始返回消息中,我可以使用@SendToUser,即使我们没有用户,Spring也只会将返回值发送到发送消息的Web套接字。(请参见this question)。
尽管响应速度较慢,我认为我需要使用SimpMessagingTemplate.convertAndSendToUser(user, destination, message),但是我不能这样做,因为我必须传递用户,而我无法弄清楚@SendToUser使用了哪个用户。我尝试按照此问题中的步骤进行操作,但在未经身份验证时无法使其工作(此时principal.getName()返回null)。
为了原型设计,我已大大简化了此过程,因此不必担心线程同步或其他任何事情。我只想让Web套接字正常工作。
以下是我的控制器:
@Controller
public class TestSocketController
{
private SimpMessagingTemplate template;
@Autowired
public TestSocketController(SimpMessagingTemplate template)
{
this.template = template;
}
// This doesn't work because I need to pass something for the first parameter.
// If I just use convertAndSend, it broacasts the response to all browsers
void setResults(String ret)
{
template.convertAndSendToUser("", "/user/topic/testwsresponse", ret);
}
// this only sends "Testing Return" to the browser tab hooked to this websocket
@MessageMapping(value="/testws")
@SendToUser("/topic/testwsresponse")
public String handleTestWS(String msg) throws InterruptedException
{
(new Thread(new Later(this))).start();
return "Testing Return";
}
public class Later implements Runnable
{
TestSocketController Controller;
public Later(TestSocketController controller)
{
Controller = controller;
}
public void run()
{
try
{
java.lang.Thread.sleep(2000);
Controller.setResults("Testing Later Return");
}
catch (Exception e)
{
}
}
}
}
记录一下,这是浏览器端:
var client = null;
function sendMessage()
{
client.send('/app/testws', {}, 'Test');
}
// hooked to a button
function test()
{
if (client != null)
{
sendMessage();
return;
}
var socket = new SockJS('/application-name/sendws/');
client = Stomp.over(socket);
client.connect({}, function(frame)
{
client.subscribe('/user/topic/testwsresponse', function(message)
{
alert(message);
});
sendMessage();
});
});
这里是配置:
@Configuration
@EnableWebSocketMessageBroker
public class TestSocketConfig extends AbstractWebSocketMessageBrokerConfigurer
{
@Override
public void configureMessageBroker(MessageBrokerRegistry config)
{
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/queue", "/topic");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
{
registry.addEndpoint("/sendws").withSockJS();
}
}
更新:由于存在可能通过其他WebSocket发送信息的安全问题,我建议我的团队不要使用Spring 4.0实现的STOMP over Web Sockets。我理解Spring团队为什么这样做,它比我们需要的更强大,但是我们项目的安全限制非常严格,实际需求又非常简单,所以我们决定走另一条路。这并不否定下面的答案,因此请根据您的项目需求自行决定。至少我们希望所有人都了解技术的局限性,无论好坏。