2009-12-04 21 views
12

Necesito obtener el objeto de solicitud en el código de Java. No puedo pasar este objeto a mi código por ciertas razones. ¿Hay alguna manera en que pueda decir algo como: getCurrentHTTPServletRequest?Obtiene el objeto HttpServletRequest (solicitud) desde el código de Java

Es seguro para mí asumir que estoy en un contexto de servlet.

+0

favor Elaborar *, donde *, * por qué * y * * cuando usted necesita esto, entonces podemos pop con mucho mejores sugerencias de cómo hacer esto el manera correcta. Publicar semi pseudocódigo/sscce también puede ser útil para obtener una idea de lo que está tratando de lograr. – BalusC

+0

Necesito extender Solr QueryComponent que acepta SolrRequest. Desafortunadamente, SolrRequest no es una envoltura de solicitud de servlet. SolrDispatchFilter (se utiliza para gestionar solicitudes, no solo filtros) realiza la traducción HttpServletRequest a SolrRequest. Por lo tanto, la única forma de pasar información adicional desde la solicitud a mi QueryComponent personalizado es modificando SolrDispatchFilter, lo que no quiero hacer. Muchas gracias muchachos por su ayuda. La variable ThreadLocal debería hacer el trabajo por mí. – aseem

Respuesta

17

Bueno, debe pasarlo si lo necesita. Cualquier otra cosa que hagas será fea, básicamente.

puede usar una variable ThreadLocal - básicamente establece el contexto para ese hilo en particular cuando obtiene la solicitud, y luego la busca más adelante. Eso funcionará siempre que solo necesite obtener la solicitud dentro del hilo que la está procesando, y siempre que no haga ningún manejo asincrónico de solicitudes funky. Sin embargo, es frágil, precisamente por esas razones.

Sin embargo, quisiera fuertemente aconsejarle que sea explícito acerca de sus dependencias en su lugar. Pase la solicitud de servlet, o solo los bits que necesita.

+4

+1: para el * debe pasarlo *. Mucho más recomendado que los feos subprocesos de ThreadLocal que realmente no usaría como subprocesos de solicitud pueden ser agrupados por el contenedor web, o realmente debes asegurarte de que lo elimines del subproceso cuando termine. Demasiado trabajo y efectos secundarios desagradables/ – BalusC

+3

No siempre es posible pasar objetos hacia abajo. Puede que tenga que cruzar algunas API de las que no tiene control. Incluso si puede cambiar cualquier API, sería tonto e inconviniente declarar un argumento de solicitud en todos sus métodos, y pasar el objeto de solicitud cada vez que llame a cualquier método. ThreadLocal está bien siempre que sepa lo que está haciendo. – irreputable

+1

Entonces, o bien la API no está diseñada para el propósito específico, o estás buscando una solución en la dirección incorrecta. ¿Qué hay de acceder * desde el otro lado *, por ejemplo? He hecho JSP/Servlet por demasiado tiempo para confirmar que hay suficientes formas mejores y que no necesitas necesariamente cosas de ThreadLocal para esto. – BalusC

0

Suponiendo que el servlet de nivel superior realmente es un tabú por algún motivo loco relacionado con el negocio, todavía existe la opción de definir un ServletFilter para ver previamente la solicitud y rellenarla en un ThreadLocal. Suponiendo que el web.xml no es también sacrosanto.

Pero estoy de acuerdo con Jon Skeet en que esto sería muy feo. Codificaría esto y luego trataría de encontrar un trabajo diferente. :)

En realidad, dado que un filtro puede arrebatar totalmente el control del servlet de recepción, puede utilizar esta técnica para desviar el código a un servlet propio, hacer lo que desee, y LUEGO ejecutar el otro , servlet "oficial" ... o cualquier otra cosa en ese sentido. Algunas de esas soluciones incluso le permitirán tratar de manera correcta y sólida con sus datos de solicitud.

4

Jon Skeet dijo prácticamente todo, pero una aclaración a su consejo "solo los bits que necesita" - si necesita que sus parámetros de solicitud se transmitan, pero no necesita una dependencia en HttpServletRequest, pase request.getParameterMap().

y que se extiende un poco en la opción ThreadLocal - puede tener un Filter que maneja todas las peticiones entrantes, y establece la petición en un

public final static ThreadLocal<HttpServletRequest> httpServletRequestTL = 
     new ThreadLocal<HttpServletRequest>(); 

Debido a que se está configurando en cada solicitud (cuidado con el filtro mapeo), no tendrá que preocuparse por el grupo de subprocesos de servlet-contenedor; siempre tendrá la solicitud actual.

P.S. esta es la lógica detrás de la utilidad de primavera propuesta por skaffman. Me uno a él para recomendar el componente estable, en lugar de hacer uno propio.

9

Suponiendo que no puede pasar el objeto de solicitud por la pila de llamadas, se hace necesario algún tipo de mecanismo de compartición, lo que no es ideal, pero a veces es necesario.

Spring proporciona el RequestContextFilter solo para este propósito. Utiliza ThreadLocal, y permite que el código busque la solicitud actual a través del RequestContextHolder.Tenga en cuenta que este filtro hace no requieren el uso de cualquier otra parte de la primavera:

Servlet 2.3 Filter that exposes the request to the current thread, through both LocaleContextHolder and RequestContextHolder. To be registered as filter in web.xml.

This filter is mainly for use with third-party servlets, e.g. the JSF FacesServlet. Within Spring's own web support, DispatcherServlet's processing is perfectly sufficient.

Si usted va a utilizar ThreadLocal, entonces mejor usar una solución existente, trabajando, en lugar de los insectos arrastrándose en riesgo , que el código ThreadLocal es propenso a.

4

No hay servlet API para hacer esto. Sin embargo, Tomcat proporciona una llamada de API para hacer esto,

HttpServletRequest request = (HttpServletRequest)org.apache.catalina.core.ApplicationFilterChain.getLastServicedRequest(); 

Esto hará que la última solicitud se pasa a un servlet para el mantenimiento del hilo actual.

Para que esto funcione, el Tomcat debe estar en modo "Estricto cumplimiento del servlet". Si no es así, necesita habilitar mediante la adición de este parámetro JVM:

org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true 
+0

Esta es la respuesta más cercana a una situación que estoy enfrentando. Creé una recompensa si te interesa. Básicamente tengo un filtro que obtiene un objeto de fábrica de servicio Spring del contexto de servlet, esta fábrica asigna una instancia de un bean cuando el filtro llama a su método getService pero necesito pasar la sesión o el objeto httpServletRequest real de la solicitud. Pero no debería porque romperá la abstracción del puente de servicios remotos que posee el filtro. Su respuesta parece correcta, pero el problema es que la aplicación web es multiusuario y podría terminar con la solicitud incorrecta, ¿verdad? – Jigzat

+0

Parece que lo que necesito, pero obtengo "java.lang.IllegalAccessError: org/apache/catalina/core/ApplicationFilterChain" al llamar a tal. – Laloutre

Cuestiones relacionadas