Получить объект HttpServletRequest (запрос) из кода Java - PullRequest
13 голосов
/ 04 декабря 2009

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

Можно с уверенностью предположить, что я нахожусь в контексте сервлета.

Ответы [ 5 ]

18 голосов
/ 04 декабря 2009

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

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

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

9 голосов
/ 04 декабря 2009

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

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

Servlet 2.3 Фильтр, который выставляет запрос к текущему потоку, через оба LocaleContextHolder и RequestContextHolder. Быть зарегистрированным как фильтр в web.xml.

Этот фильтр в основном предназначен для использования с сторонние сервлеты, например JSF FacesServlet. В собственной сети Spring поддержка, ДиспетчерСервлет обработка вполне достаточна.

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

4 голосов
/ 05 декабря 2009

Для этого не существует API сервлетов. Тем не менее, Tomcat предоставляет API-вызов для этого,

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

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

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

org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true
4 голосов
/ 04 декабря 2009

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

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

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

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

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

0 голосов
/ 04 декабря 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...