2009-12-04 2 views
12

Мне нужно получить объект запроса в Java-коде. Я не могу передать этот объект до моего кода по определенным причинам. Есть ли способ сказать что-то вроде: getCurrentHTTPServletRequest?Получить объект HttpServletRequest (запрос) из кода Java

Для меня безопасно предположить, что я в контексте сервлета.

+0

Пожалуйста разработать *, где *, * почему * и * когда * вам это нужно, то мы можем выскочить с гораздо лучшими предложениями, как сделать этого правильно. Публикация полу псевдокода/sscce также может помочь получить картину того, чего вы пытаетесь достичь. – BalusC

+0

Мне нужно расширить Solr QueryComponent, который принимает SolrRequest. SolrRequest, к сожалению, не является оберткой вокруг запроса сервлета. SolrDispatchFilter (используется для обработки запроса, а не только для фильтра) выполняет перевод HttpServletRequest в SolrRequest. Поэтому единственный способ передать дополнительную информацию из запроса до моего пользовательского QueryComponent - это изменить SolrDispatchFilter, который я не хочу делать. Большое вам спасибо за помощь. Переменная ThreadLocal должна выполнять эту работу для меня. – aseem

ответ

17

Ну, вы должны должны передать его, если вам это нужно. Все, что вы делаете, будет уродливо, в основном.

Вы можете использовать переменную ThreadLocal - в основном задать контекст для этой конкретной нити при получении запроса, а затем получить ее позже. Это будет работать до тех пор, пока вам нужно только получить запрос в потоке, который его обрабатывает, и до тех пор, пока вы не будете заниматься фанкой асинхронной обработкой запросов. Это хрупкое, хотя именно по этим причинам.

Тем не менее, я бы решительно советую вам четко указать свои зависимости. Либо передайте запрос сервлета, либо просто нужные вам биты.

+4

+1: для * следует передать его *. Гораздо более рекомендуется, чем уродливые хакеры ThreadLocal, которые я действительно не буду использовать в качестве потоков запросов, могут быть объединены с помощью webcontainer, или вы действительно должны убедиться, что вы удалите его из потока по завершении. Слишком много работы и неприятных побочных эффектов/ – BalusC

+3

Нельзя передавать предметы вниз. Возможно, вам придется пересечь некоторые API, с которыми вы не контролируете. Даже если вы можете изменить любой API, было бы глупо и неудобно объявлять аргумент запроса во всех ваших методах и передавать объект запроса каждый раз, когда вы вызываете какой-либо метод. ThreadLocal прекрасен, пока вы знаете, что делаете. – irreputable

+1

Тогда либо API не намерен для достижения цели, либо ищет решение в неправильном направлении. Как насчет доступа к нему * с другой стороны * например? Я слишком долго делал JSP/Servlet, чтобы подтвердить, что есть достаточно лучшие способы, и для этого вам не обязательно нужны материалы ThreadLocal. – BalusC

0

Предполагая, что сервлет верхнего уровня действительно является табу по какой-то сумасшедшей причине, связанной с бизнесом, есть еще возможность определить ServletFilter для предварительного просмотра запроса и внесения его в ThreadLocal. Предполагая, что web.xml также не является священным.

Но я согласен с Джоном Скитом в том, что это было бы очень уродливо. Я бы закодировал это, а затем попытался найти другую работу. :)

На самом деле, учитывая, что фильтр может полностью вырвать управление из принимающего сервлета, вы можете использовать эту технику, чтобы отвлечь код на свой собственный сервлет, делать все, что хотите, и затем запускать другой , «официальный» сервлет ... или что-то еще в этом направлении. Некоторые из этих решений позволят вам правильно и надежно обрабатывать ваши данные запроса.

4

Jon Skeet сказал практически все, но одно пояснение к его совету «только то, что вам нужно» - если вам нужны ваши параметры запроса, переданные вниз, но вам не нужна зависимость от HttpServletRequest, пройдите request.getParameterMap().

И простирающийся немного на опции ThreadLocal - вы можете иметь Filter, который обрабатывает все входящие запросы, и устанавливает запрос в

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

Потому что вы устанавливаете его на каждом запросе (поосторожнее с фильтром сопоставление), вам не придется беспокоиться о пуле потоков сервлетов-контейнеров - вы всегда будете иметь текущий запрос.

P.S. это логика утилиты весны, предложенная скаффманом - я присоединяюсь к нему, рекомендуя стабильный компонент, а не создавая свои собственные.

9

Предполагая, что вы не можете передать объект запроса в стек вызовов, тогда необходим необходимый механизм обмена, что не является идеальным, но иногда необходимым.

Spring содержит RequestContextFilter для этой цели. Он использует ThreadLocal и позволяет коду получать текущий запрос через RequestContextHolder.Обратите внимание, что этот фильтр делает не требуют использовать любую другую часть весны:

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.

Если вы собираетесь использовать ThreadLocal, то лучше использовать существующее, работающее решение, а не ошибки риски ползучих , к которому относится код ThreadLocal.

4

Для этого не существует сервлет API. Однако Tomcat действительно обеспечивает API вызова, чтобы сделать это,

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

Это позволит получить последний запрос передается в сервлет для обслуживания из текущего потока.

Для этого необходимо, чтобы Tomcat находился в режиме «Строгое соответствие сервлета». Если нет, то вам необходимо включить его, добавив этот параметр JVM:

org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true 
+0

Это ближайший ответ на ситуацию, с которой я столкнулся. Я создал для него щедрость, если вы заинтересованы. В основном у меня есть фильтр, который получает объект фабрики Spring-сервиса из контекста сервлета, этот завод выделяет экземпляр компонента, когда фильтр вызывает метод getService, но мне нужно передать сеанс или фактический объект httpServletRequest запроса. Но я не должен, потому что это нарушит абстракцию моста удаленных служб, которому принадлежит фильтр. Ваш ответ выглядит правильно, но проблема в том, что webApp является многопользовательским, и я могу завершить неправильный запрос, не так ли? – Jigzat

+0

Кажется, что мне нужно, но я получаю «java.lang.IllegalAccessError: org/apache/catalina/core/ApplicationFilterChain» при вызове таких. – Laloutre

Смежные вопросы