我得到了这样的URI:

https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback

我需要一个包含已解析元素的集合:

NAME               VALUE
------------------------
client_id          SS
response_type      code
scope              N_FULL
access_type        offline
redirect_uri       http://localhost/Callback

确切地说,我需要一个与c# /等价的Java。净HttpUtility。ParseQueryString方法。


当前回答

对于Android,如果你在项目中使用OkHttp。你可以看看这个。它简单又有用。

final HttpUrl url = HttpUrl.parse(query);
if (url != null) {
    final String target = url.queryParameter("target");
    final String id = url.queryParameter("id");
}

其他回答

用谷歌番石榴,分成两行:

import java.util.Map;
import com.google.common.base.Splitter;

public class Parser {
    public static void main(String... args) {
        String uri = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
        String query = uri.split("\\?")[1];
        final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator('=').split(query);
        System.out.println(map);
    }
}

这让你

{client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback}

Kotlin的答案,最初参考https://stackoverflow.com/a/51024552/3286489,但通过整理代码和提供2个版本的改进版本,并使用不可变的集合操作

使用java.net.URI提取查询。然后使用下面提供的扩展函数

假设你只想要查询的最后一个值,即page2&page3将得到{page=3},使用下面的扩展函数

    fun URI.getQueryMap(): Map<String, String> {
        if (query == null) return emptyMap()

        return query.split("&")
                .mapNotNull { element -> element.split("=")
                        .takeIf { it.size == 2 && it.none { it.isBlank() } } }
                .associateBy({ it[0].decodeUTF8() }, { it[1].decodeUTF8() })
    }

    private fun String.decodeUTF8() = URLDecoder.decode(this, "UTF-8") // decode page=%22ABC%22 to page="ABC"

假设你想要查询所有值的列表,即page2&page3将得到{page=[2,3]}

    fun URI.getQueryMapList(): Map<String, List<String>> {
        if (query == null) return emptyMap()

        return query.split("&")
                .distinct()
                .mapNotNull { element -> element.split("=")
                        .takeIf { it.size == 2 && it.none { it.isBlank() } } }
                .groupBy({ it[0].decodeUTF8() }, { it[1].decodeUTF8() })
    }

    private fun String.decodeUTF8() = URLDecoder.decode(this, "UTF-8") // decode page=%22ABC%22 to page="ABC"

使用方法如下

    val uri = URI("schema://host/path/?page=&page=2&page=2&page=3")
    println(uri.getQueryMapList()) // Result is {page=[2, 3]}
    println(uri.getQueryMap()) // Result is {page=3}

只是Java 8版本的更新

public Map<String, List<String>> splitQuery(URL url) {
    if (Strings.isNullOrEmpty(url.getQuery())) {
        return Collections.emptyMap();
    }
    return Arrays.stream(url.getQuery().split("&"))
            .map(this::splitQueryParameter)
            .collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, **Collectors**.mapping(Map.Entry::getValue, **Collectors**.toList())));
}

mapping和toList()方法必须用于顶部答案中没有提到的collector。否则它会在IDE中抛出编译错误

如果你碰巧在类路径上有cxf-core,并且你知道你没有重复的查询参数,你可能想要使用UrlUtils.parseQueryString。

如果你正在使用servlet doGet,试试这个

request.getParameterMap()

返回此请求参数的java.util.Map。 返回: 一个不可变的java.util.Map,包含参数名作为键,参数值作为映射值。参数映射中的键类型为String。参数映射中的值类型为字符串数组。 (Java文档)