Spring: как мне внедрить HttpServletRequest в bean-компонент с областью действия запроса?

96

Я пытаюсь настроить компонент с ограниченным объемом запроса весной.

Я успешно настроил его, поэтому компонент создается один раз для каждого запроса. Теперь ему нужно получить доступ к объекту HttpServletRequest.

Поскольку компонент создается один раз за запрос, я полагаю, что контейнер может легко внедрить объект запроса в мой компонент. Как я могу это сделать ?

Леонель
источник

Ответы:

115

Компоненты с областью действия запроса могут быть автоматически связаны с объектом запроса.

private @Autowired HttpServletRequest request;
Скаффман
источник
2
Есть ли для этого старомодный способ XML?
cherouvim
2
У меня не работает (spring mvc 3.1) - может есть еще что-то, что нужно сделать? Собираюсь с решением Самита.
kldavis4 07
2
Проблема в том, что при тестировании валидаторов с использованием MockMvc и такого рода инъекций у вас будут проблемы.
Возможно,
21
Можно также автоматически подключать HttpServletRequest к bean-компонентам без области запроса, поскольку для HttpServletRequest Spring будет генерировать прокси-сервер HttpServletRequest, который знает, как получить фактический экземпляр запроса. Таким образом, запрос autowire безопасен, даже если ваш контроллер имеет одноэлементную область видимости.
vtor
3
Предупреждение для пользователей Spring <= 3.1: автоматическое подключение не будет работать при выполнении тестов.
Рубенс Мариуццо
138

Spring предоставляет текущий HttpServletRequestобъект (а также текущий HttpSessionобъект) через объект- оболочку типа ServletRequestAttributes. Этот объект-оболочка привязан к ThreadLocal и получается путем вызова staticметода RequestContextHolder.currentRequestAttributes().

ServletRequestAttributesпредоставляет метод getRequest()для получения текущего запроса, getSession()для получения текущего сеанса и других методов для получения атрибутов, хранящихся в обеих областях. Следующий код, хотя и немного уродливый, должен предоставить вам текущий объект запроса в любом месте приложения:

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

Обратите внимание, что RequestContextHolder.currentRequestAttributes()метод возвращает интерфейс и должен иметь тип ServletRequestAttributes, реализующий интерфейс.


Spring Javadoc: RequestContextHolder | ServletRequestAttributes

самитгаур
источник
8
Инъекция - хорошее решение, но я обнаружил проблемы с проверкой MockMvc валидаторов Spring, которые вводят HttpServletRequest. Поэтому, если вы хотите, чтобы как тестовые тесты, так и производственный код работали правильно, это должен быть выбор.
Neyko
@Нейко Почему? для фиктивного теста (модульного теста?) вы можете ввести фиктивный HttpServletRequest или что угодно, не так ли? Или вы можете использовать MockHttpServletRequest, я думаю?
wonhee
Безопасно ли использовать в экземпляре службы с одноэлементной областью действия?
Джин Квон
2

Как предлагается здесь, вы также можете ввести HttpServletRequestкак параметр метода, например:

public MyResponseObject myApiMethod(HttpServletRequest request, ...) {
    ...
}
Уилл Каин
источник