Wiosna: jak wstrzyknąć HttpServletRequest do komponentu bean o zasięgu żądania?

96

Próbuję skonfigurować komponent bean o zakresie żądania wiosnę .

Skonfigurowałem go pomyślnie, więc fasola jest tworzona raz na żądanie. Teraz musi uzyskać dostęp do obiektu HttpServletRequest.

Ponieważ fasola jest tworzona raz na żądanie, domyślam się, że kontener może łatwo wstrzyknąć obiekt żądania do mojego ziarna. Jak mogę to zrobić ?

Leonel
źródło

Odpowiedzi:

115

Fasola o zakresie żądania może być automatycznie związana z obiektem żądania.

private @Autowired HttpServletRequest request;
skaffman
źródło
2
Czy jest na to staroświecki sposób XML?
cherouvim
2
U mnie nie działa (wiosna mvc 3.1) - może jest jeszcze coś do zrobienia? Idąc z rozwiązaniem Samita.
kldavis4
2
Problem polega na tym, że kiedy testujesz walidatory przy użyciu MockMvc i tego rodzaju iniekcji, będziesz miał problemy. Być może inne rozwiązanie będzie preferowane w tym przypadku
Neyko
21
Możliwe jest autowire HttpServletRequest również do beanów bez zakresu żądania, ponieważ dla HttpServletRequest Spring wygeneruje proxy HttpServletRequest, które wie, jak uzyskać rzeczywistą instancję żądania. Dzięki temu automatyczne przesyłanie żądań jest bezpieczne, nawet jeśli kontroler ma pojedynczy zakres.
wtor
3
Ostrzeżenie dla użytkowników Spring <= 3.1, automatyczne okablowanie nie będzie działać podczas testów.
Rubens Mariuzzo
138

Spring ujawnia bieżący HttpServletRequestobiekt (jak również bieżący HttpSessionobiekt) przez obiekt opakowujący typu ServletRequestAttributes. Ten obiekt otoki jest powiązany z ThreadLocal i jest uzyskiwany przez wywołanie staticmetodyRequestContextHolder.currentRequestAttributes() .

ServletRequestAttributeszapewnia metodę getRequest()pobierania bieżącego żądania, getSession()pobierania bieżącej sesji i innych metod pobierania atrybutów przechowywanych w obu zakresach. Poniższy kod, choć nieco brzydki, powinien dostarczyć aktualny obiekt żądania w dowolnym miejscu aplikacji:

HttpServletRequest curRequest = 
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

Zwróć uwagę, że RequestContextHolder.currentRequestAttributes()metoda zwraca interfejs i musi zostać zeskanowana do ServletRequestAttributestego, który implementuje interfejs.


Spring Javadoc: RequestContextHolder | ServletRequestAttributes

samitgaur
źródło
8
Iniekcja jest dobrą rozdzielczością, ale znalazłem problemy z testowaniem MockMvc w walidatorach Spring, które wstrzykują HttpServletRequest. Więc jeśli chcesz, aby zarówno testy próbne, jak i kod produkcyjny działały poprawnie, to powinien być wybór.
Neyko,
@Neyko Dlaczego to jest? dla testu próbnego (test jednostkowy?), możesz wstrzyknąć fałszywy HttpServletRequest lub cokolwiek chcesz .. prawda? Lub możesz użyć MockHttpServletRequest, jak sądzę?
wonhee
Czy można bezpiecznie używać w wystąpieniu usługi o pojedynczym zakresie?
Jin Kwon
2

Jak zasugerowano tutaj , możesz również wstrzyknąć parametr HttpServletRequestjako metodę, np .:

public MyResponseObject myApiMethod(HttpServletRequest request, ...) {
    ...
}
Will Cain
źródło