Analizowanie ciągów zapytań na Androidzie


271

Java EE ma ServletRequest.getParameterValues ​​() .

Na platformach innych niż EE funkcja URL.getQuery () po prostu zwraca ciąg znaków.

Jaki jest normalny sposób, aby poprawnie parsować ciąg zapytania w adresie URL, gdy nie ma Java EE?


< rant >

Popularnym w odpowiedziach jest próba stworzenia własnego parsera. To bardzo interesujący i ekscytujący projekt mikrokodowania, ale nie mogę powiedzieć, że to dobry pomysł :(

Fragmenty kodu poniżej są ogólnie wadliwe lub uszkodzone, przy okazji. Złamanie ich jest ciekawym ćwiczeniem dla czytelnika. I hakerom atakującym witryny, które ich używają .

Analiza ciągów zapytań jest dobrze zdefiniowanym problemem, ale czytanie specyfikacji i rozumienie niuansów nie jest trywialne. O wiele lepiej jest pozwolić, aby jakiś programista biblioteki platform wykonał ciężką pracę i dokonał naprawy!

< / rant >


Czy możesz opublikować przykładowy adres URL, co otrzymujesz getQuery()i co chcesz uzyskać jako wynik?
Thomas Owens,

1
Czy chcesz to zrobić ze strony serwletu lub strony JSP? Potrzebuję wyjaśnienia, zanim odpowiem.
ChadNC,

1
Czy musisz także analizować parametry POST?
Thilo,

2
Nawet jeśli korzystasz z J2EE (lub SE z wybranymi pakietami EE dodanymi przez OSGi, tak jak ja), to pytanie może mieć sens. W moim przypadku ciągi zapytań / ciała POST zakodowane w adresie URL są przetwarzane przez część systemu, która celowo jest niezależna od takich rzeczy ServletRequest.
Hanno Fietz

61
Upvoted dla <rant />!
Nowaker

Odpowiedzi:


65

Od Androida M sprawy stały się bardziej skomplikowane. Odpowiedź android.net.URI .getQueryParameter () zawiera błąd, który łamie spacje przed JellyBean. Apache URLEncodedUtils.parse () działa, ale przestarzałe w L i usunięto M .

Więc najlepszą odpowiedzią jest teraz UrlQuerySanitizer . Istnieje od 1 poziomu API i nadal istnieje. Sprawia również, że myślisz o trudnych kwestiach, takich jak sposób postępowania ze znakami specjalnymi lub powtarzane wartości.

Najprostszy kod to

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

Jeśli jesteś zadowolony z domyślnego zachowania podczas analizowania, możesz:

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

ale powinieneś upewnić się, że rozumiesz, jakie jest domyślne zachowanie podczas analizowania, ponieważ może nie być tym, czego chcesz.


4
URLQuerySanitizer.getAllButNullLegal () zwraca UrlQuerySanitizer.ValueSanitizer, a nie UrlQuerySanitizer.
Peter Zhao

31
Z jakiegoś powodu powyższe nie działało dla mnie, musiałem go nieco zmodyfikować - co czyni to jeszcze łatwiejszym:UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(YourStringURL); String value = sanitizer.getValue("parameter");
SeBsZ 24.04.16

3
Nie działa. UrlQuerySanitizer w sdk-23 ma tylko jedną metodęsanitize()
Ninja

Spowoduje to odkodowanie znaków specjalnych i emoji do _. Musiałem iść z stackoverflow.com/a/35638979/1155282
Irshu

Czy istnieje biblioteka tego odpowiednika w ramach Spring Framework?
iamjoshua

202

Na Androidzie:

import android.net.Uri;

[...]

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

20
zauważ, że używa to klasy Uri, a nie klasy URI (Uri jest częścią android.net, podczas gdy URI jest częścią java.net)
Marius

5
Zauważ też, że przed Ice Cream Sandwich nie parsuje znaków + w wartościach do znaku spacji.
rpetrich

@ rpetrich faktycznie doktorzy mówią, że błąd był wcześniejszy niż Jelly Bean, w tym Ice Cream Sandwich. ref
Big McLargeHuge

64

9
Jest to dostępne w bibliotece klienta Apache http, nie tylko na Androidzie. Przy okazji łącze do apache zostało zmienione. Najnowszy to: hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Cristian Vrabie

9
Irytująco URLEncodedUtils.parse()zwraca wartość, Listktórą trzeba będzie zapętlić, aby znaleźć wartość dla określonego klucza. Byłoby o wiele przyjemniej, gdyby zwrócił Mappodobny w odpowiedzi BalusC.
Asaph

1
@Hanno Fietz masz na myśli, że ufasz tym alternatywom? Wiem, że są wadliwe. Wiem, że wskazanie błędów, które widzę, zachęci tylko ludzi do przyjęcia „naprawionych” wersji, zamiast sami szukać błędów, które przeoczyłem.
Czy

1
@Will - dobrze, nigdy nie tylko zaufanie kopiuj i wklej fragmenty dostałem z każdej strony, i nikt nie powinien. Ale tutaj te fragmenty są raczej dobrze recenzowane i komentowane, a zatem arenaprawdę bardzo pomocne. Po prostu widząc jakieś sugestie co może być nie tak z tym kodem jest już bardzo pomocne w myśleniu o sobie. I pamiętajcie, nie chciałem powiedzieć, że „roll your own is better”, ale raczej, że wspaniale jest mieć dobry materiał do świadomej decyzji w moim własnym kodzie.
Hanno Fietz

8
Wyobrażam sobie, że parse zwraca listę, dzięki czemu zachowuje porządkowanie pozycyjne i łatwiej pozwala na zduplikowane wpisy.
dhaag23

26

Oto odpowiedź BalusC , ale kompiluje i zwraca wyniki:

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;
}

1
Uwaga JVM: Zaimplementowałem równoważną formę tego w Scali przy użyciu kolekcji Java; tutaj jest github gist: gist.github.com/3504765
Jay Taylor

2
Sugeruję zmianę String pair[] = param.split("=");na String pair[] = param.split("=", 2);podział pary klucz = wartość tylko przy pierwszym wystąpieniu. Uważam, że dozwolone jest, aby niekodowane znaki równości w wartości.
Dennie

22

Jeśli masz biblioteki jetty (serwer lub klient) na ścieżce klasy, możesz użyć klas util jetty (patrz javadoc ), np .:

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");

13

Jeśli używasz Wiosna 3.1 lub nowszy (Yikes, miał nadzieję, że wsparcie wrócił dalej), można użyć UriComponentsi UriComponentsBuilder:

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

components.getQueryParams() zwraca a MultiValueMap<String, String>

Oto więcej dokumentacji .


Tego szukam. Moje pytanie brzmi: jak zdobyć numer URI? Utknąłem z utrzymaniem kodu, którego nie mogę wiele zmienić i nie korzystamy z HttpServlet. Zamiast tego wystarczy użyć adnotacji i Spring (@Get, @Produces (mediaType) i @Path ("/ dataAsJSON / datafield / {datafield})) Wystarczy wiedzieć, jak uzyskać ciąg zapytania, aby móc go przeanalizować w sposób pokazany w ten przykład
Nelda.techspiress

5

W przypadku serwletu lub strony JSP można uzyskać kwerendowe pary klucz / wartość za pomocą request.getParameter („nazwa parametru”)

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

Są inne sposoby na zrobienie tego, ale tak właśnie robię na wszystkich tworzonych przez mnie serwletach i stronach jsp.


3
HttpServletRequest jest częścią J2EE, której nie ma. Również użycie getParamter () nie jest tak naprawdę parsowaniem.
Mr. Shiny and New 安 宇

3
Poświęć trochę czasu na przeczytanie komentarza, w którym poprosiłem o wyjaśnienie jego pytania. Ta odpowiedź jest odpowiedzią na jego odpowiedź na komentarz, w którym stwierdził: „Próbuję to zrobić na Androidzie, ale wszystkie odpowiedzi na wszystkich platformach byłyby przydatnymi odpowiedziami, które mogłyby dać wskazówki (także innym osobom, które mogą się z tym spotkać) pytanie), więc nie powstrzymuj się! ” Odpowiedziałem na jego pytanie na podstawie tego komentarza. Jeśli nie masz nic przydatnego do dodania, nie dodawaj niczego
ChadNC

1
Nie denerwuj się zbytnio. „To nie odpowiada na pytanie” jest przydatne, aby dodać, IMO.
Mr. Shiny and New 安 宇

1
Nie ma znaczenia, czy jest to Android, czy nie. Pytanie brzmi: jak parsować Ciąg zawierający URL i pobrać z niego parametry URL. To, co tu przenosisz, jest częścią Servlet API, gdzie kontener Servlet analizuje dla ciebie parametry przychodzące z żądania HTTP. Nie ma to znaczenia, ponieważ pytanie dotyczy parsowania ciągu zawierającego adres URL, a nie żądania HTTP i nie wewnątrz kontenera serwletu.
mvmn

5

Na Androidzie próbowałem użyć odpowiedzi @diyism, ale napotkałem problem ze spacją podniesiony przez @rpetrich, na przykład: Wypełniam formularz gdzie username = "us+us"i password = "pw pw"powoduję, że ciąg adresu URL wygląda następująco:

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

Jednak kod @diyism zwraca "us+us"i "pw+pw"tzn. Nie wykrywa znaku spacji. Jeśli adres URL został przepisany przy %20użyciu znaku spacji, zostanie on zidentyfikowany:

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

Prowadzi to do następującej poprawki:

Uri uri = Uri.parse(url_string.replace("+", "%20"));
uri.getQueryParameter("para1");

replace(" ", "%20")to jest złe. Ale
załatwiłem sprawę

Prawidłową składnią powinien być „jakiś ciąg” .replaceAll („[+]”, „% 20”);
RRTW

4

Analiza łańcucha zapytania jest nieco bardziej skomplikowana niż się wydaje, w zależności od tego, jak wybaczający chcesz być.

Po pierwsze, ciąg zapytania to bajty ascii. Odczytujesz te bajty pojedynczo i konwertujesz je na znaki. Jeśli postać jest? lub & a następnie sygnalizuje początek nazwy parametru. Jeśli znak ma wartość =, oznacza to początek wartości parametru. Jeśli znak ma wartość%, oznacza to początek zakodowanego bajtu. Tutaj jest trudniej.

Kiedy czytasz w% char, musisz przeczytać następne dwa bajty i zinterpretować je jako cyfry szesnastkowe. Oznacza to, że następne dwa bajty to 0-9, af lub AF. Sklej te dwie cyfry szesnastkowe, aby uzyskać wartość bajtu. Pamiętaj jednak, że bajty nie są znakami . Musisz wiedzieć, jakie kodowanie zostało użyte do zakodowania znaków. Znak é nie koduje tego samego w UTF-8, jak w ISO-8859-1. Zasadniczo nie można wiedzieć, jakie kodowanie zastosowano dla danego zestawu znaków. Zawsze używam UTF-8, ponieważ moja witryna jest skonfigurowana tak, aby zawsze obsługiwać wszystko przy użyciu UTF-8, ale w praktyce nie możesz być tego pewien. Niektóre programy klienckie podadzą kodowanie znaków w żądaniu; możesz spróbować to przeczytać, jeśli masz pełne żądanie HTTP. Jeśli masz tylko adres URL w izolacji, powodzenia.

W każdym razie, zakładając, że używasz UTF-8 lub innego wielobajtowego kodowania znaków, teraz po odkodowaniu jednego zakodowanego bajtu musisz go odłożyć na bok, aż do przechwycenia następnego bajtu. Potrzebne są wszystkie zakodowane bajty, które są razem, ponieważ nie można poprawnie dekodować adresu URL jeden bajt na raz. Odłóż wszystkie bajty, które są razem, a następnie odkoduj je wszystkie naraz, aby zrekonstruować swoją postać.

Co więcej, staje się bardziej zabawny, jeśli chcesz być łagodny i brać pod uwagę aplikacje klienckie, które zmieniają adresy URL. Na przykład niektórzy klienci poczty internetowej kodują rzeczy podwójnie. Lub podwoj znaki? & = (Na przykład:) http://yoursite.com/blah??p1==v1&&p2==v2. Jeśli chcesz spróbować z wdziękiem sobie z tym poradzić, musisz dodać więcej logiki do twojego parsera.


To nie wyjaśnia, jak analizować lub odzyskiwać wartości parametrów
zapytania

Racja, ale trochę nieporęczna. Do tego mamy już URLDecoder.
BalusC,

2
@ChadNC: trzecie zdanie mówi, jak parsować: czytaj po jednym bajcie na raz i konwertuj na znaki. Czwarte zdanie ostrzega przed specjalnymi znakami. Itd. Może nie przeczytałeś odpowiedzi?
Mr. Shiny and New 安 宇

@BalusC: URLDecoder działa, ale ma kilka trybów awarii, jeśli próbujesz być bardziej łagodny w tym, jakiego rodzaju URL akceptujesz.
Mr. Shiny and New 安 宇

1
Zgadzam się z @ Mr.ShinyAndNew param zapytanie param nie jest łatwe. Wspieram FIQL i to staje się PRAWDZIWYM bólem w dupie. Np .: yoursite.com/blah??p1==v1&&p2==v2,p2==v3;p2==v4
rafa.ferreira

4

Na Androidzie jest to tak proste, jak poniższy kod:

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

Również jeśli nie chcesz rejestrować każdego oczekiwanego klucza zapytania, użyj:

sanitzer.setAllowUnregisteredParamaters(true)

Przed zadzwonieniem:

sanitzer.parseUrl(yourUrl)

4

Mam metody, aby to osiągnąć:

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) i najłatwiejszy sposób na wykonanie tego za pomocą klasy 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 "";
}

i to jest przykład użycia jednej z dwóch metod:

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

wartość tagValue wynosi 800


3

Na Androidzie możesz użyć metody statycznej Uri.parse klasy android.net.Uri, aby wykonać ciężkie podnoszenie. Jeśli robisz cokolwiek z identyfikatorami URI i zamiarami, i tak będziesz chciał ich użyć.


3

Dla porównania, właśnie z tym skończyłem (na podstawie URLEncodedUtils i zwracania mapy).

Cechy:

  • akceptuje część ciągu adresu URL adresu URL zapytania (można użyć request.getQueryString())
  • pusty ciąg zapytania utworzy pusty Map
  • parametr bez wartości (test?) zostanie zamapowany na pusty List<String>

Kod:

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;
}

Pomocnik zgodności (wartości są przechowywane w tablicy String, podobnie jak w 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;
}

3

To działa dla mnie .. Nie jestem pewien, dlaczego każdy szukał mapy, listy> Potrzebowałem tylko prostej nazwy mapy.

Dla uproszczenia użyłem kompilacji w 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;
}

1
co z formularzami z wielokrotnym wyborem? Powtarzanie kluczy w prawidłowych ciągach zapytań (i ciałach formularza POST) jest całkowicie normalne. Istnieją inne wady i przypadki narożne nieobjęte; wiele z nich zostało wspomnianych w komentarzach do innych podejść. Powstrzymam formularz od wskazywania ich w obawie, że to naprawisz zamiast korzystać z wysokiej jakości biblioteki, zgodnie z moim twierdzeniem w pytaniu;)
Czy

2

Do tego lepiej nadaje się Multimapa Guavy. Oto krótka czysta wersja:

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);
        }
    }


1

Oryginalnie odpowiedział tutaj

Na Androida jest klasa Uri w pakiecie android.net . Pamiętaj, że Uri jest częścią android.net, podczas gdy URI jest częścią java.net.

Klasa Uri ma wiele funkcji do wyodrębniania par klucz-wartość zapytania. wprowadź opis zdjęcia tutaj

Następująca funkcja zwraca pary klucz-wartość w postaci HashMap.

W Javie:

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;
}

W Kotlinie:

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
    }

0

Nie wydaje mi się, żeby taki był w JRE. Podobne funkcje można znaleźć w innych pakietach, takich jak Apache HttpClient. Jeśli nie używasz żadnych innych pakietów, musisz po prostu napisać własny. To nie jest takie trudne. Oto czego używam

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;
 } 
}

Jaka jest droga z klasami Apache?
Czy


3
Umieść link do apache commons we własnej odpowiedzi, abym mógł głosować.
itsadok

0

Na podstawie odpowiedzi z BalusC napisałem przykładowy kod 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
            }
        }
    }

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;
}


0

za pomocą Guawy:

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;
}

0

Odpowiadając tutaj, ponieważ jest to popularny wątek. To czyste rozwiązanie w Kotlinie, które korzysta z zalecanego UrlQuerySanitizerinterfejsu API. Zobacz oficjalną dokumentację . Dodałem konstruktor ciągów, aby połączyć i wyświetlić parametry.

    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")
    }

-2

ta metoda pobiera nazwę URI i zwraca mapę wartości nominalnej i wartości nominalnej

  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;
}

1
Zgodnie z powyższym stwierdzeniem można to w prosty sposób rozbić. Nie przejmuj się naprawą, po prostu skorzystaj z profesjonalnej biblioteki narzędzi.
Czy

-3

Mówisz „Java”, ale „nie Java EE”. Czy masz na myśli, że używasz JSP i / lub serwletów, ale nie masz pełnego stosu Java EE? W takim przypadku powinieneś mieć do dyspozycji request.getParameter ().

Jeśli masz na myśli, że piszesz Javę, ale nie piszesz stron JSP ani serwletów, lub po prostu używasz Javy jako punktu odniesienia, ale korzystasz z innej platformy, która nie ma wbudowanej analizy parametrów ... Wow , to brzmi jak mało prawdopodobne pytanie, ale jeśli tak, zasadą byłoby:

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

(Mógłbym napisać kod Java, ale byłoby to bezcelowe, ponieważ jeśli masz dostępną Javę, możesz po prostu użyć request.getParameters.)


uważaj na kodowanie znaków podczas dekodowania url cyfr szesnastkowych.
Mr. Shiny and New 安 宇

To Android, stąd Java, ale nie J2EE.
Andrzej Doyle

Zapomniałem wspomnieć: musisz także sprawdzić „+”, który powinien zostać przetłumaczony na spację. Spacje osadzone są niedozwolone w ciągu zapytania.
Jay
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.