2014-12-16 2 views
6

Ich benutze einen Spring MVC-Controller und möchte die Ausführung einer Aufgabe starten ich einen neuen Thread. Der Thread sollte jedoch nicht sofort starten, sondern erst nachdem die Antwort an den Client gesendet wurde.Spring Controller starten Verarbeitung nach Antwort gesendet wird

Mittel - in strengen zeitlichen Reihenfolge:

  1. Anfrage
  2. Rückkehr neue ResponseEntity .../Kunde erhält Status Http 200 ok.
  3. beginnt die Verarbeitung der Aufgabe.

Wie erreiche ich das?

Ich wollte Spring async Abstraktion verwenden, Aufruf einer Methode mit @ Async kommentiert, aber auf diese Weise habe ich nicht garantieren, dass der neue Thread wartet auf die Antwort gesendet werden.

+0

Können Sie uns zeigen, was Sie bisher gemacht haben? – Marv

Antwort

8

Sie können einen Interceptor dafür verwenden.Die Reihenfolge oder Ereignisse für eine Anfrage in Spring MVC ist die Handhabung:

  • DispatcherServlet einen Request, Response Paar erhalten und bestimmt die Handhabung
  • [optional] Abfangjäger preHandle sind aufgerufen (mit Option Verarbeitung zu stoppen)
  • Controller heißt
  • [optional] Abfangjäger postHandle
  • ViewResolver und Sicht tun, um die tatsächlichen Responsebearbeitung und senden Sie die Antwort
  • [optional] Abfangjäger afterComp genannt werden letion heißen

Die oben über simplificated und richtet sich gerade in diesem Interceptor afterCompletion Methoden zeigt aufgerufen werden, nachdem die Reaktion auf Client gesendet wurde, mit folgenden Signatur:

void afterCompletion(HttpServletRequest request, 
        HttpServletResponse response, 
        Object handler, 
        Exception ex) 
        throws Exception 

Bei diesem Verfahren Sie können das Auftreten einer Ausnahme und die Korrektheit der Antwort (ex == null && response.getStatus == HttpServletResponse.SC_OK) testen, bevor Sie mit der Verarbeitung beginnen.

+1

@Hille hat schon die Idee gegeben, aber ich habe diese Antwort vorbereitet und erst nach dem Posten gesehen. –

+0

Gebe mir eine Empfehlung und alles ist in Ordnung :-). – Hille

+0

@Hille: Sie haben es wirklich verdient! –

0

Sie können die Aufgabe zu einer blockierenden Warteschlange hinzufügen, bevor die Antworteinheit erstellt wird. Lassen Sie einen Task Executor regelmäßig (alle x Sekunden) über die Warteschlange laufen und nach Tasks suchen. Wenn eine Aufgabe gefunden wird, wird sie ausgeführt. Wenn nicht, beendet der Thread seine Laufmethode und wartet auf den nächsten Lauf (in x Sekunden).

, wie eine Aufgabe periodisch auszuführen: http://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/

die Warteschlange als Abhängigkeit sowohl die Steuerung injizieren und die Aufgabe Exekutor-Service. Dies sollte eine einfache Lösung für den Anfang sein.

In diesem Szenario können Sie nicht sicher sein, dass der Client die Anfrage erhält. Wenn Sie jedoch sicher sein möchten (r), fügen Sie Ihrem Aufgabenobjekt ein Fälligkeitsdatum mit einem ausreichenden Versatz hinzu (z. B. aktuelle Zeit + 30 Sekunden). Lassen Sie den Task-Executor prüfen, ob das Fälligkeitsdatum der abgefragten Task jetzt oder in der Vergangenheit liegt. Ansonsten ignorieren Sie die Aufgabe für diesen Lauf.

3

Wenn Ihre Anforderung "nach Antwort gesendet" mit "nachdem die Ansicht gerendert wurde" erfüllt wird, können Sie eine Implementierung von HandlerInterceptor verwenden. Für ein Beispiel vgl. Spring 3 MVC Interceptor tutorial with example, löst Ihren Job in afterCompletion.

Wenn Ihr Job ausgelöst werden muss, "nachdem es den Draht getroffen hat", würde ich gerne wissen, warum.

Verwandte Themen