2012-04-10 10 views
10

Zostało zgłoszone podczas testowania, że ​​czasami można nacisnąć przycisk więcej niż jeden raz, jeśli odpowiedź nie jest renderowana wystarczająco szybko, powodując kilka wywołań kodu wewnętrznego, czego nie chcemy.Jak obsługiwać wiele przesyłek przed renderowaniem odpowiedzi?

Aplikacja jest profilem internetowym Java EE 6 z wykorzystaniem JSF 2.0 wewnątrz Glassfish 3.1.1.

zastanawiałem się, jak to powinno być prawidłowo rozpatrywane, i pomyśleli o kilka scenariuszy:

  • Składanie należy wyłączyć wszystkie przyciski za pomocą JavaScript natomiast odpowiedź jest renderowane.
  • Flaga w zakresie Sesja mówi, że jest już aktywna, więc poufny kod jest pomijany i po prostu przechodzi do ponownego renderowania odpowiedzi dla poprzedniego zgłoszenia.
  • Zsynchronizowany blok opóźniający przetwarzanie do czasu zakończenia poprzedniego żądania. Następnie należy wykryć, że został już przetworzony i pominięty.
  • Używanie jednego z "nowych" zakresów, takich jak konwersja do obsługi wykrywania?

Moje bezpośrednie wrażenie jest takie, że najlepszym podejściem jest posiadanie wrażliwego kodu blokującego atom, ale wtedy problem polega na renderowaniu poprawnej odpowiedzi.

Jak mam się do tego zbliżyć?

+0

Próbowałeś czegoś takiego jak jQuery blockui? Zsynchronizowany blok BTW nie działa w klastrze. –

+0

Nic jeszcze nie zostało wypróbowane. To jest w "dobrze, jak mam to zrobić?" etap. –

Odpowiedz

2

Jak wspomniał Adrian, używałbym również BlockUI. Istnieje BlockUI component z Primefaces. Kiedy przesyłasz swoje formularze przez ajax, możesz również użyć nakładki podczas żądania. Zobacz Primefaces`s Ajax Status na przykład.

10

Przesyłanie powinno wyłączyć wszystkie przyciski przy użyciu javascript podczas renderowania odpowiedzi.

Jest to najłatwiejsze do wdrożenia w sposób ogólny. Jeśli używasz wyłącznie <f:ajax>, możesz użyć jsf.ajax.addOnEvent(), aby wykonać pracę w sposób ogólny. Alternatywnym podejściem JavaScript jest stworzenie rodzaju nakładki "Ładowanie", która blokuje interfejs użytkownika, aby użytkownik końcowy nie mógł już wchodzić w interakcje z podstawową stroną. Jest to w zasadzie bezwzględnie umieszczony ukryty <div>, który obejmuje całą rzutnię z pewnym opacity (przezroczystość). Możesz go pokazać po przesłaniu i ukryć na render. Słowo kluczowe dla tej techniki to "modal dialog". Biblioteki komponentów JSF zorientowanych na UI mają przynajmniej taki komponent już w swoim asortymencie. Na przykład. PrimeFaces z <p:dialog modal="true"> wewnątrz <p:ajaxStatus>, albo <p:blockUI>

Jedyną wadą jest to, że nie będzie działać, jeśli klient ma JS wyłączona lub nie używać go i tym samym nie będzie stanowić przeszkody dla klientów HTTP z podwójnymi twierdzi.


Flaga w zakresie Session mówiąc to jest już aktywne, więc kod wrażliwy jest pomijany i po prostu przechodzi do ponownego renderingu odpowiedzi na poprzednie przedstawienia.

To jest bardziej znany jako "synchronizer token pattern" i nigdy nie zwrócono się do JSF przez spec issue 559, który jest obecnie na bilecie ukierunkowanej na 2.2, ale nie wydaje się być każda aktywność na nim. Część wykrywania i blokowania jest technicznie łatwa do wdrożenia, ale część obsługi synchronicznej odpowiedzi nie jest łatwa do wdrożenia, jeśli chcesz, aby użytkownik końcowy ostatecznie uzyskał odpowiedź wygenerowaną przez początkowe żądanie. Obsługa odpowiedzi asynchronicznej jest łatwa: po prostu nie określaj żadnych składników do aktualizacji, tzn. Opróżnij kolekcję zwróconą przez PartialViewContext#getRenderIds(). W końcu jest to bardziej niezawodne niż używanie JS do wyłączania przycisków lub blokowania interfejsu użytkownika.

O ile mi wiadomo, tylko Seam 2 oferował do tego celu komponent JSF wielokrotnego użytku, <s:token>. Muszę jednak przyznać, że jest to interesujący pomysł na nowy komponent OmniFaces. Może osobiście to przyjrzę.


Zsynchronizowany blok opóźnienia przetwórczego do poprzedniego żądania zakończeniu. Następnie należy wykryć, że został już przetworzony i pominięty.

Nie jest to łatwe do wdrożenia w sposób ogólny, wymagałoby to zmiany wszystkich metod działania w celu sprawdzenia, czy zadanie zostało już wykonane. Nie działa również, jeśli webapp działa na wielu serwerach. Token synchronizatora jest łatwiejszy, ponieważ byłby wykonywany przed wywołaniem metod akcji. Token synchronizatora jest także tańszy, ponieważ nie dostajesz wielu żądań w kolejce, które kosztowałyby tylko wątki/zasoby.


Korzystając z jednego z „nowych” zakresów takich jak konwersja do obsługi wykrywania?

Ten problem nie może zostać rozwiązany przez zabawę z zarządzanymi zakresami fasoli. Zarządzane komponenty bean bean mają inny cel: czas życia instancji komponentu bean.

+0

Jako dodatek do "bloku synchronicznego" możesz również obejrzeć ten filtr - http://onjava.com/onjava/2004/03/24/examples/RequestControlFilter.java –

+0

Dziękuję za bardzo wyczerpującą odpowiedź. Czy masz dodatkowe sugestie, których nie myślałem o sobie? –

+0

Nie ma za co. Nie, nie ma innych sposobów niż używanie JS do wyłączania/blokowania interakcji użytkownika lub używania wzorca tokena synchronizatora. – BalusC

Powiązane problemy