Spring: Wie injiziere ich eine HttpServletRequest in eine Bean mit Anforderungsbereich?

95

Ich versuche, im Frühjahr eine Bean mit Anforderungsbereich einzurichten .

Ich habe es erfolgreich eingerichtet, sodass die Bean einmal pro Anfrage erstellt wird. Jetzt muss es auf das HttpServletRequest-Objekt zugreifen.

Da die Bean einmal pro Anforderung erstellt wird, kann der Container das Anforderungsobjekt problemlos in meine Bean einfügen. Wie kann ich das machen ?

Leonel
quelle

Antworten:

113

Beans mit Anforderungsbereich können mit dem Anforderungsobjekt automatisch verdrahtet werden.

private @Autowired HttpServletRequest request;
Skaffman
quelle
2
Gibt es dafür einen altmodischen XML-Weg?
Cherouvim
2
Funktioniert bei mir nicht (spring mvc 3.1) - vielleicht muss noch etwas getan werden? Mit Samits Lösung gehen.
kldavis4
2
Das Problem ist, dass beim Testen von Validatoren mit MockMvc und dieser Art der Injektion Probleme auftreten.
Möglicherweise
21
Es ist möglich, HttpServletRequest auch automatisch in Beans ohne Anforderungsbereich zu verdrahten, da Spring für HttpServletRequest einen Proxy HttpServletRequest generiert, der weiß, wie die tatsächliche Instanz der Anforderung abgerufen wird. So ist es sicher, eine automatische Drahtanforderung anzufordern, selbst wenn Ihr Controller einen Singleton-Bereich hat.
Vtor
3
Warnung für Spring <= 3.1-Benutzer funktioniert das automatische Verdrahten nicht, wenn Tests ausgeführt werden.
Rubens Mariuzzo
138

Spring macht das aktuelle HttpServletRequestObjekt (sowie das aktuelle HttpSessionObjekt) durch ein Wrapper- Objekt vom Typ verfügbarServletRequestAttributes . Dieses Wrapper-Objekt ist an ThreadLocal gebunden und wird durch Aufrufen der staticMethode abgerufen RequestContextHolder.currentRequestAttributes().

ServletRequestAttributesBietet die Methode getRequest()zum Abrufen der aktuellen Anforderung, getSession()zum Abrufen der aktuellen Sitzung und andere Methoden zum Abrufen der in beiden Bereichen gespeicherten Attribute. Der folgende Code ist zwar etwas hässlich, sollte Ihnen jedoch das aktuelle Anforderungsobjekt an einer beliebigen Stelle in der Anwendung anzeigen:

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

Beachten Sie, dass die RequestContextHolder.currentRequestAttributes()Methode eine Schnittstelle zurückgibt und typisiert werden muss ServletRequestAttributes, um die Schnittstelle zu implementieren.


Spring Javadoc: RequestContextHolder | ServletRequestAttributes

Samitgaur
quelle
8
Die Injektion hat eine gute Auflösung, aber ich habe Probleme beim Testen von Spring-Validatoren durch MockMvc festgestellt, die HttpServletRequest injizieren. Wenn Sie also möchten, dass sowohl Mock-Tests als auch Produktionscode ordnungsgemäß ausgeführt werden, sollten Sie die richtige Wahl treffen.
Neyko
@Neyko Warum ist es? Für einen Mock-Test (Unit-Test?) können Sie Mock-HttpServletRequest oder was auch immer Sie wollen injizieren, nicht wahr? Oder können Sie MockHttpServletRequest verwenden, denke ich?
Wonhee
Ist es sicher, in einer Dienstinstanz mit Singleton-Gültigkeitsbereich verwendet zu werden?
Jin Kwon
2

Wie hier vorgeschlagen , können Sie auch den HttpServletRequestParameter als Methode injizieren, z.

public MyResponseObject myApiMethod(HttpServletRequest request, ...) {
    ...
}
Will Cain
quelle