2013-07-25 2 views
18

У меня есть долговременная задача, определенная в службе Spring. Он запускается контроллером Spring MVC. Я хочу запустить службу и вернуть вызывающему абоненту HttpResponse до окончания обслуживания. Служба сохраняет файл в файловой системе в конце. В javascript я создал опрос, чтобы проверить статус сервиса.Разница между springmvc @Async, DeferredResult, Callable

Весной 3.2 Я нашел аннотацию @Async, но я не понимаю, как она отличается от DeferredResult и Callable. Когда мне нужно использовать @Async и когда следует использовать DeferredResult?

ответ

3

DeferredResult использует сервлет 3.0 AsyncContext. Он не будет блокировать поток, как другие, когда вам нужно вернуть результат.

Другим преимуществом является то, что DeferredResult поддерживает обратные вызовы.

21

Async аннотирует метод, поэтому он будет вызываться асинхронно.

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

Таким образом, Spring может сделать это, чтобы определить, как это будет выполнено. Например:

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

Таким образом, когда вы звоните service.DoSomeWork («параметр») вызов помещается в очередь исполнителя, чтобы называться асинхронно. Это полезно для задач, которые могут выполняться одновременно.

Вы можете использовать Async для выполнения любой асинхронной задачи. Если вы хотите периодически вызывать задачу, вы можете использовать @Scheduled (и использовать задачу: планировщик вместо задачи: исполнитель). Это упрощенные способы вызова java Runnables.

DeferredResult <> Используется для ответа на ходатайство, не блокируя поток HTTP Tomcat, используемый для ответа. Обычно это будет возвращаемое значение для аннотированного метода ResponseBody.

@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; 
    } 
} 

В предыдущем примере не хватает одной важной вещи, и это, что не показывает, как отложенный результат будет установлен. В каком-то другом методе (вероятно, метод setValue) будет создан result.setResult (значение). После вызова setResult Spring вызывается процедура onCompletion и возвращает ответ на HTTP-запрос (см. https://en.wikipedia.org/wiki/Push_technology#Long_polling).

Но если вы просто выполняете setValue синхронно, нет никакого преимущества в использовании отложенного результата. Здесь находится Async. Вы можете использовать метод async для установки возвращаемого значения в какой-то момент в будущем с использованием другого потока.

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

Async не требуется для использования отложенного результата, его единственным способом сделать это.

В примере есть очередь отложенных результатов, которые, например, могут быть запланированы для выполнения запланированных задач для обработки ожидающих запросов. Также вы можете использовать некоторый механизм блокировки (см. http://en.wikipedia.org/wiki/New_I/O), чтобы установить возвращаемое значение.

Для завершения картины вы можете найти информацию о стандартных фьючерсах java (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html) и вызовах (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html), которые в некоторой степени эквивалентны Spring DeferredResult и Async.

+0

Не могли бы вы объяснить 'service.setValue (результат); // Устанавливает значение! ', Здесь что означает' service'? – coderz

+0

Посмотрите на блок кода после этого. Существует пример того, как вы должны реализовать метод setValue. –

+0

Зачем вам нужен список "suspResults"? Разве Spring не отслеживает отложенные объекты? Если вы задаете результат по определенному отложенному результату в SetValue, я не понимаю, почему потребность в этом списке объектов с отсрочкой –

Смежные вопросы