Java EEには ServletRequest.getParameterValues() があります。
非EEプラットフォームでは、 RL.getQuery() は単に文字列を返します。
Java EEでnotのときにURLのクエリ文字列を適切に解析する通常の方法は何ですか?
<rant>
回答では、独自のパーサーを作成してみてください。これは非常に興味深くエキサイティングなマイクロコーディングプロジェクトですが、良いアイデアだとは言えません:(
以下のコードスニペットは一般に欠陥があるか壊れています。それらを破ることは、読者にとって興味深い演習です。 そしてそれらを使用するWebサイトを攻撃するハッカーにも。
クエリ文字列の解析は明確に定義された問題ですが、仕様を読んでニュアンスを理解することは簡単ではありません。一部のプラットフォームライブラリコーダーにハードワークを行わせ、修正を行う方がはるかに良いです!
</ rant>
Android M以来、物事はより複雑になりました。 Android.net.URI 。getQueryParameter()の答えには、JellyBeanの前のスペースを壊すバグがあります。 Apache URLEncodedUtils.parse() は機能していましたが、 Lで非推奨 、および Mで削除 でした。
したがって、現在の最良の答えは rlQuerySanitizer です。これはAPIレベル1から存在し、現在も存在しています。また、特殊文字や繰り返し値の処理方法など、トリッキーな問題について考えることもできます。
最も単純なコードは
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
Androidの場合:
import Android.net.Uri;
[...]
Uri uri=Uri.parse(url_string);
uri.getQueryParameter("para1");
BalusCの答え ですが、コンパイルして結果を返します:
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;
}
クラスパスにjetty(サーバーまたはクライアント)ライブラリがある場合、jetty utilクラスを使用できます( javadoc を参照)。例:
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");
Spring 3.1以降を使用している場合(同様に、サポートがさらに戻ることを期待していた場合)、UriComponents
およびUriComponentsBuilder
を使用できます。
UriComponents components = UriComponentsBuilder.fromUri(uri).build();
List<String> myParam = components.getQueryParams().get("myParam");
components.getQueryParams()
はMultiValueMap<String, String>
を返します
サーブレットまたはJSPページの場合、request.getParameter( "paramname")を使用してクエリ文字列のキー/値のペアを取得できます。
String name = request.getParameter("name");
他の方法もありますが、私が作成するすべてのサーブレットとjspページでそれを行う方法です。
これを達成する方法があります:
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)および ri class:を使用してこれを行う最も簡単な方法
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 "";
}
これは、2つの方法のいずれかを使用する方法の例です。
String url = "http://www.jorgesys.com/advertisements/publicidadmobile.htm?position=x46&site=reform&awidth=800&aheight=120";
String tagValue = getQueryString(url,"awidth");
tagValueの値は800
です
クエリ文字列の解析は、どの程度寛容になりたいかに応じて、見かけよりも少し複雑です。
まず、クエリ文字列はASCIIバイトです。これらのバイトを一度に1つずつ読み取り、文字に変換します。文字が?または&その後、パラメータ名の開始を通知します。文字が=の場合、パラメータ値の開始を通知します。文字が%の場合、エンコードされたバイトの開始を通知します。ここが難しいところです。
%charを読み取る場合、次の2バイトを読み取り、16進数として解釈する必要があります。つまり、次の2バイトは0〜9、a〜fまたはA〜Fになります。これらの2桁の16進数を接着して、バイト値を取得します。ただし、バイトは文字ではないであることを忘れないでください。文字のエンコードに使用されたエンコードを知っている必要があります。文字éは、ISO-8859-1の場合と同じUTF-8のエンコードを行いません。一般に、特定の文字セットにどのエンコーディングが使用されたかを知ることは不可能です。私のウェブサイトは常にUTF-8を使用してすべてを提供するように構成されているため、私は常にUTF-8を使用しますが、実際には確実ではありません。一部のユーザーエージェントは、リクエストで文字エンコーディングを通知します。完全なHTTPリクエストがある場合は、それを読むことができます。 URLを分離している場合は、幸運を祈ります。
とにかく、UTF-8または他のマルチバイト文字エンコーディングを使用していると仮定すると、エンコードされた1バイトをデコードしたので、次のバイトをキャプチャするまで脇に置いておく必要があります。一度に1バイトを適切にURLデコードできないため、すべてのエンコードされたバイトが必要です。一緒になっているすべてのバイトを脇に置き、一度にすべてをデコードしてキャラクターを再構築します。
さらに、あなたが寛大になり、URLを破壊するユーザーエージェントを説明したい場合は、もっと楽しくなります。たとえば、一部のWebメールクライアントは、物を二重にエンコードします。または、?&=文字を2倍にします(例:http://yoursite.com/blah??p1==v1&&p2==v2
)。これをうまく処理しようとする場合は、パーサーにロジックを追加する必要があります。
Androidで@diyismの回答を使用しようとしましたが、@ rpetrichで発生したスペース文字の問題に遭遇しました。たとえば、フォームに記入してusername = "us+us"
とpassword = "pw pw"
がURL文字列のように見えるようにします。
http://somewhere?username=us%2Bus&password=pw+pw
ただし、@ diyismコードは"us+us"
および"pw+pw"
を返します。つまり、スペース文字は検出されません。 URLが%20
で書き換えられた場合、スペース文字が識別されます:
http://somewhere?username=us%2Bus&password=pw%20pw
これにより、次の修正が行われます。
Uri uri = Uri.parse(url_string.replace("+", "%20"));
uri.getQueryParameter("para1");
Androidでは、次のコードのように簡単です。
UrlQuerySanitizer sanitzer = new UrlQuerySanitizer(url);
String value = sanitzer.getValue("your_get_parameter");
また、予想される各クエリキーの使用を登録したくない場合:
sanitzer.setAllowUnregisteredParamaters(true)
呼び出す前に:
sanitzer.parseUrl(yourUrl)
これは私のために動作します。すべてがMap、List>の後にある理由がわかりません。必要なのは単純な名前値Mapだけでした。
物事を単純にするために、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;
}
Androidでは、 Android.net.Uri クラスのUri.parse静的メソッドを使用して、面倒な作業を行うことができます。 URIとインテントを使って何かをしているなら、とにかくそれを使いたいでしょう。
参考までに、これは私が最終的に得たものです(URLEncodedUtilsに基づき、Mapを返します)。
特徴:
request.getQueryString()
を使用できます)Map
を生成しますList<String>
にマップされますコード:
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;
}
互換性ヘルパー(値は 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;
}
Guava Multimapはこれに適しています。ここに簡潔な短いバージョンがあります:
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);
}
}
Apache AXIS2には、QueryStringParser.Javaの自己完結型の実装があります。 Axis2を使用していない場合は、ここからソースコードとテストケースをダウンロードするだけです-
本来の回答 こちら
Androidでは、パッケージにUriクラスがありますAndroid.net。 UriはAndroid.netの一部であり、URIはJava.netの一部であることに注意してください。
Uriクラスには、クエリのキーと値のペアを抽出するための多くの関数があります。
次の関数は、キーと値のペアをHashMapの形式で返します。
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;
}
コトリンで:
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
}
BalusCからの回答に基づいて、いくつかのサンプル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
}
}
}
これは人気のあるスレッドであるため、ここで答えます。これは、推奨されるUrlQuerySanitizer
apiを使用するKotlinのクリーンなソリューションです。 公式ドキュメントを参照 。パラメーターを連結して表示するための文字列ビルダーを追加しました。
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")
}
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;
}
グアバを使用:
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;
}
Apache HttpComponentsを使用し、値でパラメーターにアクセスするためのコレクションコードと接続します。 http://www.joelgerard.com/2012/09/14/parsing-query-strings-in-Java-and-accessing -values-by-key /
JREにあるとは思わない。 Apache HttpClientのような他のパッケージで同様の機能を見つけることができます。他のパッケージを使用しない場合は、独自のパッケージを作成する必要があります。そんなに難しくありません。これが私が使っているものです、
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;
}
}