278 votes

Analyse des chaînes de requête sur Android

Java EE a ServletRequest.getParameterValues().

Sur les plateformes non-EE, [URL.getQuery()](http://download.oracle.com/javase/1.4.2/docs/api/java/net/URL.html#getQuery()) renvoie simplement une chaîne de caractères.

Quelle est la façon normale de parser correctement la chaîne de requête dans une URL lorsque vous n'êtes pas sur Java EE?


Il est populaire dans les réponses d'essayer de créer votre propre analyseur. Il s'agit d'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. Les casser est un exercice intéressant pour le lecteur. Et pour les hackers qui attaquent les sites web qui les utilisent.

L'analyse des chaînes de requête est un problème bien défini mais lire la spécification et comprendre les nuances n'est pas trivial. Il est bien mieux de laisser un développeur de bibliothèques de plateforme faire le travail difficile, et les corrections, pour vous!

0 votes

Pouvez-vous poster un exemple d'URL, ce que vous obtenez de getQuery(), et ce que vous voulez obtenir en sortie ?

1 votes

Voulez-vous faire cela à partir d'un servlet ou d'une page JSP? J'ai besoin de quelques éclaircissements avant de répondre.

0 votes

Je suis en train d'essayer de le faire sur Android, mais toutes les réponses sur toutes les plates-formes seraient des réponses utiles qui pourraient donner des indices (également à d'autres personnes qui pourraient rencontrer cette question), alors ne vous retenez pas !

213voto

diyism Points 1191

Sous Android:

import android.net.Uri;

[...]

Uri uri=Uri.parse(url_string);
uri.getQueryParameter("para1");

20 votes

Notez que cela utilise la classe Uri et non la classe URI (Uri fait partie de android.net, tandis que URI fait partie de java.net)

5 votes

Aussi noter que avant Ice Cream Sandwich, cela échoue à analyser les caractères + dans les valeurs vers un caractère espace.

0 votes

@rpetrich en réalité, les documents indiquent que le bogue date d'avant la gelée, y compris la crème glacée sandwich. ref

64voto

Will Points 30630

0 votes

Salut Will, je pense que la classe Apache est encore en version alpha (4.1)

0 votes

@Daziplqa Je ne suis pas sûr de comprendre? Cela a été sur la plate-forme Android depuis le début et ça fonctionne pour moi :)

9 votes

Cela est disponible dans la bibliothèque cliente apache http, pas seulement sur Android. Au fait, le lien vers apache a été changé. Le dernier est : hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/or‌​g/…

26voto

dfrankow Points 2983
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("=", 2);
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;
}

1 votes

Note JVM : J'ai implémenté une forme équivalente en Scala en utilisant les Collections Java; voici le gist github : gist.github.com/3504765

2 votes

Je suggère de changer String pair[] = param.split("="); en String pair[] = param.split("=", 2); pour diviser la paire clé=valeur seulement à la première occurrence. Je crois qu'il est autorisé d'avoir des signes égaux non encodés dans la valeur.

0 votes

Merci @Dennie, ajouté.

22voto

moritz Points 2477

Si vous avez les bibliothèques jetty (serveur ou client) dans votre classpath, vous pouvez utiliser les classes utilitaires de jetty (voir javadoc), par exemple :

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

assert params.getString("foo").equals("bar");
assert params.getString("bla").equals("blub");

13voto

Nick Spacek Points 1098

Si vous utilisez Spring 3.1 ou une version ultérieure (oups, j'espérais que la prise en charge remonte plus loin), vous pouvez utiliser UriComponents et UriComponentsBuilder:

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

components.getQueryParams() renvoie un MultiValueMap

Voici quelques documentations supplémentaires.

0 votes

C'est quelque chose que je recherche. Ma question est comment puis-je obtenir l'uri? Je suis bloqué avec la maintenance du code que je ne peux pas beaucoup changer et nous n'utilisons pas HttpServlet. À la place, nous utilisons uniquement des annotations et Spring (@Get, @Produces (mediaType) et @Path ("/dataAsJSON/datafield/{datafield}")). J'ai juste besoin de savoir comment obtenir la chaîne de requête afin de pouvoir l'analyser comme le montre cet exemple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X