Java EE有ServletRequest.getParameterValues()。

在非ee平台上,URL.getQuery()只是返回一个字符串。

当不在Java EE上时,正确解析URL中的查询字符串的正常方法是什么?


在回答中,尝试创建自己的解析器是很受欢迎的。这是一个非常有趣和令人兴奋的微编码项目,但我不能说这是一个好主意。

下面的代码段通常是有缺陷或损坏的。对读者来说,打破它们是一项有趣的练习。还有攻击使用它们的网站的黑客。

解析查询字符串是一个明确定义的问题,但阅读规范并理解其中的细微差别并非易事。最好是让一些平台库编码器为您做艰苦的工作,并进行修复!


当前回答

自从Android M之后,事情变得更加复杂。android.net.URI.getQueryParameter()的答案有一个错误,在JellyBean之前打破空格。 Apache URLEncodedUtils.parse()可以工作,但在L中已弃用,在M中已被删除。

所以现在最好的答案是UrlQuerySanitizer。它从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");

如果你对默认的解析行为满意,你可以这样做:

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

但是您应该确保了解默认的解析行为是什么,因为它可能不是您想要的。

其他回答

在Android上,代码如下所示:

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

另外,如果你不想注册每个预期的查询键使用:

sanitzer.setAllowUnregisteredParamaters(true)

在调用之前:

sanitzer.parseUrl(yourUrl)

仅供参考,这是我最终得到的结果(基于URLEncodedUtils,并返回一个Map)。

特点:

它接受url的查询字符串部分(你可以使用request.getQueryString()) 空查询字符串将产生空Map 没有值的参数(?test)将被映射为空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;
}

兼容性帮助器(值存储在String数组中,就像在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;
}

在Android上,你可以使用Uri。uri类的解析静态方法来完成繁重的工作。如果你在做任何与uri和intent相关的事情,无论如何你都会想要使用它。

这对我有用。 我不知道为什么每个人都想要一个地图,列表> 我所需要的只是一个简单的名称值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是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
    }