2011-10-26 6 views
5

Mam pewne metody w moim kontrolera, który wykonuje @Async zadaniePowrót @Async metoda wynik w Spring MVC i odesłać go do Ajax klienta

@Async 
public Future<String> getResultFromServer(){ 
    String result = ...... 
    return new AsyncResult<String>(result); 
} 

Czas wykonywania metoda jest do 1o minut. Wszystko, co muszę zrobić, to po prostu zwrócić wynik do klienta, który będzie połączony za pomocą AJAX/JQuery.

Nie chcę, aby klient co sekundę prosił mój serwer o wykonanie metody @Async. Chcę tylko, aby moje połączenie było otwarte, a następnie po prostu "wypchnij" wynik na serwer.

@RequestMapping(value="/async.do", method=RequestMethod.POST) 
public void getResult(HttpServletResponse res){ 
    String result = null; 
    PrintWriter out = res.getWriter(); 
    Future<String> future = getResultFromServer(); 
    try { 
     if (future.isDone()) 
      result = future.get(); 
     out.println(result); 
     out.close(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 
} 

Rozumiem, że to bardzo zbliżone do modelu Comit, ale nie znam komety w ogóle.

Moje pytanie brzmi: jak mogę utrzymać połączenie otwarte po stronie klienta przy użyciu JavaScript/JQuery?

i czy moja metoda zostanie przekazana klientowi za pomocą metody @RequestMapping(value="/async.do", method=RequestMethod.POST)?

+1

Jak w końcu rozwiązałeś tę/część 2? – happybuddha

Odpowiedz

2

Najprostszym sposobem nie byłoby wywołanie metody w sposób asynchroniczny, ale wywołanie jej bezpośrednio z kontrolera w sposób synchroniczny.

Następnie żądanie będzie musiało "czekać", aż wynik metody zostanie obliczony, i może zostać zwrócony, gdy tylko zostanie utworzony.

Oczywiście oznacza to, że połączenie będzie otwarte przez czas potrzebny do wykonania pracy (1 minuta).

+0

dziękuję za odpowiedź i za pomysł na wykonanie metody bezpośrednio, mam inną obawę: O ile rozumiem, Tomcat kontynuuje moją prośbę w osobnym wątku, który otwiera się dla mojego połączenia HTTP. Czy to oznacza, że ​​jeśli moja prośba potrwa 15 minut, wątek Tomcat będzie działał przez cały czas? Czy to oznacza, że ​​ta operacja wymaga 2 wątków jeden dla żądania, a drugi dla zadania Async? czy istnieje sposób zawieszenia pierwszego wątku podczas wykonywania drugiego wątku (zadania asynchronicznego)? –

+0

Jeśli używasz '@ async', masz dwa wątki, jeden wywołuje metodę opisaną przez' @ async' i natychmiast zwraca, a drugi naprawdę robi to w metodzie '@ async'. Aby zawiesić pierwszy wątek, po prostu wywołaj future.get(), blokuje to wątek, aż wynik zostanie wygenerowany. Ale jeśli to zrobisz: wywołaj '@ async' i wywołaj metodę future.get() bezpośrednio po oddziałach, wtedy kompletny plik' @ ascync' jest bezużyteczny, ponieważ symulujesz (prawie) normalne zachowanie wywołania metody z dużą ilością technicznych rzeczy. – Ralph

+0

@ danny.lesnik: Ale jeśli twoje obliczenia zajmie 15 minut, to naprawdę potrzebujesz innego rozwiązania niż utrzymywanie połączenia dla tego przedziału czasowego! – Ralph