Spring MVC - Como obter todos os parâmetros de solicitação em um mapa no controlador Spring?

183

URL de exemplo:

../search/?attr1=value1&attr2=value2&attr4=value4

Eu não sei os nomes de attr1, att2 e attr4.

Eu gostaria de poder fazer algo assim (ou similar, não me importo, desde que eu tenha acesso ao Mapa do pedido param name -> value:

@RequestMapping(value = "/search/{parameters}", method = RequestMethod.GET)
public void search(HttpServletRequest request, 
@PathVariable Map<String,String> allRequestParams, ModelMap model)
throws Exception {//TODO: implement}

Como posso conseguir isso com o Spring MVC?

MDb
fonte

Respostas:

311

Enquanto as outras respostas estão corretas, certamente não é o "caminho da primavera" para usar o objeto HttpServletRequest diretamente. A resposta é realmente bastante simples e o que você esperaria se estivesse familiarizado com o Spring MVC.

@RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
@RequestParam Map<String,String> allRequestParams, ModelMap model) {
   return "viewName";
}
Adam Gent
fonte
41
Se você estiver olhando para processar os valores da lista, como de um grupo de caixas de seleção com o mesmo nome, use: @RequestParam MultiValueMap<String, String>
IcedDante
1
Obrigado por isso. Você também pode fazer o mesmo com os cabeçalhos: stackoverflow.com/a/19556291/2599745
Rob Worsnop
3
Isso funciona apenas quando o método de solicitação é GET ou POST. Não está funcionando para os métodos de solicitação PUT, DELETE etc.
George Siggouroglou
Não se esqueça de adicionar import org.springframework.ui.ModelMap;também.
precisa saber é o seguinte
@typelogic ModelMapnão é necessário para obter todos os parâmetros de solicitação como mapa; isso é simplesmente um detalhe específico ao código do OP.
Xlm
34

Editar

Foi apontado que existe ( pelo menos a partir do 3.0 ) um mecanismo Spring MVC puro pelo qual se pode obter esses dados. Não vou detalhar aqui, pois é a resposta de outro usuário. Veja a resposta de @ AdamGent para obter detalhes, e não esqueça de votar.

Na documentação do Spring 3.2, esse mecanismo é mencionado na RequestMappingpágina JavaDoc e na RequestParampágina JavaDoc, mas antes, é mencionado apenas na RequestMappingpágina. Na documentação 2.5, não há menção desse mecanismo.

Essa é provavelmente a abordagem preferida para a maioria dos desenvolvedores, pois remove (pelo menos isso) a ligação ao HttpServletRequestobjeto definido pelo servlet-api jar.

/Editar

Você deve ter acesso à string de consulta de solicitações via request.getQueryString().

Além de getQueryString, os parâmetros de consulta também podem ser recuperados de request.getParameterMap () como um mapa.

nicholas.hauschild
fonte
12
Suspeito que alguém tenha votado contra esta resposta apenas porque getQueryString retorna uma String e não um Map. O op estava procurando um mapa de parâmetros. Eu adicionei getParameterMap à sua resposta para ajudar a torná-la mais correta :) +1
jmort253
Não, eu diminuí o voto porque não é a maneira do Spring MVC de fazer isso. @RequestParamterá o prazer de ter um Mapcomo parâmetro (veja a minha resposta).
Adam Gent
@AdamGent A pergunta foi feita no momento em que o Spring 3.2 ainda não havia sido lançado. Volte e dê uma olhada no JavaDoc para 3.1, e você notará que não há essa menção de utilizar @RequestParamem um Map<String,String>para recuperar todos os parâmetros da cadeia de caracteres de consulta. E por favor, não me sinto tão abominado sobre as respostas que você vê aqui ... eles não são que os maus :) static.springsource.org/spring/docs/3.1.x/javadoc-api/org/...
Nicholas. hauschild
Eu acho que existia na versão 3.1, mas não era JavaDoced. Não disse que estava detestada, mas chocada por o @RequestParam Map<>caminho não ter sido feito. Eu tenho um pouco de aborrecimento pelo fato de muitos projetos modernos que eu já vi o Spring MVC (primavera 3.1 e superior) e eles colocarão o HttpServletRequest e o HttpServletResponse em todos os métodos. E parece que é porque os desenvolvedores juniores usam o StackOverflow e o google em vez de examinar o documento. Isso torna difícil para o projeto Spring alternar da API do servlet para dizer uma API Netty. O JAX-RS tem problemas semelhantes de abuso, mas em um grau muito menor.
Adam Gent
E o JavaDoced no 3.1 não está nos lugares certos: " Além disso, o @RequestParam pode ser usado em um parâmetro do método Map <String, String> ou MultiValueMap <String, String> para obter acesso a todos os parâmetros de solicitação. ". De fato, ele remonta à versão 3.0 (eu sabia que a havia usado antes da 3.1). Meu aborrecimento ainda está de pé em que as pessoas não se incomodou em fazer a pesquisa :)
Adam Gent
14

O objeto HttpServletRequest já fornece um mapa de parâmetros. Veja request.getParameterMap () para mais detalhes.

Kevin
fonte
1
O mapa de parâmetros Get também conterá dados do formulário de uma solicitação POST. Se o usuário não souber as chaves na string de consulta, como será capaz de distinguir entre o que veio da string de consulta e o que é dos dados de um corpo POST?
Nicholas.hauschild
Você está me dizendo que vai processar uma postagem de formulário, mas não tem idéia de quais são os parâmetros reais do formulário?
Kevin
2
A pergunta afirma que ele não sabe quais são os nomes dos parâmetros. Além disso, também não sei o que são. ;)
nicholas.hauschild
Desculpe, acho a premissa um pouco ridícula.
Kevin
11
Faz sentido em um aplicativo orientado a dados. Um em que os caminhos de solicitação e as cadeias de consulta podem ser criados pelo cliente, e o servidor de aplicativos procuraria o valor correspondente (de qualquer tipo de fonte de dados) usando esses caminhos e as cadeias de consulta como chaves.
Nicholas.hauschild
12

você pode simplesmente usar isso:

Map<String, String[]> parameters = request.getParameterMap();

Isso deve funcionar bem

Biggy_java
fonte
10

Aqui está um exemplo simples de obter parâmetros de solicitação em um mapa.

 @RequestMapping(value="submitForm.html", method=RequestMethod.POST)
     public ModelAndView submitForm(@RequestParam Map<String, String> reqParam) 
       {
          String name  = reqParam.get("studentName");
          String email = reqParam.get("studentEmail");

          ModelAndView model = new ModelAndView("AdmissionSuccess");
          model.addObject("msg", "Details submitted by you::
          Name: " + name + ", Email: " + email );
       }

Nesse caso, ele vinculará o valor de studentName e studentEmail às variáveis ​​de nome e email, respectivamente.

Shrirang Kadale
fonte
8

Use org.springframework.web.context.request.WebRequestcomo parâmetro no método do controlador, ele fornece o método getParameterMap(), a vantagem é que você não restringe seu aplicativo à API do Servlet, o WebRequest é um exemplo do Objeto de Contexto do padrão JavaEE.

Diego Lins de Freitas
fonte
6

Existem duas interfaces

  1. org.springframework.web.context.request.WebRequest
  2. org.springframework.web.context.request.NativeWebRequest

Permite o acesso genérico a parâmetros de solicitação e acesso a request/sessionatributos, sem vínculos com a API nativa de Servlet / Portlet .

Ex.:

@RequestMapping(value = "/", method = GET)
public List<T> getAll(WebRequest webRequest){
    Map<String, String[]> params = webRequest.getParameterMap();
    //...
}

PS Existem documentos sobre argumentos que podem ser usados ​​como parâmetros de controlador.

katoquro
fonte
Obrigado, funciona. Posso perguntar, qual é o sentido do String[]valor? Eu tenho que indexá-lo para 0 apenas para obter o valor.
precisa saber é o seguinte
Não pode haver uma matriz de valores como key=val1,val2ou key=val1&key=val2(se bem me lembro suporte ambas as notações de primavera), assim você terá array com 2 elementos
katoquro
6

Talvez eu esteja atrasado para a festa, mas de acordo com meu entendimento, você está procurando algo parecido com isto:

for(String params : Collections.list(httpServletRequest.getParameterNames())) {
    // Whatever you want to do with your map
    // Key : params
    // Value : httpServletRequest.getParameter(params)                
}
goelanshul
fonte
2
@SuppressWarnings("unchecked")
Map<String,String[]> requestMapper=request.getParameterMap();
JsonObject jsonObject=new JsonObject();
for(String key:requestMapper.keySet()){
    jsonObject.addProperty(key, requestMapper.get(key)[0]);
}

Todos os parâmetros serão armazenados jsonObject.

Agyaey Tiwari
fonte
1

Há uma diferença fundamental entre os parâmetros de consulta e os parâmetros de caminho. É assim: www.your_domain?queryparam1=1&queryparam2=2- parâmetros de consulta. www.your_domain/path_param1/entity/path_param2- parâmetros de caminho.

O que eu achei surpreendente é que, no mundo do Spring MVC, muitas pessoas confundem uma pela outra. Embora os parâmetros de consulta sejam mais parecidos com os critérios de uma pesquisa, os parâmetros de caminho provavelmente identificarão um recurso de forma exclusiva. Dito isto, isso não significa que você não pode ter vários parâmetros de caminho em seu URI, porque a estrutura de recursos pode ser aninhada. Por exemplo, digamos que você precise de um recurso de carro específico de uma pessoa específica:

www.my_site/customer/15/car/2 - à procura de um segundo carro de um 15º cliente.

O que seria um caso de usuário para colocar todos os parâmetros de caminho em um mapa? Os parâmetros do caminho não têm uma "chave" quando você olha para um URI, essas chaves dentro do mapa seriam retiradas da anotação do @Mapping, por exemplo:

@GetMapping("/booking/{param1}/{param2}")

Do ponto de vista HTTP / REST, os parâmetros do caminho não podem ser projetados realmente em um mapa. É tudo sobre a flexibilidade do Spring e seu desejo de acomodar qualquer capricho de desenvolvedores, na minha opinião.

Eu nunca usaria um mapa para parâmetros de caminho, mas pode ser bastante útil para parâmetros de consulta.

yuranos
fonte