我得到了这样的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方法。
如果您正在使用Java 8,并且愿意编写一些可重用的方法,那么可以在一行中完成。
private Map<String, List<String>> parse(final String query) {
return Arrays.asList(query.split("&")).stream().map(p -> p.split("=")).collect(Collectors.toMap(s -> decode(index(s, 0)), s -> Arrays.asList(decode(index(s, 1))), this::mergeLists));
}
private <T> List<T> mergeLists(final List<T> l1, final List<T> l2) {
List<T> list = new ArrayList<>();
list.addAll(l1);
list.addAll(l2);
return list;
}
private static <T> T index(final T[] array, final int index) {
return index >= array.length ? null : array[index];
}
private static String decode(final String encoded) {
try {
return encoded == null ? null : URLDecoder.decode(encoded, "UTF-8");
} catch(final UnsupportedEncodingException e) {
throw new RuntimeException("Impossible: UTF-8 is a required encoding", e);
}
}
但这是一条很残酷的线。
一个kotlin版本
由马提亚提供的答案
fun decomposeQueryString(query: String, charset: Charset): Map<String, String?> {
return if (query.split("?").size <= 1)
emptyMap()
else {
query.split("?")[1]
.split("&")
.map { it.split(Pattern.compile("="), 2) }
.associate {
Pair(
URLDecoder.decode(it[0], charset.name()),
if (it.size > 1) URLDecoder.decode(it[1], charset.name()) else null
)
}
}
}
这需要问号'?’。
只是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中抛出编译错误
Netty还提供了一个很好的查询字符串解析器,称为QueryStringDecoder。
在一行代码中,它可以解析问题中的URL。
我喜欢它是因为它不需要捕获或抛出java.net.MalformedURLException。
一句话:
Map<String, List<String>> parameters = new QueryStringDecoder(url).parameters();
查看javadocs: https://netty.io/4.1/api/io/netty/handler/codec/http/QueryStringDecoder.html
下面是一个简短的、完整的、正确的例子:
import io.netty.handler.codec.http.QueryStringDecoder;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
public class UrlParse {
public static void main(String... args) {
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";
QueryStringDecoder decoder = new QueryStringDecoder(url);
Map<String, List<String>> parameters = decoder.parameters();
print(parameters);
}
private static void print(final Map<String, List<String>> parameters) {
System.out.println("NAME VALUE");
System.out.println("------------------------");
parameters.forEach((key, values) ->
values.forEach(val ->
System.out.println(StringUtils.rightPad(key, 19) + val)));
}
}
而产生
NAME VALUE
------------------------
client_id SS
response_type code
scope N_FULL
access_type offline
redirect_uri http://localhost/Callback