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 >
getQuery()
i co chcesz uzyskać jako wynik?ServletRequest
.Odpowiedzi:
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
Jeśli jesteś zadowolony z domyślnego zachowania podczas analizowania, możesz:
ale powinieneś upewnić się, że rozumiesz, jakie jest domyślne zachowanie podczas analizowania, ponieważ może nie być tym, czego chcesz.
źródło
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(YourStringURL);
String value = sanitizer.getValue("parameter");
UrlQuerySanitizer
w sdk-23 ma tylko jedną metodęsanitize()
_
. Musiałem iść z stackoverflow.com/a/35638979/1155282Na Androidzie:
źródło
W systemie Android biblioteki Apache zapewniają analizator składni zapytań:
http://developer.android.com/reference/org/apache/http/client/utils/URLEncodedUtils.html i http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/ http / client / utils / URLEncodedUtils.html
źródło
URLEncodedUtils.parse()
zwraca wartość,List
którą trzeba będzie zapętlić, aby znaleźć wartość dla określonego klucza. Byłoby o wiele przyjemniej, gdyby zwróciłMap
podobny w odpowiedzi BalusC.are
naprawdę 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.Oto odpowiedź BalusC , ale kompiluje i zwraca wyniki:
źródło
String pair[] = param.split("=");
naString 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.Jeśli masz biblioteki jetty (serwer lub klient) na ścieżce klasy, możesz użyć klas util jetty (patrz javadoc ), np .:
źródło
Jeśli używasz Wiosna 3.1 lub nowszy (Yikes, miał nadzieję, że wsparcie wrócił dalej), można użyć
UriComponents
iUriComponentsBuilder
:components.getQueryParams()
zwraca aMultiValueMap<String, String>
Oto więcej dokumentacji .
źródło
W przypadku serwletu lub strony JSP można uzyskać kwerendowe pary klucz / wartość za pomocą request.getParameter („nazwa parametru”)
Są inne sposoby na zrobienie tego, ale tak właśnie robię na wszystkich tworzonych przez mnie serwletach i stronach jsp.
źródło
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"
ipassword = "pw pw"
powoduję, że ciąg adresu URL wygląda następująco:Jednak kod @diyism zwraca
"us+us"
i"pw+pw"
tzn. Nie wykrywa znaku spacji. Jeśli adres URL został przepisany przy%20
użyciu znaku spacji, zostanie on zidentyfikowany:Prowadzi to do następującej poprawki:
źródło
replace(" ", "%20")
to jest złe. AleAnaliza ł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.źródło
Na Androidzie jest to tak proste, jak poniższy kod:
Również jeśli nie chcesz rejestrować każdego oczekiwanego klucza zapytania, użyj:
Przed zadzwonieniem:
źródło
Mam metody, aby to osiągnąć:
1) :
2) i najłatwiejszy sposób na wykonanie tego za pomocą klasy Uri :
i to jest przykład użycia jednej z dwóch metod:
wartość tagValue wynosi
800
źródło
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ć.
źródło
Dla porównania, właśnie z tym skończyłem (na podstawie URLEncodedUtils i zwracania mapy).
Cechy:
request.getQueryString()
)Map
List<String>
Kod:
Pomocnik zgodności (wartości są przechowywane w tablicy String, podobnie jak w ServletRequest.getParameterMap () ):
źródło
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 ();
źródło
Do tego lepiej nadaje się Multimapa Guavy. Oto krótka czysta wersja:
źródło
Apache AXIS2 ma autonomiczną implementację QueryStringParser.java. Jeśli nie używasz Axis2, po prostu pobierz kod źródłowy i przypadek testowy stąd -
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
źródło
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.
Następująca funkcja zwraca pary klucz-wartość w postaci HashMap.
W Javie:
W Kotlinie:
źródło
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
źródło
Na podstawie odpowiedzi z BalusC napisałem przykładowy kod Java:
źródło
źródło
Użyj Apache HttpComponents i połącz go z kodem kolekcji, aby uzyskać dostęp do parametrów według wartości: http://www.joelgerard.com/2012/09/14/parsing-query-strings-in-java-and-accessing-values-by -klucz/
źródło
za pomocą Guawy:
źródło
Odpowiadając tutaj, ponieważ jest to popularny wątek. To czyste rozwiązanie w Kotlinie, które korzysta z zalecanego
UrlQuerySanitizer
interfejsu API. Zobacz oficjalną dokumentację . Dodałem konstruktor ciągów, aby połączyć i wyświetlić parametry.źródło
ta metoda pobiera nazwę URI i zwraca mapę wartości nominalnej i wartości nominalnej
źródło
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:
(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.)
źródło