Spring MVC - Jak uzyskać wszystkie parametry żądania na mapie w kontrolerze Spring?

183

Przykładowy adres URL:

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

Nie znam nazw attr1, att2 i attr4.

Chciałbym móc zrobić coś takiego (lub podobnego, nie przejmuj się, o ile mam dostęp do mapy param name 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}

Jak mogę to osiągnąć za pomocą Spring MVC?

MDb
źródło

Odpowiedzi:

310

Podczas gdy inne odpowiedzi są poprawne, z pewnością nie jest to „wiosenny sposób” bezpośredniego używania obiektu HttpServletRequest. Odpowiedź jest w rzeczywistości dość prosta i możesz się spodziewać, jeśli znasz Spring MVC.

@RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
@RequestParam Map<String,String> allRequestParams, ModelMap model) {
   return "viewName";
}
Adam Gent
źródło
41
Jeśli chcesz przetworzyć wartości listy, na przykład z grupy @RequestParam MultiValueMap<String, String>
pól
1
Dzięki za to. Możesz zrobić to samo z nagłówkami: stackoverflow.com/a/19556291/2599745
Rob Worsnop
3
Działa to tylko wtedy, gdy metoda żądania to GET lub POST. Nie działa w przypadku metod żądania PUT, DELETE itp.
George Siggouroglou,
Nie zapomnij również dodać import org.springframework.ui.ModelMap;.
truthadjustr
@typelogic ModelMapnie jest potrzebny, aby uzyskać wszystkie parametry żądania jako mapę; to po prostu szczegół specyficzny dla kodu OP.
xlm
34

Edytować

Wskazano, że istnieje ( przynajmniej od 3.0 ) czysty mechanizm Spring MVC, za pomocą którego można uzyskać te dane. Nie będę go tutaj szczegółowo opisywać, ponieważ jest to odpowiedź innego użytkownika. Zobacz odpowiedź @ AdamGent, aby poznać szczegóły, i nie zapomnij głosować za nią.

W dokumentacji Spring 3.2 mechanizm ten jest wymieniony zarówno na RequestMappingstronie JavaDoc, jak i RequestParamJavaDoc, ale wcześniej wspomniano tylko na RequestMappingstronie. W dokumentacji 2.5 nie ma wzmianki o tym mechanizmie.

Jest to prawdopodobnie preferowane podejście dla większości programistów, ponieważ usuwa (przynajmniej to) wiązanie z HttpServletRequestobiektem zdefiniowanym przez jar apletu-api.

/Edytować

Powinieneś mieć dostęp do ciągu zapytania zapytania za pośrednictwem request.getQueryString().

Oprócz getQueryString parametry zapytania można również pobrać z request.getParameterMap () jako mapę.

nicholas.hauschild
źródło
12
Podejrzewam, że ktoś ocenił tę odpowiedź tylko dlatego, że getQueryString zwraca String, a nie Mapę. Operacja szukała mapy parametrów. Dodałem getParameterMap do twojej odpowiedzi, aby poprawić jej poprawność :) +1
jmort253
Nie, zlekceważyłem, ponieważ nie jest to wiosenny sposób MVC. @RequestParamchętnie przyjmie Mapjako parametr (patrz moja odpowiedź).
Adam Gent
@AdamGent Pytanie zadano w czasie, gdy Spring 3.2 nie został jeszcze wydany. Wrócić i przyjrzeć się z JavaDoc do 3,1, i można zauważyć, nie ma takiej wzmianki o wykorzystaniu @RequestParamna zasadzie Map<String,String>, aby pobrać wszystkie parametry ciągu zapytania. I proszę, nie czuj się tak wkurzony odpowiedziami, które tutaj widzisz ... nie są takie złe :) static.springsource.org/spring/docs/3.1.x/javadoc-api/org/…
nicholas. hauschild
Myślę, że istniał w wersji 3.1, ale nie był JavaDoced. Nie powiedziałem, że jestem zniesmaczony, ale zszokowałem się, że @RequestParam Map<>tak się nie stało. Mam lekką irytację w związku z tym, że wiele nowoczesnych projektów, które widziałem Spring MVC (wiosna 3.1 i nowsza), będą umieszczać HttpServletRequest i HttpServletResponse na każdej metodzie. I wydaje się, że jest tak, ponieważ młodsi programiści używają StackOverflow i Google zamiast patrzeć na dokument. Utrudnia to projektowi Spring zmianę z apletu apletu na API Netty. JAX-RS ma podobne problemy z nadużyciami, ale w znacznie mniejszym stopniu.
Adam Gent
I jest JavaDoced w wersji 3.1 po prostu nie we wszystkich właściwych miejscach: „ Dodatkowo @RequestParam może być używany w parametrze metody Map <String, String> lub MultiValueMap <String, String>, aby uzyskać dostęp do wszystkich parametrów żądania. ”. W rzeczywistości wraca do wersji 3.0 (wiedziałem, że używałem go przed wersją 3.1). Nadal mam irytację, że ludzie nie zawracali sobie głowy badaniami :)
Adam Gent
14

Obiekt HttpServletRequest już udostępnia mapę parametrów. Aby uzyskać więcej informacji, patrz request.getParameterMap () .

Kevin
źródło
1
Pobierz mapę parametrów będzie również zawierać dane formularza z żądania POST. Jeśli użytkownik nie zna kluczy w ciągu zapytania, to w jaki sposób będzie w stanie rozróżnić między tym, co pochodzi z ciągu zapytania, a tym, co pochodzi z danych z ciała POST?
nicholas.hauschild
Mówisz mi, że zamierzasz przetworzyć formularz, ale nie masz pojęcia, jakie są rzeczywiste parametry formularza?
Kevin
2
Pytanie stwierdza, że ​​nie wie, jakie są nazwy parametrów. Nie wiem też, czym one są. ;)
nicholas.hauschild
Przepraszam, uważam to założenie za trochę śmieszne.
Kevin
11
Ma to sens w aplikacji opartej na danych. Jeden, w którym klient może tworzyć ścieżki żądań i ciągi zapytań, a serwer aplikacji szukałby odpowiedniej wartości (z dowolnego źródła danych), używając tych ścieżek i ciągów zapytań jako kluczy.
nicholas.hauschild
12

możesz po prostu użyć tego:

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

To powinno działać dobrze

Biggy_java
źródło
10

Oto prosty przykład uzyskiwania parametrów żądania na mapie.

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

W takim przypadku powiąże wartość studentName i studentEmail odpowiednio ze zmiennymi name i email.

Shrirang Kadale
źródło
8

Użyj org.springframework.web.context.request.WebRequestjako parametru w metodzie kontrolera, zapewnia on tę metodę getParameterMap(), zaletą jest to, że nie dokręcasz aplikacji do interfejsu API serwletu, WebRequest jest przykładem obiektu kontekstowego wzorca JavaEE.

Diego Lins de Freitas
źródło
6

Istnieją dwa interfejsy

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

Umożliwia ogólny dostęp do parametrów żądania oraz request/sessiondostęp do atrybutów, bez powiązań z natywnym interfejsem API serwletów / portletów .

Dawny.:

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

PS Istnieją dokumenty dotyczące argumentów, które można wykorzystać jako parametry kontrolera.

katoquro
źródło
Dziękuję, że działa. Czy mogę zapytać, jaki jest sens String[]tej wartości? Muszę zindeksować go do 0, aby uzyskać wartość.
truthadjustr
Może istnieć tablica wartości takich jak key=val1,val2lub key=val1&key=val2(jeśli dobrze pamiętam, że obsługuję oba te zapisy), więc otrzymasz tablicę z 2 elementami
katoquro
6

Mogę spóźnić się na przyjęcie, ale według mojego zrozumienia szukasz czegoś takiego:

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

Wszystkie parametry zostaną zapisane w jsonObject.

Agyaey Tiwari
źródło
1

Istnieje zasadnicza różnica między parametrami zapytania a parametrami ścieżki. Wygląda to tak: www.your_domain?queryparam1=1&queryparam2=2- parametry zapytania. www.your_domain/path_param1/entity/path_param2- parametry ścieżki.

Zaskoczyło mnie to, że w świecie Spring MVC wiele osób myli jeden z drugim. Podczas gdy parametry zapytania są bardziej podobne do kryteriów wyszukiwania, parametry ścieżki najprawdopodobniej jednoznacznie zidentyfikują zasób. To powiedziawszy, nie oznacza to, że nie możesz mieć wielu parametrów ścieżki w twoim URI, ponieważ struktura zasobów może być zagnieżdżona. Załóżmy na przykład, że potrzebujesz określonego zasobu samochodowego konkretnej osoby:

www.my_site/customer/15/car/2 - szukam drugiego samochodu 15. klienta.

Jaki byłby użyteczny przykład umieszczenia wszystkich parametrów ścieżki na mapie? Parametry ścieżki nie mają „klucza”, gdy patrzysz na sam URI, te klucze wewnątrz mapy zostałyby pobrane z adnotacji @Mapping, na przykład:

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

Z perspektywy perspektywy HTTP / REST parametrów ścieżki nie można tak naprawdę rzutować na mapę. Moim zdaniem, chodzi o elastyczność Springa i chęć zaspokojenia wszelkich zachcianek deweloperów.

Nigdy nie użyłbym mapy dla parametrów ścieżki, ale może być całkiem przydatny dla parametrów zapytania.

yuranos
źródło