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


当前回答

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

其他回答

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

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

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}

有一个新版本的Apache HTTP客户端- org.apache.httpcomponents。client5 -其中URLEncodedUtils现在已弃用。应该改为使用URIBuilder:

import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.net.URIBuilder;

private static Map<String, String> getQueryParameters(final String url) throws URISyntaxException {
    return new URIBuilder(new URI(url), StandardCharsets.UTF_8).getQueryParams()
                                                               .stream()
                                                               .collect(Collectors.toMap(NameValuePair::getName,
                                                                                         nameValuePair -> URLDecoder.decode(nameValuePair.getValue(), StandardCharsets.UTF_8)));
}

纯Java 11

给定要分析的URL:

URL url = new URL("https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback");

这个解决方案收集了一个对列表:

List<Map.Entry<String, String>> list = Pattern.compile("&")
   .splitAsStream(url.getQuery())
   .map(s -> Arrays.copyOf(s.split("=", 2), 2))
   .map(o -> Map.entry(decode(o[0]), decode(o[1])))
   .collect(Collectors.toList());

另一方面,这个解决方案收集一个映射(假设在url中可以有更多具有相同名称但不同值的参数)。

Map<String, List<String>> list = Pattern.compile("&")
   .splitAsStream(url.getQuery())
   .map(s -> Arrays.copyOf(s.split("=", 2), 2))
   .collect(groupingBy(s -> decode(s[0]), mapping(s -> decode(s[1]), toList())));

这两种解决方案都必须使用实用函数来正确解码参数。

private static String decode(final String encoded) {
    return Optional.ofNullable(encoded)
                   .map(e -> URLDecoder.decode(e, StandardCharsets.UTF_8))
                   .orElse(null);
}

在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
    }