Spring MVC - Comment obtenir tous les paramètres de requête dans une carte dans le contrôleur Spring?

188

Exemple d'URL:

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

Je ne connais pas les noms de attr1, att2 et attr4.

J'aimerais pouvoir faire quelque chose comme ça (ou similaire, je m'en fiche, du moment que j'ai accès à la carte du nom du paramètre de la requête -> valeur:

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

Comment puis-je y parvenir avec Spring MVC?

MDb
la source

Réponses:

316

Bien que les autres réponses soient correctes, ce n'est certainement pas la "manière Spring" d'utiliser directement l'objet HttpServletRequest. La réponse est en fait assez simple et à quoi vous vous attendriez si vous connaissez Spring MVC.

@RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
@RequestParam Map<String,String> allRequestParams, ModelMap model) {
   return "viewName";
}
Adam Gent
la source
44
Si vous cherchez à traiter des valeurs de liste, comme à partir d'un groupe de cases à cocher avec le même nom, utilisez: @RequestParam MultiValueMap<String, String>
IcedDante
1
Merci pour cela. Vous pouvez également faire la même chose avec les en-têtes: stackoverflow.com/a/19556291/2599745
Rob Worsnop
3
Cela ne fonctionne que lorsque la méthode de requête est GET ou POST. Cela ne fonctionne pas pour les méthodes de requête PUT, DELETE, etc.
George Siggouroglou
N'oubliez pas d'ajouter import org.springframework.ui.ModelMap;également.
eigenfield
@typelogic ModelMapn'est pas nécessaire pour obtenir tous les paramètres de requête sous forme de carte; c'est simplement un détail spécifique au code d'OP.
xlm
35

Éditer

Il a été souligné qu'il existe ( au moins à partir de 3.0 ) un mécanisme pur Spring MVC par lequel on pourrait obtenir ces données. Je ne vais pas le détailler ici, car c'est la réponse d'un autre utilisateur. Voir la réponse de @ AdamGent pour plus de détails, et n'oubliez pas de voter pour.

Dans la documentation Spring 3.2, ce mécanisme est mentionné à la fois sur la RequestMappingpage JavaDoc et la RequestParampage JavaDoc, mais auparavant, il n'est mentionné que dans la RequestMappingpage. Dans la documentation 2.5, il n'y a aucune mention de ce mécanisme.

C'est probablement l'approche préférée pour la plupart des développeurs car elle supprime (au moins cette) liaison à l' HttpServletRequestobjet défini par le fichier jar servlet-api.

/Éditer

Vous devriez avoir accès à la chaîne de requête des requêtes via request.getQueryString().

En plus de getQueryString, les paramètres de requête peuvent également être récupérés à partir de request.getParameterMap () sous forme de Map.

nicholas.hauschild
la source
12
Je soupçonne que quelqu'un a décliné cette réponse simplement parce que getQueryString renvoie une chaîne et non une carte. L'op cherchait une carte des paramètres. J'ai ajouté getParameterMap à votre réponse pour la rendre plus correcte :) +1
jmort253
Non, j'ai voté contre parce que ce n'est pas la manière Spring MVC de le faire. @RequestParamprendra volontiers a Mapcomme paramètre (voir ma réponse).
Adam Gent
@AdamGent La question a été posée à un moment où Spring 3.2 n'était pas encore sorti. Revenez en arrière et jetez un œil à JavaDoc pour 3.1, et vous remarquerez qu'il n'y a aucune mention de l'utilisation @RequestParamsur a Map<String,String>pour récupérer tous les paramètres de chaîne de requête. Et s'il vous plaît, ne vous sentez pas si abhorré par les réponses que vous voyez ici ... elles ne sont pas si mauvaises :) static.springsource.org/spring/docs/3.1.x/javadoc-api/org/…
nicholas. hauschild
Je pense qu'il existait dans 3.1 mais n'était pas JavaDoced. Je n'ai pas dit que j'étais abhorré mais choqué que le @RequestParam Map<>chemin n'ait pas été fait. Je suis légèrement ennuyé par le fait que de nombreux projets modernes que j'ai vus Spring MVC (printemps 3.1 et supérieur) ils mettront HttpServletRequest et HttpServletResponse sur chaque méthode. Et il semble que c'est parce que les développeurs juniors utilisent StackOverflow et google au lieu de regarder le document. Cela rend difficile pour le projet Spring de passer d'une API de servlet à une API Netty. JAX-RS a des problèmes d'abus similaires, mais à un degré bien moindre.
Adam Gent
Et il est JavaDoced dans 3.1 mais pas aux bons endroits: " De plus, @RequestParam peut être utilisé sur un paramètre de méthode Map <String, String> ou MultiValueMap <String, String> pour accéder à tous les paramètres de requête. ". En fait, cela remonte à la version 3.0 (je savais que je l'utilisais avant la version 3.1). Mon ennui tient toujours au fait que les gens n'ont pas pris la peine de faire la recherche :)
Adam Gent
14

L'objet HttpServletRequest fournit déjà une carte des paramètres. Voir request.getParameterMap () pour plus de détails.

Kevin
la source
1
Get parameter map contiendra également les données de formulaire d'une requête POST. Si l'utilisateur ne connaît pas les clés de la chaîne de requête, comment pourra-t-il faire la distinction entre ce qui provient de la chaîne de requête et ce qui provient des données d'un corps POST?
nicholas.hauschild
Êtes-vous en train de me dire que vous allez traiter une publication de formulaire mais vous n'avez aucune idée des paramètres réels du formulaire?
Kevin le
2
La question indique qu'il ne sait pas quels sont les noms des paramètres. De plus, je ne sais pas non plus ce qu'ils sont. ;)
nicholas.hauschild
Désolé, je trouve la prémisse un peu ridicule.
Kevin le
11
Cela a du sens dans une application basée sur les données. Un où les chemins de requête et les chaînes de requête peuvent être constitués par le client, et le serveur d'application rechercherait alors la valeur correspondante (à partir de n'importe quel type de source de données) en utilisant ces chemins et ces chaînes de requête comme clés.
nicholas.hauschild
12

vous pouvez simplement utiliser ceci:

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

Cela devrait bien fonctionner

Biggy_java
la source
10

Voici un exemple simple d' obtention de paramètres de requête dans une carte.

 @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 );
       }

Dans ce cas, il liera respectivement la valeur de studentName et studentEmail avec des variables de nom et d'email.

Shrirang Kadale
la source
8

Utilisé org.springframework.web.context.request.WebRequestcomme paramètre dans votre méthode de contrôleur, il fournit la méthode getParameterMap(), l'avantage est que vous ne serrez pas votre application à l'API Servlet, la WebRequest est un exemple d'objet de contexte de modèle JavaEE.

Diego Lins de Freitas
la source
7

Il y a deux interfaces

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

Permet l'accès aux paramètres de requête génériques ainsi que l' request/sessionaccès aux attributs, sans lien avec l'API Servlet / Portlet native .

Ex.:

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

PS Il existe des documents sur les arguments qui peuvent être utilisés comme paramètres de contrôleur.

Katoquro
la source
Merci ça marche. Puis-je demander, à quoi sert String[]la valeur? Je dois l'indexer à 0 juste pour obtenir la valeur.
eigenfield le
Il peut y avoir un tableau de valeurs comme key=val1,val2ou key=val1&key=val2(si je me souviens bien que le ressort supporte ces deux notations), vous obtiendrez donc un tableau avec 2 éléments
katoquro
6

Je suis peut-être en retard à la fête, mais d'après ce que j'ai compris, vous cherchez quelque chose comme ceci:

for(String params : Collections.list(httpServletRequest.getParameterNames())) {
    // Whatever you want to do with your map
    // Key : params
    // Value : httpServletRequest.getParameter(params)                
}
goelanshul
la source
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]);
}

Tous les paramètres seront stockés dans jsonObject.

Agyaey Tiwari
la source
1

Il existe une différence fondamentale entre les paramètres de requête et les paramètres de chemin. Cela va comme ceci: www.your_domain?queryparam1=1&queryparam2=2- paramètres de requête. www.your_domain/path_param1/entity/path_param2- paramètres de chemin.

Ce que j'ai trouvé surprenant, c'est que dans le monde de Spring MVC, beaucoup de gens confondent l'un avec l'autre. Bien que les paramètres de requête ressemblent plus à des critères de recherche, les paramètres de chemin identifieront probablement de manière unique une ressource. Cela dit, cela ne signifie pas que vous ne pouvez pas avoir plusieurs paramètres de chemin dans votre URI, car la structure des ressources peut être imbriquée. Par exemple, disons que vous avez besoin d'une ressource automobile spécifique d'une personne spécifique:

www.my_site/customer/15/car/2 - recherche d'une deuxième voiture d'un 15e client.

Quel serait un cas d'utilisation pour mettre tous les paramètres de chemin dans une carte? Les paramètres de chemin n'ont pas de "clé" lorsque vous regardez un URI lui-même, ces clés à l'intérieur de la carte seraient extraites de votre annotation @Mapping, par exemple:

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

À partir de la perspective HTTP / REST, les paramètres de chemin d'accès ne peuvent pas vraiment être projetés sur une carte. Tout dépend de la flexibilité de Spring et de son désir de s'adapter à tous les caprices des développeurs, à mon avis.

Je n'utiliserais jamais une carte pour les paramètres de chemin, mais cela peut être très utile pour les paramètres de requête.

yuranos
la source