Spring: como injeto um HttpServletRequest em um bean com escopo de solicitação?

95

Estou tentando configurar um bean com escopo de solicitação no Spring.

Eu configurei com sucesso para que o bean seja criado uma vez por solicitação. Agora, ele precisa acessar o objeto HttpServletRequest.

Como o bean é criado uma vez por solicitação, eu acho que o contêiner pode injetar facilmente o objeto de solicitação em meu bean. Como eu posso fazer isso ?

Leonel
fonte

Respostas:

114

Os beans com escopo de solicitação podem ser autowired com o objeto de solicitação.

private @Autowired HttpServletRequest request;
skaffman
fonte
2
Existe uma maneira XML antiquada para isso?
cherouvim de
2
Não funciona para mim (spring mvc 3.1) - talvez haja algo mais que precise ser feito? Indo com a solução de Samit.
kldavis4
2
O problema é que quando você testar validadores usando MockMvc e este tipo de injeção você terá problemas. Pode ser que a outra solução seja preferida neste caso
Neyko
21
É possível autowire HttpServletRequest também em beans sem escopo de solicitação, porque para HttpServletRequest Spring gerará um proxy HttpServletRequest que está ciente de como obter a instância real da solicitação. Portanto, é seguro fazer uma solicitação de autowire mesmo se o seu controlador tiver escopo único.
vtor
3
Aviso para usuários Spring <= 3.1 o autowiring não funcionará executando testes.
Rubens Mariuzzo
138

O Spring expõe o HttpServletRequestobjeto atual (assim como o HttpSessionobjeto atual ) por meio de um objeto wrapper do tipo ServletRequestAttributes. Este objeto wrapper está vinculado a ThreadLocal e é obtido chamando o staticmétodo RequestContextHolder.currentRequestAttributes().

ServletRequestAttributesfornece o método getRequest()para obter a solicitação atual, getSession()para obter a sessão atual e outros métodos para obter os atributos armazenados em ambos os escopos. O código a seguir, embora um pouco feio, deve fornecer o objeto de solicitação atual em qualquer lugar do aplicativo:

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

Observe que o RequestContextHolder.currentRequestAttributes()método retorna uma interface e precisa ser convertido para ServletRequestAttributesque implemente a interface.


Spring Javadoc: RequestContextHolder | ServletRequestAttributes

samitgaur
fonte
8
A injeção é uma boa resolução, mas encontrei problemas com os validadores Spring de teste do MockMvc que injetam HttpServletRequest. Portanto, se você deseja que os testes de simulação e o código de produção sejam executados corretamente, esta deve ser a escolha.
Neyko
@Neyko Por que isso? para teste de simulação (teste de unidade?), você pode injetar HttpServletRequest de simulação ou o que quiser .. não é? Ou você pode usar MockHttpServletRequest, eu acho?
wonhee de
É seguro ser usado em uma instância de serviço com escopo único?
Jin Kwon
2

Conforme sugerido aqui, você também pode injetar o HttpServletRequestparâmetro como um método, por exemplo:

public MyResponseObject myApiMethod(HttpServletRequest request, ...) {
    ...
}
Will Cain
fonte