2013-07-25 12 views
18

Ich habe eine lange laufende Aufgabe in einem Spring-Service definiert. Es wird von einem Spring MVC Controller gestartet. Ich möchte den Dienst starten und eine HttpResponse an den Anrufer zurückgeben, bevor der Dienst beendet wird. Der Dienst speichert am Ende eine Datei im Dateisystem. In Javascript habe ich einen Abrufauftrag erstellt, um den Dienststatus zu überprüfen.Unterschied zwischen springmvc @ Async, DeferredResult, Callable

Im Frühjahr 3.2 Ich habe die @Async Annotation gefunden, aber ich verstehe nicht, wie es sich von DeferredResult und Callable unterscheidet. Wann muss ich @Async verwenden und wann sollte ich DeferredResult verwenden?

Antwort

3

DeferredResult nutzt den Servlet 3.0 AsyncContext. Es blockiert den Thread nicht wie die anderen, wenn Sie ein Ergebnis benötigen.

Ein weiterer großer Vorteil ist, dass DeferredResult Rückrufe unterstützt.

21

Async kommentiert eine Methode, so dass sie asynchron aufgerufen wird.

@org.springframework.stereotype.Service 
public class MyService { 
    @org.springframework.scheduling.annotation.Async 
    void DoSomeWork(String url) { 
     [...] 
    } 
} 

So Spring könnte tun, müssen Sie definieren, wie ausgeführt wird. Zum Beispiel:

<task:annotation-driven /> 
<task:executor id="executor" pool-size="5-10" queue-capacity="100"/> 

diese Weise, wenn Sie service.DoSomeWork („Parameter“) der Anruf Anruf in die Warteschlange des Testamentsvollstreckers gesetzt wird asynchron aufgerufen werden. Dies ist nützlich für Aufgaben, die gleichzeitig ausgeführt werden können.

Sie können Async verwenden, um jede Art von asynchroner Task auszuführen. Wenn Sie eine Aufgabe regelmäßig aufrufen möchten, können Sie @Scheduled verwenden (und task: scheduler statt task: executor verwenden). Sie sind vereinfachte Möglichkeiten, Java-Runnables aufzurufen.

DeferredResult <> wird verwendet, um auf eine Petition zu antworten, ohne den HTTP-Thread von Tomcat zu blockieren, der zur Beantwortung verwendet wird. Normalerweise wird der Rückgabewert für eine responseBody-Methode mit Annotationen angegeben.

@org.springframework.stereotype.Controller 
{ 
    private final java.util.concurrent.LinkedBlockingQueue<DeferredResult<String>> suspendedRequests = new java.util.concurrent.LinkedBlockingQueue<>(); 

    @RequestMapping(value = "/getValue") 
    @ResponseBody 
    DeferredResult<String> getValue() { 
      final DeferredResult<String> result = new DeferredResult<>(null, null); 
      this.suspendedRequests.add(result); 
      result.onCompletion(new Runnable() { 
      @Override 
      public void run() { 
     suspendedRequests.remove(result); 
      } 
}); 
      service.setValue(result); // Sets the value! 
      return result; 
    } 
} 

Im vorherigen Beispiel fehlt eine wichtige Sache, und es ist, dass nicht zeigen, wie das latente Ergebnis eingestellt werden soll. In einer anderen Methode (wahrscheinlich der setValue-Methode) wird es ein result.setResult (value) geben. Nach dem Aufruf von setResult Spring wird die onCompletion-Prozedur aufgerufen und die Antwort an die HTTP-Anforderung zurückgegeben (siehe https://en.wikipedia.org/wiki/Push_technology#Long_polling).

Aber wenn Sie gerade den setValue synchron ausführen, gibt es keinen Vorteil bei der Verwendung eines verzögerten Ergebnisses. Hier ist Async in der Hand. Sie können eine asynchrone Methode verwenden, um den Rückgabewert zu einem späteren Zeitpunkt mit einem anderen Thread festzulegen.

@org.springframework.scheduling.annotation.Async 
    void SetValue(DeferredResult<String> result) { 
     String value; 
     // Do some time consuming actions 
     [...] 
     result.setResult(value); 
    } 

Async ist nicht erforderlich, um ein verzögertes Ergebnis zu verwenden, es ist nur eine Möglichkeit, dies zu tun.

Im Beispiel gibt es eine Warteschlange mit verzögerten Ergebnissen, bei der z. B. eine geplante Aufgabe überwacht werden könnte, um ihre ausstehenden Anforderungen zu verarbeiten. Sie können auch einen nicht blockierenden Mechanismus verwenden (siehe http://en.wikipedia.org/wiki/New_I/O), um den Rückgabewert festzulegen.

Um das Bild zu vervollständigen, könnten Sie Informationen über Java-Standard-Futures (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html) und Callables (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html) suchen, die Spring DefredredResult und Async ähnlich sind.

+0

Können Sie 'service.setValue (result) erklären; // Setzt den Wert! ', Was bedeutet' service'? – coderz

+0

Schauen Sie sich den Code danach an. Dort finden Sie ein Beispiel dafür, wie Sie die setValue-Methode implementieren sollten. –

+0

Warum brauchen Sie die Liste "suspendedResults"? Verfolgt Spring nicht die verzögerten Objekte? Wenn Sie das Ergebnis für ein bestimmtes Deferred-Ergebnis in SetValue festlegen, sehe ich nicht, warum diese Liste der verzögerten Objekte erforderlich ist –

Verwandte Themen