HttpServletRequest: obtiene parámetros de cadena de consulta, sin datos de formulario


76

En HttpServletRequest , getParameterMapdevuelve un mapa de todos los parámetros de cadena de consulta y parámetros de datos de publicación.

¿Hay alguna forma de obtener un mapa de SOLO parámetros de cadena de consulta? Estoy tratando de evitar usar getQueryString y analizar los valores.


15
Puede tener ambos ... puede tener parámetros de cadena de consulta en una solicitud POST. Y en ese caso, todos son devueltos por "getParameterMap"
JasonStoltz

Oh, ok. ¿Por qué uno necesita ambos, solo por curiosidad?
Jacob

2
Porque en la página resultante, quiero que aparezca una cadena de consulta en la url / estar en la cadena de consulta. Tenemos un sistema de seguimiento que busca parámetros específicos en la cadena de consulta.
JasonStoltz

req.getParameterMap (). containsKey ("nombre de usuario");
Parag Jadhav

Respuestas:


22

Al contrario de lo que dijo cularis, puede haber ambos en el mapa de parámetros.

La mejor manera que veo es utilizar el mapa de parámetros como proxy y, para cada recuperación de parámetro, verificar si queryString contiene "&? <parameterName> =".

Tenga en cuenta que parameterName debe estar codificado en URL antes de que se pueda realizar esta verificación, como señaló Qerub.

Eso le ahorra el análisis y aún le brinda solo parámetros de URL.


2
Tenga en cuenta que parameterNamedebe estar codificado en URL antes de que se pueda realizar esta verificación.
qerub

12
La cadena de consulta nunca contiene ?. Ese es el carácter separador entre URI y cadena de consulta.
BalusC

Hola @DoubleMalt, tengo el mismo requisito, pero no puedo obtener la solución que proporcionaste. ¿Puede proporcionar un código de ejemplo?
Vishal Zanzrukia

@VishalZanzrukia: ¿Cuál es tu código que no funciona?
DoubleMalt

1
Me gusta la idea, pero no siempre hay un carácter "=" en la cadena de consulta. Si el valor del parámetro está vacío, solo hay <parameterName> en la cadena de consulta. Personalmente, creo que dividir por "&" y "=" sería una mejor solución.
Bren

95

Puede usar request.getQueryString(), si la cadena de consulta es como

username=james&password=pwd

Para obtener un nombre, puedes hacer esto

request.getParameter("username"); 

Esto es para usar páginas de un servidor Java.
Jorgesys

2
el segundo estropeará el flujo de solicitud, supongo que la pregunta es cómo obtener el nombre de usuario y mantener el flujo de entrada para su procesamiento posterior
Pavel Niedoba

23

La API del servlet carece de esta característica porque se creó en un momento en que muchos creían que la cadena de consulta y el cuerpo del mensaje eran solo dos formas diferentes de enviar parámetros, sin darse cuenta de que los propósitos de los parámetros son fundamentalmente diferentes.

Los parámetros de la cadena de consulta? Foo = bar son parte de la URL porque están involucrados en la identificación de un recurso (que podría ser una colección de muchos recursos), como "todas las personas de 42 años":

GET / personas? Edad = 42

Los parámetros del cuerpo del mensaje en POST o PUT están ahí para expresar una modificación a los recursos de destino. Fx estableciendo un valor para el atributo "cabello":

PUT / personas? Edad = 42

cabello = gris

Por lo tanto, definitivamente es RESTful usar los parámetros de consulta y los parámetros del cuerpo al mismo tiempo, separados para que pueda usarlos para diferentes propósitos. La característica definitivamente falta en la API de servlet de Java.


12

Como dicen las otras respuestas, no hay forma de obtener parámetros de cadena de consulta usando la API de servlet.

Entonces, creo que la mejor manera de obtener parámetros de consulta es analizar la cadena de consulta usted mismo. (Es más complicado iterar sobre los parámetros y verificar si la cadena de consulta contiene el parámetro)

Escribí el siguiente código para obtener los parámetros de la cadena de consulta. Usando apache StringUtils y ArrayUtils que también admite valores de parámetros de consulta separados por CSV.

Ejemplo: username=james&username=smith&password=pwd1,pwd2volverá

password : [pwd1, pwd2] (longitud = 2)

username : [james, smith] (longitud = 2)

public static Map<String, String[]> getQueryParameters(HttpServletRequest request) throws UnsupportedEncodingException {
    Map<String, String[]> queryParameters = new HashMap<>();
    String queryString = request.getQueryString();
    if (StringUtils.isNotEmpty(queryString)) {
        queryString = URLDecoder.decode(queryString, StandardCharsets.UTF_8.toString());
        String[] parameters = queryString.split("&");
        for (String parameter : parameters) {
            String[] keyValuePair = parameter.split("=");
            String[] values = queryParameters.get(keyValuePair[0]);
            //length is one if no value is available.
            values = keyValuePair.length == 1 ? ArrayUtils.add(values, "") :
                    ArrayUtils.addAll(values, keyValuePair[1].split(",")); //handles CSV separated query param values.
            queryParameters.put(keyValuePair[0], values);
        }
    }
    return queryParameters;
}

Considero que esto es mucho mejor que la respuesta aceptada, no sé por qué evitar analizar la cadena de consulta porque crear un proxy no es una mejor solución
Pavel Niedoba

1
Me pregunto, si alguno de los parámetros de consulta contiene un &carácter en su valor, si le dará el resultado correcto
amdg

1
@amdg: ese carácter estaría codificado en URL, por lo que el código es bueno. Si no estuviera codificado, la cadena no se podría analizar.
maratón

Considere usar URLDecoder.decode(keyValuePair[0])(o [1]) también: docs.oracle.com/javase/6/docs/api/java/net/URLDecoder.html
Plutón

1
Los parámetros de consulta con valores separados por csv no se consideran aquí. por ejemplo: username=james&username=smith&password=pwd1,pwd2tendrá un mapa con 2 valores para el nombre de usuario (que es correcto) pero solo 1 valor para la contraseña (que es incorrecta)
Niv

4

Java 8

return Collections.list(httpServletRequest.getParameterNames())
                  .stream()
                  .collect(Collectors.toMap(parameterName -> parameterName, httpServletRequest::getParameterValues));

2

Me temo que no hay forma de analizar los parámetros de la cadena de consulta por separado de los parámetros de la publicación. Por cierto, el hecho de que dicha API esté ausente puede significar que probablemente debería verificar su diseño. ¿Por qué utiliza una cadena de consulta al enviar POST? Si realmente desea enviar más datos a la URL, use una convención similar a REST, por ejemplo, en lugar de enviar

http://mycompany.com/myapp/myservlet?first=11&second=22

decir:

http://mycompany.com/myapp/myservlet/11/22


Estoy usando el parámetro de cadena de consulta en un POST porque quiero mantener todas y cada una de las cadenas de consulta pasadas al formulario original a través del POST. Esto es principalmente para fines de seguimiento ... no estoy seguro de que la convención similar a REST funcione en este caso, porque estoy bastante seguro de que la biblioteca de seguimiento busca parámetros específicos en la cadena de consulta.
JasonStoltz

¿Alguna razón en particular por la que recomendaría usar la convención similar a REST para un parámetro de cadena de consulta? ¿No estoy seguro de entender cuál es la ventaja?
JasonStoltz

8
"Por cierto, el hecho de que tal API esté ausente puede significar que probablemente debería comprobar su diseño". En este caso, significa que Oracle debería verificar su diseño :)
Stijn de Witt
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.