首页 > 解决方案 > 拆分url字符串时如何使用LinkedHashMap创建键值对?

问题描述

下面我有一个网址:

https://test.com/login/?response_type=code&redirect_uri=https%3A%2F%2Ftest.com&client=testclient&successUrl=https%3A%2F%2Flocalhost%3A4444%2Ftestsite%2Foauth%2Ftestendpoint%3Fresponse_type%3Dcode%26redirect_uri%3Dhttps%253A%252F%252Ftest.com%26client%3Dtestclient

我对其进行解码,使其看起来像一个更整洁的 url 字符串:

 public void testMethod() {

        final String url = URLDecoder.decode(getLastResponse().getHeaders().getFirst("location"), "UTF-8");

}

现在我想做的是按域和查询参数分解这个 url 并分配它们。这样我就可以对它们执行断言。我要做到这一点的方法是通过值键对,但我正在努力掌握它的概念。

这是我在下面的尝试,但一团糟。有人知道我如何使用 LinkedHashMap 来帮助执行键值对吗?此外,正如您在 url 中看到的,一些参数出现两次,因此需要帮助检查多个参数

final Map<String, List<String>> query_pairs = new LinkedHashMap<>();
    final String[] pairs = url.split("&|\\?");
    for (String pair : pairs) {
        final int idx = pair.indexOf("=");
        final String key = idx > 0 ? url : pair;
        if (!query_pairs.containsKey(key)) {
            query_pairs.put(key, new LinkedList<>());
        }
        final String value = idx > 0 && pair.length() > idx + 1 ? url : null;
        query_pairs.get(key).add(value);
    }

标签: java

解决方案


从 URL 开始,并解码注释中提到的其他参考中提到的参数值会更容易。下面是一个使用 Java 流来破坏 url 的示例:

public static Map<String, List<String>> split(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)
            //.peek(a -> System.out.println(Arrays.toString(a)))
            .collect(Collectors.groupingBy(key -> URLDecoder.decode(key[0], StandardCharsets.UTF_8),
                        LinkedHashMap::new,
                        Collectors.mapping(value -> value.length < 2 ? "" : URLDecoder.decode(value[1], StandardCharsets.UTF_8), Collectors.toList())))
           ;
}

您可能需要调整过滤器以忽略空属性字段(使用 查询&&)或将零长度参数值设为 null 或“”。示例调用:

String s = "http://stackoverflow.com/page?&source=somewhere&date=2020-10-01&flag3&name1=val%20ue1&date=2020-12-31&&=&flag&name1=secondvalue&arg=v";
URL url = new URL(s);
Map<String, List<String>> map = split(url);
System.out.println("  => "+map);
List<String> list = map.get("name1");
System.out.println("KEYS of name1 ="+list);

印刷:

{date=[2020-10-01, 2020-12-31], =[, ], flag=[], arg=[v], flag3=[], source=[somewhere], name1=[val ue1, secondvalue]}
KEYS of name1 =[val ue1, secondvalue]

推荐阅读