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.

JasonStoltz
fuente
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.

DoubleMalt
fuente
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"); 
línea costera
fuente
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.

Ola Berg
fuente
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;
}
Bren
fuente
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));
Giani Segatto
fuente
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

AlexR
fuente
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