Spring: ¿cómo inyecto un HttpServletRequest en un bean con ámbito de solicitud?

95

Estoy tratando de configurar un bean con ámbito de solicitud en Spring.

Lo configuré con éxito para que el bean se cree una vez por solicitud. Ahora, necesita acceder al objeto HttpServletRequest.

Dado que el bean se crea una vez por solicitud, me imagino que el contenedor puede inyectar fácilmente el objeto de solicitud en mi bean. Cómo puedo hacer eso ?

Leonel
fuente

Respuestas:

114

Los beans de ámbito de solicitud se pueden conectar automáticamente con el objeto de solicitud.

private @Autowired HttpServletRequest request;
skaffman
fuente
2
¿Existe una forma XML antigua para esto?
Cherouvim
2
No funciona para mí (spring mvc 3.1) - ¿tal vez hay algo más que deba hacerse? Siguiendo la solución de Samit.
kldavis4
2
El problema es que cuando pruebes validadores usando MockMvc y este tipo de inyección, tendrás problemas. Puede ser que la otra solución sea la preferida en este caso
Neyko
21
Es posible conectar automáticamente HttpServletRequest también en beans sin alcance de solicitud, porque para HttpServletRequest Spring generará un proxy HttpServletRequest que sabe cómo obtener la instancia real de solicitud. Por lo tanto, es seguro realizar una solicitud de cableado automático incluso si su controlador tiene un alcance único.
vtor
3
Advertencia para los usuarios de Spring <= 3.1, el cableado automático no funcionará al ejecutar pruebas.
Rubens Mariuzzo
138

Spring expone el HttpServletRequestobjeto actual (así como el HttpSessionobjeto actual ) a través de un objeto contenedor de tipo ServletRequestAttributes. Este objeto contenedor está vinculado a ThreadLocal y se obtiene llamando al staticmétodo RequestContextHolder.currentRequestAttributes().

ServletRequestAttributesproporciona el método getRequest()para obtener la solicitud actual, getSession()para obtener la sesión actual y otros métodos para obtener los atributos almacenados en ambos ámbitos. El siguiente código, aunque un poco feo, debería llevarle el objeto de solicitud actual en cualquier lugar de la aplicación:

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

Tenga en cuenta que el RequestContextHolder.currentRequestAttributes()método devuelve una interfaz y es necesario convertirlo en el ServletRequestAttributesque implementa la interfaz.


Spring Javadoc: RequestContextHolder | ServletRequestAttributes

samitgaur
fuente
8
La inyección tiene una buena resolución, pero he encontrado problemas con los validadores Spring de prueba de MockMvc que inyectan HttpServletRequest. Entonces, si desea que tanto las pruebas simuladas como el código de producción se ejecuten correctamente, esta debería ser la elección.
Neyko
@Neyko ¿Por qué? para una prueba simulada (¿prueba unitaria?), puede inyectar HttpServletRequest simulacro o lo que quiera ... ¿no es así? ¿O puede usar MockHttpServletRequest, supongo?
wonhee
¿Es seguro usarlo en una instancia de servicio de ámbito único?
Jin Kwon
2

Como se sugiere aquí , también puede inyectar el parámetro HttpServletRequestcomo método, por ejemplo:

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