URL生成器-UrlBuilder

由来

在JDK中,我们可以借助URL对象完成URL的格式化,但是无法完成一些特殊URL的解析和处理,例如编码过的URL、不标准的路径和参数。在旧版本的hutool中,URL的规范完全靠字符串的替换来完成,不但效率低,而且处理过程及其复杂。于是在5.3.1之后,加入了UrlBuilder类,拆分URL的各个部分,分别处理和格式化,完成URL的规范。
按照Uniform Resource Identifier的标准定义,URL的结构如下:

  • [scheme:]scheme-specific-part[#fragment]
  • [scheme:][//authority][path][?query][#fragment]
  • [scheme:][//host:port][path][?query][#fragment]

按照这个格式,UrlBuilder将URL分成scheme、host、port、path、query、fragment部分,其中path和query较为复杂,又使用UrlPathUrlQuery分别封装。

使用

相比URL对象,UrlBuilder更加人性化,例如:

  1. URL url = new URL("www.hutool.cn");

此时会报java.net.MalformedURLException: no protocol的错误,而使用UrlBuilder则会有默认协议:

  1. // 输出 http://www.hutool.cn/
  2. String buildUrl = UrlBuilder.create().setHost("www.hutool.cn").build();

完整构建

  1. // https://www.hutool.cn/aaa/bbb?ie=UTF-8&wd=test
  2. String buildUrl = UrlBuilder.create()
  3. .setScheme("https")
  4. .setHost("www.hutool.cn")
  5. .addPath("/aaa").addPath("bbb")
  6. .addQuery("ie", "UTF-8")
  7. .addQuery("wd", "test")
  8. .build();

中文编码

当参数中有中文时,自动编码中文,默认UTF-8编码,也可以调用setCharset方法自定义编码。

  1. // https://www.hutool.cn/s?ie=UTF-8&ie=GBK&wd=%E6%B5%8B%E8%AF%95
  2. String buildUrl = UrlBuilder.create()
  3. .setScheme("https")
  4. .setHost("www.hutool.cn")
  5. .addPath("/s")
  6. .addQuery("ie", "UTF-8")
  7. .addQuery("ie", "GBK")
  8. .addQuery("wd", "测试")
  9. .build();

解析

当有一个URL字符串时,可以使用of方法解析:

  1. UrlBuilder builder = UrlBuilder.ofHttp("www.hutool.cn/aaa/bbb/?a=张三&b=%e6%9d%8e%e5%9b%9b#frag1", CharsetUtil.CHARSET_UTF_8);
  2. // 输出张三
  3. Console.log(builder.getQuery().get("a"));
  4. // 输出李四
  5. Console.log(builder.getQuery().get("b"));

我们发现这个例子中,原URL中的参数a是没有编码的,b是编码过的,当用户提供此类混合URL时,Hutool可以很好的识别并全部decode,当然,调用build()之后,会全部再encode。

特殊URL解析

有时候URL中会存在&这种分隔符,谷歌浏览器会将此字符串转换为&使用,Hutool中也同样如此:

  1. String urlStr = "https://mp.weixin.qq.com/s?__biz=MzI5NjkyNTIxMg==&mid=100000465&idx=1";
  2. UrlBuilder builder = UrlBuilder.ofHttp(urlStr, CharsetUtil.CHARSET_UTF_8);
  3. // https://mp.weixin.qq.com/s?__biz=MzI5NjkyNTIxMg==&mid=100000465&idx=1
  4. Console.log(builder.build());

UrlBuilder主要应用于http模块,在构建HttpRequest时,用户传入的URL五花八门,为了做大最好的适应性,减少用户对URL的处理,使用UrlBuilder完成URL的规范化。