我得到了这样的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方法。


当前回答

在我看来,这是最好的方法:

static Map<String, String> decomposeQueryString(String query, Charset charset) {
    return Arrays.stream(query.split("&"))
        .map(pair -> pair.split("=", 2))
        .collect(Collectors.toMap(
            pair -> URLDecoder.decode(pair[0], charset),
            pair -> pair.length > 1 ? URLDecoder.decode(pair[1], charset) : null)
        );
}

前提条件是查询语法不允许重复参数。

其他回答

如果你正在使用Spring,添加一个类型为@RequestParam Map<String,String>的参数到你的控制器方法,Spring将为你构造映射!

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

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

Hutool框架通过HttpUtil来支持这一点。例子:

import cn.hutool.http.HttpUtil;

    String url ="https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
    Map<String, List<String>> stringListMap = HttpUtil.decodeParams(url, "UTF-8");
    System.out.println("decodeParams:" + stringListMap);

你会得到:

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

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

我有一个Kotlin版本,看看这是如何在谷歌的顶部结果。

@Throws(UnsupportedEncodingException::class)
fun splitQuery(url: URL): Map<String, List<String>> {

    val queryPairs = LinkedHashMap<String, ArrayList<String>>()

    url.query.split("&".toRegex())
            .dropLastWhile { it.isEmpty() }
            .map { it.split('=') }
            .map { it.getOrEmpty(0).decodeToUTF8() to it.getOrEmpty(1).decodeToUTF8() }
            .forEach { (key, value) ->

                if (!queryPairs.containsKey(key)) {
                    queryPairs[key] = arrayListOf(value)
                } else {

                    if(!queryPairs[key]!!.contains(value)) {
                        queryPairs[key]!!.add(value)
                    }
                }
            }

    return queryPairs
}

还有扩展方法

fun List<String>.getOrEmpty(index: Int) : String {
    return getOrElse(index) {""}
}

fun String.decodeToUTF8(): String { 
    URLDecoder.decode(this, "UTF-8")
}