Spring MVC - Wie werden alle Anforderungsparameter in einer Karte in Spring Controller abgerufen?

183

Beispiel-URL:

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

Ich kenne die Namen von attr1, att2 und attr4 nicht.

Ich möchte in der Lage sein, so etwas zu tun (oder ähnliches, egal, solange ich Zugriff auf die Karte des Anforderungsparameters habe -> Wert:

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

Wie kann ich dies mit Spring MVC erreichen?

MDb
quelle

Antworten:

308

Während die anderen Antworten richtig sind, ist es sicherlich nicht der "Spring-Weg", das HttpServletRequest-Objekt direkt zu verwenden. Die Antwort ist eigentlich ganz einfach und was Sie erwarten würden, wenn Sie mit Spring MVC vertraut sind.

@RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
@RequestParam Map<String,String> allRequestParams, ModelMap model) {
   return "viewName";
}
Adam Gent
quelle
41
Wenn Sie @RequestParam MultiValueMap<String, String>
Listenwerte verarbeiten möchten
1
Danke dafür. Dasselbe können Sie auch mit Headern tun: stackoverflow.com/a/19556291/2599745
Rob Worsnop
3
Dies funktioniert nur, wenn die Anforderungsmethode GET oder POST ist. Es funktioniert nicht für Anforderungsmethoden PUT, DELETE usw.
George Siggouroglou
Vergessen Sie nicht, auch hinzuzufügen import org.springframework.ui.ModelMap;.
Truthadjustr
@typelogic ModelMapwird nicht benötigt, um alle Anforderungsparameter als Map abzurufen. Das ist einfach ein Detail, das für den OP-Code spezifisch ist.
xlm
34

Bearbeiten

Es wurde darauf hingewiesen, dass es ( mindestens ab 3.0 ) einen reinen Spring-MVC-Mechanismus gibt, mit dem man diese Daten erhalten kann. Ich werde hier nicht näher darauf eingehen, da es die Antwort eines anderen Benutzers ist. Siehe die Antwort von @ AdamGent Vergessen Sie nicht, diese zu bewerten.

In der Spring 3.2-Dokumentation wird dieser Mechanismus sowohl auf der RequestMappingJavaDoc-Seite als auch auf derRequestParam JavaDoc-Seite erwähnt, zuvor jedoch nur auf der RequestMappingSeite. In der 2.5-Dokumentation wird dieser Mechanismus nicht erwähnt.

Dies ist wahrscheinlich der bevorzugte Ansatz für die meisten Entwickler, da dadurch (zumindest dieser) die Bindung an die entfernt wird HttpServletRequest durch die Servlet-API-JAR definierte Objekt entfernt wird.

/Bearbeiten

Sie sollten Zugriff auf die Anforderungsabfragezeichenfolge über haben request.getQueryString() .

Zusätzlich zu getQueryString können die Abfrageparameter auch als Map aus request.getParameterMap () abgerufen werden .

nicholas.hauschild
quelle
12
Ich vermute, jemand hat diese Antwort abgelehnt, nur weil getQueryString einen String und keine Map zurückgibt. Die Operation suchte nach einer Karte mit Parametern. Ich habe getParameterMap zu Ihrer Antwort hinzugefügt, um sie korrekter zu machen :) +1
jmort253
Nein, ich habe abgelehnt, weil dies nicht die Spring MVC-Methode ist. @RequestParamnehme gerne einen Mapals Parameter (siehe meine Antwort).
Adam Gent
@AdamGent Die Frage wurde zu einem Zeitpunkt gestellt, als Spring 3.2 noch nicht veröffentlicht wurde. Gehen Sie zurück und sehen Sie sich JavaDoc für 3.1 an. Sie werden feststellen, dass die Verwendung @RequestParamvon a Map<String,String>zum Abrufen aller Parameter für Abfragezeichenfolgen nicht erwähnt wird. Und bitte, fühlen Sie sich nicht so verabscheut über die Antworten, die Sie hier sehen ... sie sind nicht so schlecht :) static.springsource.org/spring/docs/3.1.x/javadoc-api/org/…
nicholas. hauschild
Ich denke, es existierte in 3.1, war aber nicht JavaDoced. Ich sagte nicht, dass ich verabscheut war, aber schockiert, dass der @RequestParam Map<>Weg nicht getan wurde. Ich ärgere mich leicht darüber, dass viele moderne Projekte, die ich in Spring MVC (Spring 3.1 und höher) gesehen habe, die HttpServletRequest und HttpServletResponse auf jede Methode setzen. Und es scheint, weil Junior-Entwickler StackOverflow und Google verwenden, anstatt sich das Dokument anzusehen. Dies macht es für das Spring-Projekt schwierig, von der Servlet-API zu einer Netty-API zu wechseln. JAX-RS hat ähnliche Missbrauchsprobleme, jedoch in weitaus geringerem Maße.
Adam Gent
Und es ist JavaDoced in 3.1, nur nicht an den richtigen Stellen: " Zusätzlich kann @RequestParam für einen Map <String, String> - oder MultiValueMap <String, String> -Methodenparameter verwendet werden, um Zugriff auf alle Anforderungsparameter zu erhalten. " Tatsächlich geht es bis zur Version 3.0 zurück (ich wusste, dass ich es vor 3.1 verwendet habe). Mein Ärger besteht immer noch darin, dass die Leute sich nicht die Mühe gemacht haben zu recherchieren :)
Adam Gent
14

Das HttpServletRequest-Objekt bietet bereits eine Zuordnung von Parametern. Weitere Informationen finden Sie unter request.getParameterMap () .

Kevin
quelle
1
Get Parameter Map enthält auch Formulardaten aus einer POST-Anforderung. Wenn der Benutzer die Schlüssel in der Abfragezeichenfolge nicht kennt, wie kann er dann unterscheiden, was aus der Abfragezeichenfolge stammt und was aus Daten aus einem POST-Text stammt?
nicholas.hauschild
Wollen Sie mir sagen, dass Sie einen Formularbeitrag bearbeiten werden, aber Sie haben keine Ahnung, wie die tatsächlichen Formularparameter lauten?
Kevin
2
Die Frage besagt, dass er die Parameternamen nicht kennt. Ich weiß auch nicht, was sie sind. ;)
nicholas.hauschild
Entschuldigung, ich finde die Prämisse etwas lächerlich.
Kevin
11
Dies ist in einer datengesteuerten Anwendung sinnvoll. Eine, in der Anforderungspfade und Abfragezeichenfolgen vom Client erstellt werden können und der Anwendungsserver dann den entsprechenden Wert (aus einer beliebigen Datenquelle) nachschlägt, indem diese Pfade und Abfragezeichenfolgen als Schlüssel verwendet werden.
nicholas.hauschild
12

Sie können dies einfach verwenden:

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

Das sollte gut funktionieren

Biggy_java
quelle
10

Hier ist das einfache Beispiel für das Abrufen von Anforderungsparametern in einer Map.

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

In diesem Fall werden der Wert von studentName und studentEmail mit den Variablen name und email verknüpft.

Shrirang Kadale
quelle
8

Verwenden Sie es org.springframework.web.context.request.WebRequestals Parameter in Ihrer Controller-Methode. Es stellt die Methode bereit getParameterMap(). Der Vorteil besteht darin, dass Sie Ihre Anwendung nicht an die Servlet-API binden. WebRequest ist ein Beispiel für ein JavaEE-Muster-Kontextobjekt.

Diego Lins de Freitas
quelle
6

Es gibt zwei Schnittstellen

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

Ermöglicht den Zugriff auf generische Anforderungsparameter sowie auf request/sessionAttribute ohne Verknüpfung mit der nativen Servlet / Portlet-API .

Ex.:

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

PS Es gibt Dokumente zu Argumenten, die als Controller-Parameter verwendet werden können.

katoquro
quelle
Danke, dass es funktioniert. Darf ich fragen, worum geht es String[]als Wert? Ich muss es auf 0 indizieren, um den Wert zu erhalten.
Truthadjustr
Es kann ein Array von Werten wie key=val1,val2oder geben key=val1&key=val2(wenn ich mich richtig erinnere, dass Spring beide Notationen unterstützt), so dass Sie ein Array mit 2 Elementen erhalten
Katoquro
6

Ich komme vielleicht zu spät zur Party, aber nach meinem Verständnis suchen Sie nach so etwas:

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

Alle Parameter werden in gespeichert jsonObject.

Agyaey Tiwari
quelle
1

Es gibt einen grundlegenden Unterschied zwischen Abfrageparametern und Pfadparametern. Es geht so: www.your_domain?queryparam1=1&queryparam2=2- Parameter abfragen. www.your_domain/path_param1/entity/path_param2- Pfadparameter.

Was ich überraschend fand, ist, dass in der MVC-Welt im Frühjahr viele Menschen einander verwechseln. Während Abfrageparameter eher Kriterien für eine Suche sind, identifizieren Pfadparameter eine Ressource höchstwahrscheinlich eindeutig. Dies bedeutet jedoch nicht, dass Sie nicht mehrere Pfadparameter in Ihrem URI haben können, da die Ressourcenstruktur verschachtelt werden kann. Angenommen, Sie benötigen eine bestimmte Fahrzeugressource einer bestimmten Person:

www.my_site/customer/15/car/2 - auf der Suche nach einem zweiten Auto eines 15. Kunden.

Was wäre ein Anwendungsfall, um alle Pfadparameter in eine Karte einzufügen? Pfadparameter haben keinen "Schlüssel", wenn Sie sich einen URI selbst ansehen. Diese Schlüssel in der Karte werden beispielsweise aus Ihrer @ Map-Annotation entnommen:

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

Aus HTTP / REST-Sicht können Pfadparameter nicht wirklich auf eine Karte projiziert werden. Meiner Meinung nach dreht sich alles um die Flexibilität von Spring und den Wunsch, Entwickler nach Lust und Laune unterzubringen.

Ich würde niemals eine Karte für Pfadparameter verwenden, aber sie kann für Abfrageparameter sehr nützlich sein.

Yuranos
quelle