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


当前回答

Eclipse Jersey REST框架通过UriComponent支持这一点。例子:

import org.glassfish.jersey.uri.UriComponent;

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";
MultivaluedMap<String, String> params = UriComponent.decodeQuery(URI.create(uri), true);
for (String key : params.keySet()) {
  System.out.println(key + ": " + params.getFirst(key));
}

其他回答

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

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

纯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);
}

有一个新版本的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)));
}

当查询只有单个参数定义时,有很多答案可以用于您的查询。在一些应用程序中,处理一些额外的查询参数边缘情况可能是有用的,例如:

如param1&param1=value&param1=等参数值的列表,意味着param1被设置为list。Of ("", "value", "") 无效的排列,例如querypath?&=&&=noparamname&。 在maps中使用非空字符串a=意味着“a”是List.of(“”)来匹配web servlet处理

它使用一个带有过滤器和groupingBy的流来收集到Map<String, List<String>>:

public static Map<String, List<String>> getParameterValues(URL url) {
    return Arrays.stream(url.getQuery().split("&"))
            .map(s -> s.split("="))
            // filter out empty parameter names (as in Tomcat) "?&=&&=value&":
            .filter(arr -> arr.length > 0 && arr[0].length() > 0)
            .collect(Collectors.groupingBy(arr -> URLDecoder.decode(arr[0], StandardCharsets.UTF_8),
                     // drop this line for not-name definition order Map:
                     LinkedHashMap::new, 
                     Collectors.mapping(arr -> arr.length < 2 ? "" : URLDecoder.decode(arr[1], StandardCharsets.UTF_8), Collectors.toList())));
}

Eclipse Jersey REST框架通过UriComponent支持这一点。例子:

import org.glassfish.jersey.uri.UriComponent;

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";
MultivaluedMap<String, String> params = UriComponent.decodeQuery(URI.create(uri), true);
for (String key : params.keySet()) {
  System.out.println(key + ": " + params.getFirst(key));
}