Spricht Spring @ SubscribeMapping den Client wirklich zu einem bestimmten Thema an?
Bin ich mit Spring Websocket mit STOMP, Einfache Message Broker.
In meinem @Controller
ich benutze method-level -@SubscribeMapping
, sollte das abonnieren des Klienten zu einem Thema, so dass der client Sie empfangen Nachrichten von diesem Thema hinterher. Lassen Sie sagen, der Kunde abonniert das Thema "chat":
stompClient.subscribe('/app/chat', ...);
Als client abonniert "/app/chat", statt "/Thema/chat"dieses Abonnement gehen würde, um die Methode zugeordnet ist, mit @SubscribeMapping
:
@SubscribeMapping("/chat")
public List getChatInit() {
return Chat.getUsers();
}
Hier ist was im Frühjahr ref. sagt:
Standardmäßig ist der Rückgabewert von @SubscribeMapping Methode gesendet wird
als Nachricht direkt an die angeschlossenen client und nicht passieren
durch den broker. Dies ist nützlich für die Durchführung der Anfrage-Antwort -
Nachricht Interaktionen; beispielsweise zum abrufen von Anwendungsdaten, wenn der
Anwendung UI initialisiert wird.
Okay, das war es, was ich wollen würde, aber nur teilweise!! Senden einige init-Daten nach Anmeldung, gut. Aber was abonnieren? Es scheint mir, dass das Ding, was hier passiert, ist nur ein Anfrage-Antwort -wie ein service.
Das Abonnement ist nur konsumiert. Bitte klären Sie mich, wenn dies der Fall ist.
- Hat der Kunde abonnieren Sie einige, wo, wenn der Makler nicht beteiligt ist?
- Wenn ich später möchten Sie uns eine Nachricht an "chat" subscriptors, würde der client empfangen? Es scheint nicht so.
- Die erkennt Abonnements wirklich? Broker? Oder jemand anders?
Wenn hier der client nicht abonniert haben, wo, Frage ich mich, warum nennen wir das "abonnieren"; denn der client erhält nur eine Nachricht und nicht für die künftigen Meldungen.
EDIT:
Um sicherzustellen, dass das Abonnement verwirklicht worden ist, was ich versucht habe ist wie folgt:
SERVER-Seite:
Konfiguration:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
}
Controller:
@Controller
public class GreetingController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
System.out.println("inside greeting");
return new Greeting("Hello, " + message.getName() + "!");
}
@SubscribeMapping("/topic/greetings")
public Greeting try1() {
System.out.println("inside TRY 1");
return new Greeting("Hello, " + "TRY 1" + "!");
}
}
CLIENT-Seite:
...
stompClient.subscribe('/topic/greetings', function(greeting){
console.log('RECEIVED !!!');
});
stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name }));
...
Was würde ich gerne mal passieren:
- Wenn der client abonniert '
/topic/greetings
', die Methodetry1
ist
ausgeführt. - Wenn der client sendet eine Nachricht an '
/app/hello
', es sollte erhalten die Grüße msg wäre@SendTo
'/topic/greetings
'.
Ergebnisse:
-
Wenn der Kunde abonniert
/topic/greetings
die Methodetry1
ist NICHT in der Lage, es zu fangen. -
Wenn der client sendet eine Nachricht an '
/app/hello
',greeting
Methode ausgeführt wurde, und der Kunde erhielt die Grüße Nachricht. So verstanden wir, dass es war abonniert '/topic/greetings
" richtig. -
Aber denken Sie daran 1. war fehlgeschlagen. Nach einigen versuchen, wurde es möglich, wenn der client abonniert
'/app/topic/greetings'
d.h. mit vorangestelltem/app
(Dies ist verständlich von der Konfiguration). -
Nun 1. funktioniert, allerdings dieses mal 2. fehlgeschlagen ist: Wenn der client sendet eine Nachricht an '
/app/hello
', ja,greeting
Methode ausgeführt wurde, aber der client NICHT erhalten haben, die Grüße Nachricht. (Wahrscheinlich, weil jetzt der client abonniert wurde das Thema mit einem Präfix '/app
" war unerwünscht.)
So, was, die ich habe ist entweder 1 oder 2 von dem, was ich möchte, aber nicht diese 2 zusammen.
- Wie kann ich erreichen, das mit dieser Struktur (Konfiguration der mapping-Pfade korrekt) ?
InformationsquelleAutor der Frage Mert Mertce | 2015-03-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
(Hervorhebung von mir)
Hier das Spring-Framework-Dokumentation ist zu beschreiben, was passiert mit den response-Nachrichtnicht die eingehende
SUBSCRIBE
Nachricht.So, deine Fragen zu beantworten:
Mehr auf Abonnement-management
Mit der
SimpleMessageBroker
die message-broker-Implementierung lebt in Ihrer Anwendung Instanz. Abonnements-Anmeldungen werden verwaltet von derDefaultSubscriptionRegistry
.Wenn Sie Nachrichten empfangen, die
SimpleBrokerMessageHandler
GriffeSUBSCRIPTION
Nachrichten und registrieren Abonnements (sehe die Umsetzung hier).Mit einem "echten" message-broker wie RabbitMQ, die Sie konfiguriert haben einen Stomp broker relais, leitet Nachrichten an den broker. In diesem Fall, die
SUBSCRIBE
Nachrichten an den broker, zuständig für die Verwaltung von Abonnements (sehe die Umsetzung hier).Update - mehr auf STOMP Nachrichtenfluss
Wenn man einen Blick auf die Referenz-Dokumentation auf STOMP Nachrichtenflusswirst du sehen, dass:
Also hier
/topic/hello
ist ein broker Ziel; Nachrichten gibt es direkt an den broker. Während/app/hello
ist eine Anwendung, die Ziel, ist und soll zu produzieren, die eine Nachricht gesendet werden, um/topic/hello
es sei denn@SendTo
sagt etwas anderes.Nun Ihre aktualisierte Frage ist irgendwie anders, und ohne eine genauere Anwendungsfall ist es schwer zu sagen, welches Muster ist das beste, diese zu lösen. Hier sind ein paar:
/topic/hello
/topic/hello
/app/hello
mit einem Controller reagiert darauf mit einer Nachricht sofort/app/hello
: verwenden Sie eine Kombination von@MessageMapping
@SendTo
oder eine Nachrichten-Vorlage.Wenn Sie wollen ein gutes Beispiel, dann schauen Sie sich diese chat-Anwendung demonstriert ein Protokoll von Spring websocket-Funktionen mit einem realen Fall.
InformationsquelleAutor der Antwort Brian Clozel
So, dass beide:
Thema zu liefern, eine Verbindung-Antwort
nicht Arbeit als Sie erlebt (wie auch mir).
Den Weg zur Lösung Ihrer situation (wie ich meine) ist:
Umsetzung einer ApplicationListener
Möchten Sie direkt Antworten auf eine einzelne client-Benutzer-Ziel (siehe websocket-stomp-Benutzer-Ziel
oder Sie können auch abonnieren, um eine sub-path z.B. /Thema/my-id-42 haben, dann schicken Sie eine Nachricht zu diesem Unterthema (ich weiß nicht, über Ihre genaue Verwendung Fall, mir ist, habe ich spezielle Abonnements und ich Durchlaufen Sie, wenn ich will, das broadcast)
Senden Sie eine Nachricht in Ihrem onApplicationEvent Methode der ApplicationListener, sobald Sie erhalten eine StompCommand.ABONNIEREN
Abonnement-Event-Handler:
InformationsquelleAutor der Antwort Pauli
Ich konfrontiert mit dem gleichen problem, und schließlich eingeschaltet Lösung, wenn ich Sie abonnieren beide
/topic
und/app
auf einem client, Pufferung alles empfangen/topic
handler bis/app
-gebunden ist, wird man alle herunterladen die chat-history, das ist, was@SubscribeMapping
gibt. Dann habe ich alle Zusammenführen letzten chat-Einträge mit jenen empfangen, die auf einem/topic
- es könnte Duplikate in meinem Fall.Anderen funktionierenden Ansatz war es zu erklären,
Offensichtlich nicht perfekt. Aber hat geklappt 🙂
InformationsquelleAutor der Antwort Stanislav Mamontov