Получить объект HttpServletRequest (запрос) из кода Java
Мне нужно получить объект запроса в коде Java. Я не могу передать этот объект в мой код по определенным причинам. Есть ли способ, которым я могу сказать что-то вроде: getCurrentHTTPServletRequest
?
Для меня безопасно предположить, что я нахожусь в контексте сервлета.
5 ответов
Ну, вы должны передать его, если вам это нужно. Все остальное, что вы делаете, будет в принципе уродливым.
Вы могли бы использовать ThreadLocal
переменная - обычно устанавливает контекст для этого конкретного потока, когда вы получаете запрос, а затем извлекаете его позже. Это будет работать до тех пор, пока вам нужно только получить запрос в потоке, который его обрабатывает, и до тех пор, пока вы не выполняете какой-либо броской асинхронной обработки запроса. Это хрупкий, хотя, именно по этим причинам.
Тем не менее, я настоятельно рекомендую вам четко указывать свои зависимости. Либо передайте запрос сервлета вниз, либо просто биты, которые вам нужны.
Предполагая, что вы не можете передать объект запроса по стеку вызовов, тогда необходим некоторый механизм совместного использования, который не идеален, но иногда необходим.
Spring предоставляет RequestContextFilter именно для этой цели. Оно использует ThreadLocal
и позволяет коду получать текущий запрос через RequestContextHolder. Обратите внимание, что этот фильтр не требует использования какой-либо другой части Spring:
Сервлет 2.3 Фильтр, который предоставляет запрос текущему потоку через LocaleContextHolder и RequestContextHolder. Быть зарегистрированным как фильтр в web.xml.
Этот фильтр в основном предназначен для использования со сторонними сервлетами, например, JSF FacesServlet. В собственной веб-поддержке Spring обработка DispatcherServlet вполне достаточна.
Если вы собираетесь использовать ThreadLocal
, тогда лучше использовать существующее, работающее решение, а не закрадываться ошибки риска, которые ThreadLocal
Код подвержен.
Для этого не существует API сервлетов. Тем не менее, Tomcat предоставляет вызов API для этого,
HttpServletRequest request = (HttpServletRequest)org.apache.catalina.core.ApplicationFilterChain.getLastServicedRequest();
Это получит последний запрос, переданный сервлету для обслуживания из текущего потока.
Чтобы это работало, Tomcat должен находиться в режиме "Строгое соответствие сервлетам". Если нет, вам нужно включить его, добавив этот параметр JVM:
org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true
Джон Скит сказал практически все, но одно пояснение к его совету "только те биты, которые вам нужны" - если вам нужно передать параметры вашего запроса, но вам не нужна зависимость от HttpServletRequest
, проходить request.getParameterMap()
,
И немного расширив ThreadLocal
вариант - вы можете иметь Filter
который обрабатывает все входящие запросы и устанавливает запрос в
public final static ThreadLocal<HttpServletRequest> httpServletRequestTL =
new ThreadLocal<HttpServletRequest>();
Поскольку вы устанавливаете его для каждого запроса (осторожно с отображением фильтра), вам не нужно беспокоиться о пуле потоков сервлет-контейнера - у вас всегда будет текущий запрос.
PS Такова логика весенней утилиты, предложенной skaffman - я присоединяюсь к нему, рекомендуя стабильный компонент, а не свой собственный.
Предполагая, что сервлет верхнего уровня действительно является табу по какой-то сумасшедшей причине, связанной с бизнесом, все еще есть возможность определить ServletFilter
предварительно просмотреть запрос и вставить его в ThreadLocal. Предполагая, что web.xml
это также не священно.
Но я согласен с Джоном Скитом в том, что это было бы очень уродливо. Я бы написал это, а затем попытался найти другую работу.:)
На самом деле, учитывая тот факт, что фильтр может полностью отобрать контроль у принимающего сервлета, вы можете использовать эту технику, чтобы перенаправить код на свой собственный сервлет, сделать все, что вы хотите, и ТО запустить другой, "официальный" сервлет... или что-нибудь еще в этом роде. Некоторые из этих решений даже позволят вам правильно и надежно работать с данными вашего запроса.