Примечание: см. обновление в нижней части вопроса для того, что я в итоге сделал.
Мне нужно отправить несколько ответов на запрос через веб-сокет, который отправил сообщение с запросом, первое быстро, а остальные после проверки данных (где-то между 10 и 60 секундами позже, из нескольких параллельных потоков).
У меня возникли проблемы с получением последующих ответов, чтобы остановить трансляцию по всем открытым веб-сокетам. Как заставить их отправлять только исходный веб-сокет? Или я должен использовать что-то помимо Spring STOMP (потому что, честно говоря, все, что я хочу, это маршрутизация сообщений к различным функциям, мне не нужна или не требуется возможность трансляции в другие веб-сокеты, поэтому я подозреваю, что могу написать сам распространитель сообщений, хотя он изобретает колесо).
Я не использую Spring Аутентификация (это переоснащается в устаревший код).
В исходном обратном сообщении я могу использовать @SendToUser, и даже если у нас нет пользователя, Spring отправляет только возвращаемое значение в веб-ячейку, отправившую сообщение. (см. этот вопрос).
С более медленными ответами, я думаю, мне нужно использовать SimpMessagingTemplate.convertAndSendToUser(пользователь, адрес, сообщение), но я не могу, потому что мне нужно передать его пользователю, и я не могу понять, что используется пользователь @SendToUser. Я попытался выполнить шаги в этом вопросе, но не смог заставить его работать, когда не аутентифицирован (в этом случае имя_имя() возвращает null).
Я значительно упростил это для прототипа, поэтому не беспокойтесь о синхронизации потоков или чего-то еще. Я просто хочу, чтобы веб-сокеты работали правильно.
Вот мой контроллер:
@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();
}
}
ОБНОВЛЕНИЕ. Из-за проблем безопасности, связанных с возможностью отправки информации по другим веб-сайтам, чем исходный сокет, я решил рекомендовать моей группе, что мы не используем реализацию STOMP Spring 4.0 через веб-сокеты. Я понимаю, почему команда Spring сделала это так, как они это делали, и это больше, чем нам нужно, но ограничения безопасности в нашем проекте были достаточно серьезными, и фактические требования были достаточно простыми, и мы решили пойти другой путь. Это не приводит к недействительности ответов ниже, поэтому сделайте свое собственное решение в соответствии с вашими проектами. По крайней мере, мы надеемся, что все узнали об ограничениях технологии, хорошо или плохо.