Analyser les chaînes de requête sur Android

271

Java EE a ServletRequest.getParameterValues ​​() .

Sur les plates-formes non EE, URL.getQuery () renvoie simplement une chaîne.

Quelle est la façon normale d'analyser correctement la chaîne de requête dans une URL lorsqu'elle n'est pas sur Java EE?


<coup de gueule >

Il est populaire dans les réponses d'essayer de créer votre propre analyseur. C'est un projet de micro-codage très intéressant et passionnant, mais je ne peux pas dire que c'est une bonne idée :(

Les extraits de code ci-dessous sont généralement défectueux ou cassés, entre autres. Les briser est un exercice intéressant pour le lecteur. Et aux pirates qui attaquent les sites Web qui les utilisent .

L'analyse des chaînes de requête est un problème bien défini, mais la lecture de la spécification et la compréhension des nuances ne sont pas triviales. Il est préférable de laisser un codeur de bibliothèque de plate-forme faire le travail dur et faire la réparation pour vous!

< / rant >

Volonté
la source
Pourriez-vous publier un exemple d'URL, ce que vous obtenez getQuery()et ce que vous souhaitez obtenir en sortie?
Thomas Owens
1
Voulez-vous le faire à partir d'une servlet ou d'une page JSP? J'ai besoin d'éclaircissements avant de répondre.
ChadNC
1
Avez-vous également besoin d'analyser les paramètres POST?
Thilo
2
Même si vous êtes sur J2EE (ou sur SE avec des packages EE sélectionnés ajoutés via OSGi, comme moi), cette question pourrait avoir un sens. Dans mon cas, les chaînes de requête / corps POST encodés en URL sont traités par une partie du système qui est intentionnellement agnostique ServletRequest.
Hanno Fietz
61
A voté pour <rant />!
Nowaker

Réponses:

65

Depuis Android M, les choses sont devenues plus compliquées. La réponse de android.net.URI .getQueryParameter () a un bug qui brise les espaces avant JellyBean. Apache URLEncodedUtils.parse () a fonctionné, mais a été abandonnée à L , et éliminé M .

La meilleure réponse est donc maintenant UrlQuerySanitizer . Cela existe depuis le niveau 1 de l'API et existe toujours. Cela vous fait également réfléchir aux problèmes délicats comme la façon de gérer les caractères spéciaux ou les valeurs répétées.

Le code le plus simple est

UrlQuerySanitizer.ValueSanitizer sanitizer = UrlQuerySanitizer.getAllButNullLegal();
// remember to decide if you want the first or last parameter with the same name
// If you want the first call setPreferFirstRepeatedParameter(true);
sanitizer.parseUrl(url);
String value = sanitizer.getValue("paramName"); // get your value

Si vous êtes satisfait du comportement d'analyse par défaut, vous pouvez faire:

new UrlQuerySanitizer(url).getValue("paramName")

mais vous devez vous assurer que vous comprenez quel est le comportement d'analyse par défaut, car ce n'est peut-être pas ce que vous voulez.

Nick Fortescue
la source
4
URLQuerySanitizer.getAllButNullLegal () renvoie UrlQuerySanitizer.ValueSanitizer, pas UrlQuerySanitizer.
Peter Zhao
31
Pour une raison quelconque, ce qui précède n'a pas fonctionné pour moi, j'ai dû le modifier légèrement - ce qui le rend encore plus facile:UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(YourStringURL); String value = sanitizer.getValue("parameter");
SeBsZ
3
Ne fonctionne pas. UrlQuerySanitizer dans sdk-23 n'a qu'une seule méthodesanitize()
Ninja
Cela décodera les caractères spéciaux et les emoji _. Je devais aller avec stackoverflow.com/a/35638979/1155282
Irshu
Existe-t-il une bibliothèque équivalente du framework Spring?
iamjoshua
202

Sur Android:

import android.net.Uri;

[...]

Uri uri=Uri.parse(url_string);
uri.getQueryParameter("para1");
bricolage
la source
20
notez que cela utilise la classe Uri et non la classe URI (Uri fait partie de android.net, tandis que l'URI fait partie de java.net)
Marius
5
Notez également qu'avant Ice Cream Sandwich, cela ne parvient pas à analyser + caractères dans les valeurs d'un caractère espace.
rpetrich
@rpetrich en fait, les docs disent que le bug est antérieur à Jelly Bean, y compris Ice Cream Sandwich. ref
Big McLargeHuge
64

Sur Android, les bibliothèques Apache fournissent un analyseur de requêtes:

http://developer.android.com/reference/org/apache/http/client/utils/URLEncodedUtils.html et http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/ http / client / utils / URLEncodedUtils.html

Volonté
la source
9
Ceci est disponible dans la bibliothèque client apache http, pas seulement sur Android. Btw, le lien vers apache a été modifié. Le plus récent est: hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Cristian Vrabie
9
URLEncodedUtils.parse()Retourne un ennuyeux Listque vous devrez ensuite parcourir pour trouver la valeur d'une clé spécifique. Ce serait beaucoup plus agréable si cela retournait un peu Mapcomme dans la réponse de BalusC.
Asaph
1
@Hanno Fietz, vous voulez dire que vous faites confiance à ces alternatives? Je sais qu'ils sont buggés. Je sais que signaler les bogues que je vois n'encouragera que les gens à adopter des versions «fixes», plutôt que de rechercher eux-mêmes les bogues que j'ai négligés.
Will
1
@Will - eh bien, je ne ferais jamais confiance aux extraits de copier-coller que j'ai reçus de n'importe quel site Web, et personne ne devrait. Mais ici, ces extraits sont plutôt bien examinés et commentés et donc arevraiment utiles, en fait. Le simple fait de voir quelques suggestions sur ce qui pourrait ne pas fonctionner avec le code est déjà d'une grande aide pour réfléchir par moi-même. Et attention, je ne voulais pas dire "rouler le vôtre c'est mieux", mais plutôt que c'est génial d'avoir du bon matériel pour une décision éclairée dans mon propre code.
Hanno Fietz
8
J'imagine que parse retourne une liste afin qu'elle maintienne l'ordre de position et autorise plus facilement les entrées en double.
dhaag23
26

Voici la réponse de BalusC , mais elle compile et renvoie des résultats:

public static Map<String, List<String>> getUrlParameters(String url)
        throws UnsupportedEncodingException {
    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;
}
dfrankow
la source
1
Remarque JVM: J'ai implémenté une forme équivalente de ceci dans Scala en utilisant des collections Java; voici l'essentiel de github: gist.github.com/3504765
Jay Taylor
2
Je suggère de changer String pair[] = param.split("=");en String pair[] = param.split("=", 2);pour diviser la paire clé = valeur uniquement lors de la première occurrence. Je crois qu'il est permis d'avoir des signes égaux non codés dans la valeur.
Dennie
22

Si vous avez des bibliothèques jetty (serveur ou client) sur votre chemin de classe, vous pouvez utiliser les classes util jetty (voir javadoc ), par exemple:

import org.eclipse.jetty.util.*;
URL url = new URL("www.example.com/index.php?foo=bar&bla=blub");
MultiMap<String> params = new MultiMap<String>();
UrlEncoded.decodeTo(url.getQuery(), params, "UTF-8");

assert params.getString("foo").equals("bar");
assert params.getString("bla").equals("blub");
moritz
la source
13

Si vous utilisez Spring 3.1 ou une version ultérieure (oui, j'espérais que le support allait plus loin), vous pouvez utiliser les touches UriComponentset UriComponentsBuilder:

UriComponents components = UriComponentsBuilder.fromUri(uri).build();
List<String> myParam = components.getQueryParams().get("myParam");

components.getQueryParams() renvoie un MultiValueMap<String, String>

Voici un peu plus de documentation .

Nick Spacek
la source
C'est quelque chose que je recherche. Ma question est de savoir comment obtenir l'URI? Je suis bloqué avec la maintenance du code que je ne peux pas changer beaucoup et nous n'utilisons pas HttpServlet. Au lieu de cela, il suffit d'utiliser des annotations et Spring (@Get, @Produces (mediaType) et @Path ("/ dataAsJSON / datafield / {datafield})) Il suffit de savoir comment obtenir la chaîne de requête afin que je puisse l'analyser comme indiqué dans cet exemple.
Nelda.techspiress
5

Pour une servlet ou une page JSP, vous pouvez obtenir des paires clé / valeur de chaîne de requête en utilisant request.getParameter ("paramname")

String name = request.getParameter("name");

Il existe d'autres façons de le faire, mais c'est ainsi que je le fais dans toutes les servlets et pages jsp que je crée.

ChadNC
la source
3
HttpServletRequest fait partie de J2EE qu'il n'a pas. L'utilisation de getParamter () n'est pas vraiment une analyse.
M. Shiny et New 安 宇
3
Veuillez prendre le temps de lire le commentaire dans lequel j'ai demandé des éclaircissements sur sa question. Cette réponse est en réponse à sa réponse à ce commentaire dans lequel il a déclaré: «J'essaie de le faire sur Android, mais toutes les réponses sur toutes les plates-formes seraient des réponses utiles qui pourraient donner des pointeurs (également à d'autres qui pourraient rencontrer ce question) alors ne vous retenez pas! " J'ai répondu à sa question sur la base de ce commentaire. Si vous n'avez rien d'utile à ajouter, n'ajoutez rien
ChadNC
1
Ne vous inquiétez pas trop. "Cela ne répond pas à la question" est utile d'ajouter, OMI.
M. Shiny et New 安 宇
1
Peu importe Android ou non, la question est de savoir comment analyser la chaîne contenant l'URL et en extraire les paramètres. Ce que vous portez ici fait partie de l'API Servlet, où le conteneur Servlet analyse les paramètres entrants de la requête HTTP pour vous. Ce n'est pas pertinent, car la question concerne l'analyse de la chaîne qui contient l'URL, pas la demande HTTP, et pas à l'intérieur du conteneur Servlet.
mvmn
5

Sur Android, j'ai essayé d'utiliser la réponse @diyism mais j'ai rencontré le problème de caractère d'espace soulevé par @rpetrich, par exemple: je remplis un formulaire où username = "us+us"et password = "pw pw"faisant ressembler une chaîne URL:

http://somewhere?username=us%2Bus&password=pw+pw

Cependant, le code @diyism renvoie "us+us"et "pw+pw", c'est-à-dire qu'il ne détecte pas le caractère espace. Si l'URL a été réécrite avec %20le caractère espace est identifié:

http://somewhere?username=us%2Bus&password=pw%20pw

Cela conduit au correctif suivant:

Uri uri = Uri.parse(url_string.replace("+", "%20"));
uri.getQueryParameter("para1");
Stephen Quan
la source
replace(" ", "%20")cela ne va pas. Mais a fait l'affaire pour moi: D
Mārtiņš Briedis
La syntaxe correcte doit être "une chaîne" .replaceAll ("[+]", "% 20");
RRTW
4

L'analyse de la chaîne de requête est un peu plus compliquée qu'il n'y paraît, selon la façon dont vous pardonnez.

Tout d'abord, la chaîne de requête est en octets ascii. Vous lisez ces octets un par un et les convertissez en caractères. Si le personnage est? ou & puis il signale le début d'un nom de paramètre. Si le caractère est = alors il signale le début d'une valeur de paramètre. Si le caractère est%, il signale le début d'un octet codé. Voici où cela devient délicat.

Lorsque vous lisez dans un% char, vous devez lire les deux octets suivants et les interpréter comme des chiffres hexadécimaux. Cela signifie que les deux octets suivants seront 0-9, af ou AF. Collez ces deux chiffres hexadécimaux ensemble pour obtenir votre valeur d'octet. Mais rappelez-vous, les octets ne sont pas des caractères . Vous devez savoir quel encodage a été utilisé pour encoder les caractères. Le caractère é n'encode pas la même chose en UTF-8 qu'en ISO-8859-1. En général, il est impossible de savoir quel encodage a été utilisé pour un jeu de caractères donné. J'utilise toujours UTF-8 parce que mon site Web est configuré pour toujours servir tout en utilisant UTF-8 mais en pratique, vous ne pouvez pas en être certain. Certains user-agents vous indiqueront l'encodage des caractères dans la requête; vous pouvez essayer de lire cela si vous avez une demande HTTP complète. Si vous avez juste une URL isolée, bonne chance.

Quoi qu'il en soit, en supposant que vous utilisez UTF-8 ou un autre codage de caractères multi-octets, maintenant que vous avez décodé un octet codé, vous devez le mettre de côté jusqu'à ce que vous capturiez l'octet suivant. Vous avez besoin de tous les octets codés qui sont ensemble, car vous ne pouvez pas décoder correctement l'url un octet à la fois. Mettez de côté tous les octets qui sont ensemble puis décodez-les tous à la fois pour reconstruire votre personnage.

De plus, cela devient plus amusant si vous voulez être indulgent et tenir compte des agents utilisateurs qui gèrent les URL. Par exemple, certains clients de messagerie Web codent deux fois des éléments. Ou doublez les caractères? & = (Par exemple:) http://yoursite.com/blah??p1==v1&&p2==v2. Si vous voulez essayer de gérer cela avec élégance, vous devrez ajouter plus de logique à votre analyseur.

M. brillant et nouveau 安 宇
la source
Cela n'explique pas comment analyser ou récupérer les valeurs des paramètres de la chaîne de
requête
D'accord, mais un peu lourd. Pour cela, nous avons déjà URLDecoder.
BalusC
2
@ChadNC: la troisième phrase vous indique comment analyser: lire un octet à la fois et convertir en caractères. La quatrième phrase vous avertit des caractères spéciaux. Etc. Peut-être que vous n'avez pas lu la réponse?
M. Shiny et New 安 宇
@BalusC: URLDecoder fonctionne mais il a des modes d'échec si vous essayez d'être plus indulgent dans le type d'URL que vous acceptez.
M. Shiny et New 安 宇
1
D'accord avec @ Mr.ShinyAndNew param de requête d'analyse n'est pas facile. Je soutiens FIQL et cela devient une vraie douleur dans le cul. Par exemple: yoursite.com/blah??p1==v1&&p2==v2,p2==v3;p2==v4
rafa.ferreira
4

Sur Android, c'est aussi simple que le code ci-dessous:

UrlQuerySanitizer sanitzer = new UrlQuerySanitizer(url);
String value = sanitzer.getValue("your_get_parameter");

De plus, si vous ne souhaitez pas enregistrer chaque utilisation de clé de requête attendue:

sanitzer.setAllowUnregisteredParamaters(true)

Avant d'appeler:

sanitzer.parseUrl(yourUrl)
Kevin Crain
la source
4

J'ai des méthodes pour y parvenir:

1) :

public static String getQueryString(String url, String tag) {
    String[] params = url.split("&");
    Map<String, String> map = new HashMap<String, String>();
    for (String param : params) {
        String name = param.split("=")[0];
        String value = param.split("=")[1];
        map.put(name, value);
    }

    Set<String> keys = map.keySet();
    for (String key : keys) {
        if(key.equals(tag)){
         return map.get(key);
        }
        System.out.println("Name=" + key);
        System.out.println("Value=" + map.get(key));
    }
    return "";
}

2) et la façon la plus simple de le faire en utilisant la classe Uri :

public static String getQueryString(String url, String tag) {
    try {
        Uri uri=Uri.parse(url);
        return uri.getQueryParameter(tag);
    }catch(Exception e){
        Log.e(TAG,"getQueryString() " + e.getMessage());
    }
    return "";
}

et ceci est un exemple de la façon d'utiliser l'une des deux méthodes:

String url = "http://www.jorgesys.com/advertisements/publicidadmobile.htm?position=x46&site=reform&awidth=800&aheight=120";      
String tagValue = getQueryString(url,"awidth");

la valeur de tagValue est 800

Jorgesys
la source
3

Sur Android, vous pouvez utiliser la méthode statique Uri.parse de la classe android.net.Uri pour faire le gros du travail. Si vous faites quoi que ce soit avec des URI et des intentions, vous voudrez de toute façon l'utiliser.

Patrick O'Leary
la source
3

Juste pour référence, c'est ce que j'ai fini avec (basé sur URLEncodedUtils et renvoyant une carte).

Fonctionnalités:

  • il accepte la partie chaîne de requête de l'url (vous pouvez l'utiliser request.getQueryString())
  • une chaîne de requête vide produira un vide Map
  • un paramètre sans valeur (? test) sera mappé à un vide List<String>

Code:

public static Map<String, List<String>> getParameterMapOfLists(String queryString) {
    Map<String, List<String>> mapOfLists = new HashMap<String, List<String>>();
    if (queryString == null || queryString.length() == 0) {
        return mapOfLists;
    }
    List<NameValuePair> list = URLEncodedUtils.parse(URI.create("http://localhost/?" + queryString), "UTF-8");
    for (NameValuePair pair : list) {
        List<String> values = mapOfLists.get(pair.getName());
        if (values == null) {
            values = new ArrayList<String>();
            mapOfLists.put(pair.getName(), values);
        }
        if (pair.getValue() != null) {
            values.add(pair.getValue());
        }
    }

    return mapOfLists;
}

Un assistant de compatibilité (les valeurs sont stockées dans un tableau String comme dans ServletRequest.getParameterMap () ):

public static Map<String, String[]> getParameterMap(String queryString) {
    Map<String, List<String>> mapOfLists = getParameterMapOfLists(queryString);

    Map<String, String[]> mapOfArrays = new HashMap<String, String[]>();
    for (String key : mapOfLists.keySet()) {
        mapOfArrays.put(key, mapOfLists.get(key).toArray(new String[] {}));
    }

    return mapOfArrays;
}
Dan
la source
3

Cela fonctionne pour moi .. Je ne sais pas pourquoi chacun recherchait une carte, une liste> Tout ce dont j'avais besoin était une simple carte de valeur de nom.

Pour garder les choses simples, j'ai utilisé la construction dans URI.getQuery ();

public static Map<String, String> getUrlParameters(URI uri)
    throws UnsupportedEncodingException {
    Map<String, String> params = new HashMap<String, String>();
    for (String param : uri.getQuery().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");
        }
        params.put(new String(key), new String(value));
    }
    return params;
}
Dave
la source
1
que diriez-vous des formulaires avec sélection multiple? Il est parfaitement normal d'avoir des clés répétées dans des chaînes de requête légitimes (et des corps de formulaire POST). Il y a d'autres défauts et caisses d'angle non couverts; beaucoup d'entre eux ont été mentionnés dans les commentaires sur d'autres approches. Je m'abstiendrai de les signaler en craignant que vous ne le répariez au lieu d'utiliser une bibliothèque de qualité, conformément à ma diatribe dans la question;)
Will
2

Le Multimap de Goyave est mieux adapté à cela. Voici une version courte et épurée:

Multimap<String, String> getUrlParameters(String url) {
        try {
            Multimap<String, String> ret = ArrayListMultimap.create();
            for (NameValuePair param : URLEncodedUtils.parse(new URI(url), "UTF-8")) {
                ret.put(param.getName(), param.getValue());
            }
            return ret;
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }
pathikrit
la source
1

Apache AXIS2 a une implémentation autonome de QueryStringParser.java. Si vous n'utilisez pas Axis2, téléchargez simplement le code source et le cas de test à partir d'ici -

http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/util/QueryStringParser.java

http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/transport/http/util/QueryStringParserTest.java

Sripathi Krishnan
la source
1

Répondu d'origine ici

Sur Android, il y a la classe Uri dans le package android.net . Notez que Uri fait partie de android.net, tandis que URI fait partie de java.net.

La classe Uri a de nombreuses fonctions pour extraire les paires clé-valeur de requête. entrez la description de l'image ici

La fonction suivante renvoie des paires clé-valeur sous la forme de HashMap.

En Java:

Map<String, String> getQueryKeyValueMap(Uri uri){
    HashMap<String, String> keyValueMap = new HashMap();
    String key;
    String value;

    Set<String> keyNamesList = uri.getQueryParameterNames();
    Iterator iterator = keyNamesList.iterator();

    while (iterator.hasNext()){
        key = (String) iterator.next();
        value = uri.getQueryParameter(key);
        keyValueMap.put(key, value);
    }
    return keyValueMap;
}

À Kotlin:

fun getQueryKeyValueMap(uri: Uri): HashMap<String, String> {
        val keyValueMap = HashMap<String, String>()
        var key: String
        var value: String

        val keyNamesList = uri.queryParameterNames
        val iterator = keyNamesList.iterator()

        while (iterator.hasNext()) {
            key = iterator.next() as String
            value = uri.getQueryParameter(key) as String
            keyValueMap.put(key, value)
        }
        return keyValueMap
    }
Ramakrishna Joshi
la source
0

Je ne pense pas qu'il y en ait un dans JRE. Vous pouvez trouver des fonctions similaires dans d'autres packages comme Apache HttpClient. Si vous n'utilisez aucun autre package, il vous suffit d'écrire le vôtre. Ce n'est pas si dur. Voici ce que j'utilise,

public class QueryString {

 private Map<String, List<String>> parameters;

 public QueryString(String qs) {
  parameters = new TreeMap<String, List<String>>();

  // Parse query string
     String pairs[] = qs.split("&");
     for (String pair : pairs) {
            String name;
            String value;
            int pos = pair.indexOf('=');
            // for "n=", the value is "", for "n", the value is null
         if (pos == -1) {
          name = pair;
          value = null;
         } else {
       try {
        name = URLDecoder.decode(pair.substring(0, pos), "UTF-8");
              value = URLDecoder.decode(pair.substring(pos+1, pair.length()), "UTF-8");            
       } catch (UnsupportedEncodingException e) {
        // Not really possible, throw unchecked
           throw new IllegalStateException("No UTF-8");
       }
         }
         List<String> list = parameters.get(name);
         if (list == null) {
          list = new ArrayList<String>();
          parameters.put(name, list);
         }
         list.add(value);
     }
 }

 public String getParameter(String name) {        
  List<String> values = parameters.get(name);
  if (values == null)
   return null;

  if (values.size() == 0)
   return "";

  return values.get(0);
 }

 public String[] getParameterValues(String name) {        
  List<String> values = parameters.get(name);
  if (values == null)
   return null;

  return (String[])values.toArray(new String[values.size()]);
 }

 public Enumeration<String> getParameterNames() {  
  return Collections.enumeration(parameters.keySet()); 
 }

 public Map<String, String[]> getParameterMap() {
  Map<String, String[]> map = new TreeMap<String, String[]>();
  for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
   List<String> list = entry.getValue();
   String[] values;
   if (list == null)
    values = null;
   else
    values = (String[]) list.toArray(new String[list.size()]);
   map.put(entry.getKey(), values);
  }
  return map;
 } 
}
Codeur ZZ
la source
Quel est le chemin avec les classes apache?
Will
1
Vous pouvez utiliser la méthode parse (): hc.apache.org/httpcomponents-client/httpclient/apidocs/org/…
ZZ Coder
3
Veuillez mettre le lien apache commons dans sa propre réponse afin que je puisse le voter.
itsadok
0

Sur la base de la réponse de BalusC, j'ai écrit un exemple de code Java:

    if (queryString != null)
    {
        final String[] arrParameters = queryString.split("&");
        for (final String tempParameterString : arrParameters)
        {
            final String[] arrTempParameter = tempParameterString.split("=");
            if (arrTempParameter.length >= 2)
            {
                final String parameterKey = arrTempParameter[0];
                final String parameterValue = arrTempParameter[1];
                //do something with the parameters
            }
        }
    }
Andreas
la source
0
public static Map <String, String> parseQueryString (final URL url)
        throws UnsupportedEncodingException
{
    final Map <String, String> qps = new TreeMap <String, String> ();
    final StringTokenizer pairs = new StringTokenizer (url.getQuery (), "&");
    while (pairs.hasMoreTokens ())
    {
        final String pair = pairs.nextToken ();
        final StringTokenizer parts = new StringTokenizer (pair, "=");
        final String name = URLDecoder.decode (parts.nextToken (), "ISO-8859-1");
        final String value = URLDecoder.decode (parts.nextToken (), "ISO-8859-1");
        qps.put (name, value);
    }
    return qps;
}
wafna
la source
0

en utilisant la goyave:

Multimap<String,String> parseQueryString(String queryString, String encoding) {
    LinkedListMultimap<String, String> result = LinkedListMultimap.create();

    for(String entry : Splitter.on("&").omitEmptyStrings().split(queryString)) {
        String pair [] = entry.split("=", 2);
        try {
            result.put(URLDecoder.decode(pair[0], encoding), pair.length == 2 ? URLDecoder.decode(pair[1], encoding) : null);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    return result;
}
Tyson
la source
0

Répondre ici parce que c'est un fil populaire. Il s'agit d'une solution propre dans Kotlin qui utilise l' UrlQuerySanitizerAPI recommandée . Voir la documentation officielle . J'ai ajouté un générateur de chaînes pour concaténer et afficher les paramètres.

    var myURL: String? = null
    // if the url is sent from a different activity where you set it to a value
    if (intent.hasExtra("my_value")) {
        myURL = intent.extras.getString("my_value")
    } else {
        myURL = intent.dataString
    }

    val sanitizer = UrlQuerySanitizer(myURL)
    // We don't want to manually define every expected query *key*, so we set this to true
    sanitizer.allowUnregisteredParamaters = true
    val parameterNamesToValues: List<UrlQuerySanitizer.ParameterValuePair> = sanitizer.parameterList
    val parameterIterator: Iterator<UrlQuerySanitizer.ParameterValuePair> = parameterNamesToValues.iterator()

    // Helper simply so we can display all values on screen
    val stringBuilder = StringBuilder()

    while (parameterIterator.hasNext()) {
        val parameterValuePair: UrlQuerySanitizer.ParameterValuePair = parameterIterator.next()
        val parameterName: String = parameterValuePair.mParameter
        val parameterValue: String = parameterValuePair.mValue

        // Append string to display all key value pairs
        stringBuilder.append("Key: $parameterName\nValue: $parameterValue\n\n")
    }

    // Set a textView's text to display the string
    val paramListString = stringBuilder.toString()
    val textView: TextView = findViewById(R.id.activity_title) as TextView
    textView.text = "Paramlist is \n\n$paramListString"

    // to check if the url has specific keys
    if (sanitizer.hasParameter("type")) {
        val type = sanitizer.getValue("type")
        println("sanitizer has type param $type")
    }
jungledev
la source
-2

cette méthode prend l'URI et renvoie la carte du nom et de la valeur nominale

  public static Map<String, String> getQueryMap(String uri) {

    String queryParms[] = uri.split("\\?");

    Map<String, String> map = new HashMap<>();// 

    if (queryParms == null || queryParms.length == 0) return map;

    String[] params = queryParms[1].split("&");
    for (String param : params) {
        String name = param.split("=")[0];
        String value = param.split("=")[1];
        map.put(name, value);
    }
    return map;
}
FAHAD HAMMAD ALOTAIBI
la source
1
Selon ma diatribe ci-dessus, cela peut être trivialement fait planter. Ne vous embêtez pas à réparer, utilisez simplement une bibliothèque d'utilitaires professionnelle.
Will
-3

Vous dites "Java" mais "pas Java EE". Voulez-vous dire que vous utilisez JSP et / ou des servlets mais pas une pile Java EE complète? Si tel est le cas, vous devriez toujours avoir request.getParameter () à votre disposition.

Si vous voulez dire que vous écrivez Java mais que vous n'écrivez pas de JSP ni de servlets, ou que vous utilisez simplement Java comme point de référence mais que vous êtes sur une autre plate-forme qui n'a pas d'analyse de paramètres intégrée ... Wow , cela ressemble à une question improbable, mais si c'est le cas, le principe serait:

xparm=0
word=""
loop
  get next char
  if no char
    exit loop
  if char=='='
    param_name[xparm]=word
    word=""
  else if char=='&'
    param_value[xparm]=word
    word=""
    xparm=xparm+1
  else if char=='%'
    read next two chars
    word=word+interpret the chars as hex digits to make a byte
  else
    word=word+char

(Je pourrais écrire du code Java mais ce serait inutile, car si vous avez Java disponible, vous pouvez simplement utiliser request.getParameters.)

Geai
la source
attention au codage des caractères lors du décodage url des chiffres hexadécimaux.
M. Shiny et New 安 宇
C'est Android, donc Java mais pas J2EE.
Andrzej Doyle
J'ai oublié de mentionner: Vous devez également vérifier "+", qui doit être traduit dans un espace. Les espaces intégrés sont illégaux dans une chaîne de requête.
Jay