Spring MVC: ¿cómo obtener todos los parámetros de solicitud en un mapa en el controlador Spring?

183

URL de muestra:

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

No sé los nombres de attr1, att2 y attr4.

Me gustaría poder hacer algo así (o similar, no me importa, siempre y cuando tenga acceso al Mapa de nombre de parámetro de solicitud -> valor:

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

¿Cómo puedo lograr esto con Spring MVC?

MDb
fuente

Respuestas:

311

Si bien las otras respuestas son correctas, ciertamente no es la "forma de Spring" para usar el objeto HttpServletRequest directamente. La respuesta es bastante simple y lo que esperarías si estás familiarizado con Spring MVC.

@RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
@RequestParam Map<String,String> allRequestParams, ModelMap model) {
   return "viewName";
}
Adam Gent
fuente
41
Si está buscando procesar valores de lista, como de un grupo de casillas de verificación con el mismo nombre, use: @RequestParam MultiValueMap<String, String>
IcedDante
1
Gracias por esto. También puede hacer lo mismo con los encabezados: stackoverflow.com/a/19556291/2599745
Rob Worsnop el
3
Esto solo funciona cuando el método de solicitud es GET o POST. No funciona para los métodos de solicitud PUT, DELETE, etc.
George Siggouroglou
No olvides agregar import org.springframework.ui.ModelMap;también.
truthadjustr
@typelogic ModelMapno es necesario para obtener todos los parámetros de solicitud como mapa; eso es simplemente un detalle específico del código de OP.
xlm
34

Editar

Se ha señalado que existe ( al menos a partir de 3.0 ) un mecanismo Spring MVC puro por el cual se podrían obtener estos datos. No lo detallaré aquí, ya que es la respuesta de otro usuario. Vea la respuesta de @ AdamGent para más detalles, y no se olvide de votarla.

En la documentación de Spring 3.2, este mecanismo se menciona tanto en la RequestMappingpágina JavaDoc como en la RequestParampágina JavaDoc, pero anteriormente, solo se menciona en la RequestMappingpágina. En la documentación 2.5 no se menciona este mecanismo.

Este es probablemente el enfoque preferido para la mayoría de los desarrolladores, ya que elimina (al menos esto) el enlace al HttpServletRequestobjeto definido por el servlet-api jar.

/Editar

Debe tener acceso a la cadena de consulta de solicitudes a través de request.getQueryString().

Además de getQueryString, los parámetros de consulta también se pueden recuperar de request.getParameterMap () como un mapa.

nicholas.hauschild
fuente
12
Sospecho que alguien rechazó esta respuesta solo porque getQueryString devuelve una Cadena y no un Mapa. El operador estaba buscando un mapa de parámetros. Agregué getParameterMap a su respuesta para ayudar a que sea más correcta :) +1
jmort253
No, voté en contra porque no es la forma de Spring MVC de hacerlo. @RequestParamcon gusto tomaré un Mapcomo parámetro (ver mi respuesta).
Adam Gent
@AdamGent La pregunta se hizo en un momento en que Spring 3.2 aún no se había lanzado. Regrese y eche un vistazo a JavaDoc para 3.1, y notará que no se menciona la utilización @RequestParamen un Map<String,String>para recuperar todos los parámetros de cadena de consulta. Y por favor, no se sienten tan aborrecidos sobre las respuestas que usted ve aquí ... no son que los malos :) static.springsource.org/spring/docs/3.1.x/javadoc-api/org/...
Nicholas. hauschild
Creo que existía en 3.1 pero no era JavaDoced. No dije que me aborrecieran, pero me sorprendió que @RequestParam Map<>no se hiciera el camino. Tengo una ligera molestia en que muchos proyectos modernos que he visto Spring MVC (spring 3.1 y superior) pondrán HttpServletRequest y HttpServletResponse en cada método. Y parece que es porque los desarrolladores junior usan StackOverflow y google en lugar de mirar el documento. Esto dificulta que el proyecto Spring cambie de la API de servlet para decir una API Netty. JAX-RS tiene problemas similares de abuso, pero en un grado mucho menor.
Adam Gent
Y es JavaDoced en 3.1 simplemente no en todos los lugares correctos: " Además, @RequestParam se puede usar en un parámetro de método Map <String, String> o MultiValueMap <String, String> para obtener acceso a todos los parámetros de solicitud ". De hecho, se remonta a la versión 3.0 (sabía que lo usaba antes de 3.1). Mi molestia sigue en pie en que la gente no se molestó en hacer la investigación :)
Adam Gent
14

El objeto HttpServletRequest ya proporciona un mapa de parámetros. Ver request.getParameterMap () para más detalles.

Kevin
fuente
1
Obtener mapa de parámetros también contendrá datos de formulario de una solicitud POST. Si el usuario no conoce las claves en la cadena de consulta, ¿cómo podrá distinguir entre lo que vino de la cadena de consulta y lo que proviene de los datos de un cuerpo POST?
nicholas.hauschild
¿Me está diciendo que va a procesar una publicación de formulario pero no tiene idea de cuáles son los parámetros reales del formulario?
Kevin
2
La pregunta dice que no sabe cuáles son los nombres de los parámetros. Además, tampoco sé qué son. ;)
nicholas.hauschild
Lo siento, creo que la premisa es un poco ridícula.
Kevin
11
Tiene sentido en una aplicación basada en datos. Uno en el que el cliente puede crear rutas de solicitud y cadenas de consulta, y el servidor de aplicaciones buscaría el valor correspondiente (de cualquier tipo de fuente de datos) utilizando estas rutas y cadenas de consulta como claves.
nicholas.hauschild
12

simplemente puedes usar esto:

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

Eso debería funcionar bien

Biggy_java
fuente
10

Aquí está el ejemplo simple de obtener parámetros de solicitud en un 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 );
       }

En este caso, vinculará el valor de studentName y studentEmail con las variables de nombre y correo electrónico respectivamente.

Shrirang Kadale
fuente
8

Úselo org.springframework.web.context.request.WebRequestcomo parámetro en su método de controlador, proporciona el método getParameterMap(), la ventaja es que no ajusta su aplicación a la API de Servlet, WebRequest es un ejemplo de objeto de contexto de patrón JavaEE.

Diego Lins de Freitas
fuente
6

Hay dos interfaces

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

Permite el acceso genérico a parámetros de solicitud, así como el request/sessionacceso a atributos, sin vínculos con la API nativa de Servlet / Portlet .

Ex.:

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

PD: hay documentos sobre argumentos que se pueden usar como parámetros del controlador.

katoquro
fuente
Gracias funciona ¿Puedo preguntar, de qué sirve String[]el valor? Tengo que indexarlo a 0 solo para obtener el valor.
truthadjustr
Puede haber una matriz de valores como key=val1,val2o key=val1&key=val2(si recuerdo correctamente el soporte de resorte de ambas notaciones) para que obtenga una matriz con 2 elementos
katoquro
6

Puede que llegue tarde a la fiesta, pero según tengo entendido, estás buscando algo como esto:

for(String params : Collections.list(httpServletRequest.getParameterNames())) {
    // Whatever you want to do with your map
    // Key : params
    // Value : httpServletRequest.getParameter(params)                
}
goelanshul
fuente
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 los parámetros serán almacenados en jsonObject.

Agyaey Tiwari
fuente
1

Hay una diferencia fundamental entre los parámetros de consulta y los parámetros de ruta. Es así: www.your_domain?queryparam1=1&queryparam2=2- parámetros de consulta. www.your_domain/path_param1/entity/path_param2- parámetros de ruta.

Lo que me sorprendió es que en el mundo de Spring MVC muchas personas confunden una con la otra. Si bien los parámetros de consulta son más como criterios para una búsqueda, los parámetros de ruta probablemente identificarán un recurso de manera única. Dicho esto, no significa que no pueda tener múltiples parámetros de ruta en su URI, porque la estructura de recursos puede estar anidada. Por ejemplo, supongamos que necesita un recurso de automóvil específico de una persona específica:

www.my_site/customer/15/car/2 - Buscando un segundo automóvil de un 15º cliente.

¿Cuál sería un caso de uso para poner todos los parámetros de ruta en un mapa? Los parámetros de ruta no tienen una "clave" cuando miras un URI en sí, esas claves dentro del mapa se tomarán de tu anotación @Mapping, por ejemplo:

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

Desde la perspectiva HTTP / REST, los parámetros de ruta no pueden proyectarse realmente en un mapa. En mi opinión, se trata de la flexibilidad de Spring y su deseo de acomodar cualquier capricho de los desarrolladores.

Nunca usaría un mapa para parámetros de ruta, pero puede ser bastante útil para parámetros de consulta.

yuranos
fuente