2013-07-20 12 views
8

Mam klasę pojedynczej instancji, implementując ExceptionMapper. Nie jest to klasa statyczna, ale jest to klasa, dla której wiem, że tworzone jest tylko jedno wystąpienie (zaznaczyłem - konstruktor jest wywoływany tylko raz).JAX-RS (Jersey) ExceptionMapper - wstrzyknięcie @Context do klasy statycznej/singleton - działa, ale dlaczego?

Moja klasa używa @Context HttpServletRequest i mogę jednoznacznie stwierdzić, że kiedy mój ExceptionMapper.toResponse() metoda nazywa się „żądanie” przez @Context parametr ma wartość, która jest istotna dla wniosku gdzie wyjątek jest rzucany.

The doc says jest to rzeczywiście funkcja wspierana przez projekt i odbywa się za pomocą "serwerów proxy".

Zastanawiam się, jak dokładnie to zostało zaimplementowane - w jaki sposób pojedyncza instancja może mieć jednocześnie różne wartości zmiennych członkowskich?

Dziękuję
AG

PS: Oto kod testu:

@Provider 
public class MyExceptionMapper implements ExceptionMapper<Exception> { 

    public MyExceptionMapper() { 
     System.out.println("CTOR!!"); 
    } 

    @Context HttpServletRequest req; 

    public static boolean done = false; 
    public Response toResponse(Exception ex) { 
     if (!done) { 
      done = true; 
      Thread.sleep(10000); 
     } 
     System.out.println(req.getRequestURI()); 
     return null; 
    } 
} 

Moja metoda obsługi REST rzuca wyjątek, więc kiedy wykonać następujące 2 wnioski "równolegle" (sen powyżej pilnuje pierwszy nie jest zakończone, gdy drugi przybywa i IMHO należy zmodyfikować-and-tylko jedno pole „zamów”):

- http://localhost/app/one 
- http://localhost/app/two 

Mój program drukuje:

CTOR! 
http://localhost/app/one 
http://localhost/app/two 

Odpowiedz

5

Najprostszym sposobem uzyskania efektu zauważalna jest dla zatłoczonego HttpServletRequest obiektu faktycznie być obiektem proxy, nitki świadomy delegat na rzeczywistymHttpServletRequest. Kiedy wywołujesz metody na delegacie, wszystko, co robią, polega na sprawdzeniu poprawnego rzeczywistego obiektu (np. Za pośrednictwem zmiennej lokalnej wątku) i przekazaniu wywołania na to. Ta strategia jest stosunkowo prosta, a ponieważ jest to interfejs, zdecydowanie nie musimy się martwić o dostępy terenowe (które są nieco trudniejsze do obsługi proxy).

Istnieje kilka różnych sposobów skonstruowania takiego obiektu proxy. W szczególności można to osiągnąć poprzez bezpośrednie wdrożenie interfejsu HttpServletRequest, lub można to zrobić bardziej ogólnie za pomocą Java general dynamic proxy mechanism (która może zbudować proxy dla dowolnego interfejsu). Istnieją inne, bardziej rozbudowane możliwości, takie jak generowanie kodu runtime, ale tutaj nie są potrzebne. OTOH, nie byłbym wcale zaskoczony, gdyby HttpServletRequest został bezpośrednio zaimplementowany; jest to dość ważna klasa dla implementacji JAX-RS ...

Powiązane problemy