2013-07-25 39 views
18

Tôi đã thực hiện một tác vụ dài được xác định trong dịch vụ Spring. Nó được khởi động bởi bộ điều khiển Spring MVC. Tôi muốn bắt đầu dịch vụ và trả lại số HttpResponse cho người gọi trước khi dịch vụ kết thúc. Dịch vụ lưu tệp trên hệ thống tệp ở cuối. Trong javascript tôi đã tạo một công việc bỏ phiếu để kiểm tra trạng thái dịch vụ.Sự khác biệt giữa springmvc @Async, DeferredResult, Có thể gọi

Vào mùa xuân 3.2, tôi đã tìm thấy chú thích @Async, nhưng tôi không hiểu chú thích khác với DeferredResultCallable. Khi nào tôi phải sử dụng @Async và khi nào tôi nên sử dụng DeferredResult?

Trả lời

3

DeferredResult tận dụng lợi thế của Servlet 3.0 AsyncContext. Nó sẽ không chặn các chủ đề như những người khác sẽ khi bạn cần một kết quả trả lại.

Một lợi ích lớn khác là DeferredResult hỗ trợ gọi lại.

21

Async chú thích phương thức để nó được gọi không đồng bộ.

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

Vì vậy, mùa xuân có thể làm như vậy bạn cần xác định cách thực hiện. Ví dụ:

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

Bằng cách này khi bạn gọi service.DoSomeWork ("thông số") cuộc gọi được đưa vào hàng đợi của người thi hành được gọi là không đồng bộ. Điều này rất hữu ích cho các tác vụ có thể được thực thi đồng thời.

Bạn có thể sử dụng Async để thực thi bất kỳ tác vụ không đồng bộ nào. Nếu bạn muốn gọi một nhiệm vụ định kỳ, bạn có thể sử dụng @Scheduled (và sử dụng tác vụ: lịch biểu thay vì nhiệm vụ: người thi hành). Chúng được đơn giản hóa cách gọi java Runnables.

DeferredResult <> được sử dụng để trả lời bản kiến ​​nghị mà không chặn chuỗi HTTP Tomcat được sử dụng để trả lời. Thông thường sẽ là giá trị trả về cho một phương thức chú thích 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; 
    } 
} 

Ví dụ trước thiếu một điều quan trọng và nó không hiển thị kết quả trì hoãn sẽ được đặt như thế nào. Trong một số phương thức khác (có thể là phương thức setValue) sẽ có một result.setResult (giá trị). Sau khi cuộc gọi đến setResult Spring sẽ gọi thủ tục onCompletion và trả về câu trả lời cho yêu cầu HTTP (xem https://en.wikipedia.org/wiki/Push_technology#Long_polling).

Nhưng nếu bạn chỉ đang thực hiện đồng bộ setValue thì không có lợi thế nào khi sử dụng kết quả trả về. Đây là nơi Async có trong tay. Bạn có thể sử dụng một phương thức async để đặt giá trị trả về trong một số điểm trong tương lai bằng cách sử dụng một luồng khác.

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

Không cần đồng bộ để sử dụng kết quả trì hoãn, chỉ là một cách để thực hiện.

Trong ví dụ có hàng đợi kết quả bị trì hoãn, ví dụ: tác vụ được lên lịch có thể được giám sát để xử lý yêu cầu đang chờ xử lý của nó. Ngoài ra, bạn có thể sử dụng một số cơ chế không chặn (xem http://en.wikipedia.org/wiki/New_I/O) để đặt giá trị trả lại.

Để hoàn thành bức ảnh, bạn có thể tìm kiếm thông tin về tương lai tiêu chuẩn java (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html) và gọi (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html) có phần tương đương với Spring DeferredResult và Async.

+0

Bạn có thể giải thích 'service.setValue (kết quả) hay không; // Đặt giá trị! ', Ở đây' service' nghĩa là gì? – coderz

+0

Nhìn vào khối mã sau mã đó. Có một ví dụ về cách bạn nên thực hiện phương thức setValue. –

+0

Tại sao bạn cần danh sách "suspendedResults"? Spring không theo dõi các đối tượng trì hoãn? Nếu bạn đang thiết lập kết quả trên một kết quả trì hoãn cụ thể trong SetValue, tôi không thấy lý do tại sao cần cho danh sách các đối tượng trì hoãn này –

Các vấn đề liên quan