2011-05-05 28 views
16

En Java que tengo:Cómo extraer los parámetros de una URL dada

String params = "depCity=PAR&roomType=D&depCity=NYC"; 

quiero conseguir valores de parámetros (PAR depCity, Nueva York).

así que creé expresiones regulares:

String regex = "depCity=([^&]+)"; 
Pattern p = Pattern.compile(regex); 
Matcher m = p.matcher(params); 

m.find() vuelve falsa. m.groups() está devolviendo IllegalArgumentException.

¿Qué estoy haciendo mal?

+0

duplicado posible de [Analiza una cadena URI en nombre-valor Colección] (https://stackoverflow.com/questions/13592236/parse-a-uri-string-into-name-value-collection) –

Respuesta

39

No tiene que ser regex. Ya que creo que no hay ningún método estándar para manejar esta cosa, estoy usando algo que he copiado de algún sitio (y tal vez modificado un poco):

public static Map<String, List<String>> getQueryParams(String url) { 
    try { 
     Map<String, List<String>> params = new HashMap<String, List<String>>(); 
     String[] urlParts = url.split("\\?"); 
     if (urlParts.length > 1) { 
      String query = urlParts[1]; 
      for (String param : query.split("&")) { 
       String[] pair = param.split("="); 
       String key = URLDecoder.decode(pair[0], "UTF-8"); 
       String value = ""; 
       if (pair.length > 1) { 
        value = URLDecoder.decode(pair[1], "UTF-8"); 
       } 

       List<String> values = params.get(key); 
       if (values == null) { 
        values = new ArrayList<String>(); 
        params.put(key, values); 
       } 
       values.add(value); 
      } 
     } 

     return params; 
    } catch (UnsupportedEncodingException ex) { 
     throw new AssertionError(ex); 
    } 
} 

lo tanto, cuando usted lo llama, obtendrá todos los parámetros y sus valores El método maneja params multivalor, de ahí el List<String> en lugar de String, y en su caso deberá obtener el primer elemento de lista.

+0

Esta solución también está funcionando, pero personalmente no soy fan de Maps, intento usar soluciones que son más simples. ¡Pero gracias de cualquier manera! – gospodin

+8

Los mapas son un concepto muy básico y simple, por lo que no veo ningún problema con ellos. – Bozho

+3

Esta solución no considera el fragmento parte de una URL que se adjunta al final después de un "#". En http urls, esta parte hace referencia a un anclaje interno. Por lo tanto, la consulta variable debe dividirse nuevamente en "#" y luego el índice 0 de la matriz devuelta debe procesarse adicionalmente. – haferblues

13

No estoy seguro de cómo se utiliza find y group, pero esto funciona bien:

String params = "depCity=PAR&roomType=D&depCity=NYC"; 

try { 
    Pattern p = Pattern.compile("depCity=([^&]+)"); 
    Matcher m = p.matcher(params); 
    while (m.find()) { 
     System.out.println(m.group()); 
    } 
} catch (PatternSyntaxException ex) { 
    // error handling 
} 

Sin embargo, si sólo desea que los valores, no la clave depCity= entonces usted puede utilizar m.group(1) o utilizar una expresión regular con lookarounds :

Pattern p = Pattern.compile("(?<=depCity=).*?(?=&|$)"); 

funciona en el mismo código Java como anteriormente. Trata de encontrar una posición de inicio justo después del depCity=. A continuación, compara todo lo menos posible hasta que llegue a un punto frente a & o al final de la entrada.

+0

¡Esto funciona perfectamente! Gracias – gospodin

+1

Solo una pequeña observación: en lugar de usar el patrón de complicación "(? <= depCity =). *? (? = & | $)" para obtener solo valores, estoy usando la primera solución "depCity = ([^ &] +) "en combinación con m.group (1) para obtener solo valores. – gospodin

5

Tengo tres soluciones, la tercera es una versión mejorada de Bozho.

En primer lugar, si usted no quiere escribir cosas usted mismo y sólo tiene que utilizar una librería, a continuación, utilizar httpcomponents clase de Apache de lib UriBuilder: http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html

new URIBuilder("http://...").getQueryParams()... 

Segundo:

// overwrites duplicates 
import org.apache.http.NameValuePair; 
import org.apache.http.client.utils.URLEncodedUtils; 
public static Map<String, String> readParamsIntoMap(String url, String charset) throws URISyntaxException { 
    Map<String, String> params = new HashMap<>(); 

    List<NameValuePair> result = URLEncodedUtils.parse(new URI(url), charset); 

    for (NameValuePair nvp : result) { 
     params.put(nvp.getName(), nvp.getValue()); 
    } 

    return params; 
} 

Segundo:

public static Map<String, List<String>> getQueryParams(String url) throws UnsupportedEncodingException { 
    Map<String, List<String>> params = new HashMap<String, List<String>>(); 
    String[] urlParts = url.split("\\?"); 
    if (urlParts.length < 2) { 
     return params; 
    } 

    String query = urlParts[1]; 
    for (String param : query.split("&")) { 
     String[] pair = param.split("="); 
     String key = URLDecoder.decode(pair[0], "UTF-8"); 
     String value = ""; 
     if (pair.length > 1) { 
      value = URLDecoder.decode(pair[1], "UTF-8"); 
     } 

     // skip ?& and && 
     if ("".equals(key) && pair.length == 1) { 
      continue; 
     } 

     List<String> values = params.get(key); 
     if (values == null) { 
      values = new ArrayList<String>(); 
      params.put(key, values); 
     } 
     values.add(value); 
    } 

    return params; 
} 
+0

"versión mejorada de Bozho's"? Eso es un sacrilegio :) – Zeemee

7

Si está desarrollando una aplicación de Android, intente esto:

String yourParam = null; 
Uri uri = Uri.parse(url); 
     try { 
      yourParam = URLDecoder.decode(uri.getQueryParameter(PARAM_NAME), "UTF-8"); 
     } catch (UnsupportedEncodingException exception) { 
      exception.printStackTrace(); 
     } 
+0

¿Qué biblioteca usas para la clase 'Uri'? –

+0

import android.net.Uri; –

2

Solución simple crea el mapa de todos los nombres de param y valores y úsalo :).

import org.apache.commons.lang3.StringUtils; 

    public String splitURL(String url, String parameter){ 
       HashMap<String, String> urlMap=new HashMap<String, String>(); 
       String queryString=StringUtils.substringAfter(url,"?"); 
       for(String param : queryString.split("&")){ 
        urlMap.put(StringUtils.substringBefore(param, "="),StringUtils.substringAfter(param, "=")); 
       } 
       return urlMap.get(parameter); 
      } 
+0

Sugerencia: 'Agregar String param = URLDecoder.decode (param," UTF-8 ");' dentro del ciclo – Marckaraujo

1

Si primavera-web está presente en la ruta de clase, UriComponentsBuilder se puede utilizar.

MultiValueMap<String, String> queryParams = 
      UriComponentsBuilder.fromUriString(url).build().getQueryParams(); 
Cuestiones relacionadas