在Java中构建URL

54

我正在尝试构建http://IP:4567/foldername/1234?abc=xyz。我对此知之甚少,但是我通过谷歌搜索编写了如下代码:

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;

public class MyUrlConstruct {

    public static void main(String a[]){

        try {
            String protocol = "http";
            String host = "IP";
            int port = 4567;
            String path = "foldername/1234";
            URL url = new URL (protocol, host, port, path);
            System.out.println(url.toString()+"?");
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
    }
}

我能够构建URL http://IP:port/foldername/1234?,但目前卡在查询部分,请帮助我继续前进。


2
可能是重复的问题:如何在Java中连接两个字符串? - px06
@px06 需要对URL进行转义和验证,简单的拼接是不够的,因为如果abc=xyz包含其他的=、?或&等字符,它将会被破坏。建议使用专门的库来处理这个问题,当然在极其简单的情况下,拼接也可以使用。 - Christophe Roussy
1
可能是如何在Java中构建URL?的重复问题。 - Ivar
从Java 7开始,有一个内置的(EE)javax.ws.rs.core.UriBuilder,可以为您完成此操作。 - Keeley Hoek
6个回答

76

你可以直接传递原始的规范

new URL("http://IP:4567/foldername/1234?abc=xyz");

或者您可以使用类似于org.apache.http.client.utils.URIBuilder这样的工具来进行安全构建,并且正确地进行URL编码。

URIBuilder builder = new URIBuilder();
builder.setScheme("http");
builder.setHost("IP");
builder.setPath("/foldername/1234");
builder.addParameter("abc", "xyz");
URL url = builder.build().toURL();

1
已经由于Apache HTTP客户端库的依赖而安装了这个库,非常有帮助且简单易用。 - Christophe Roussy
1
请注意,此构建器也可用于部分 URL 构建,例如仅用于参数:... builder.addParameter(...); ... builder.toString() 即使其他部分缺失,也将返回此部分。 - Christophe Roussy

36

使用OkHttp

有一个非常受欢迎的库叫做OkHttp,在GitHub上获得了20K次星标。使用这个库,你可以像下面这样构建URL:

import okhttp3.HttpUrl;

URL url = new HttpUrl.Builder()
    .scheme("http")
    .host("example.com")
    .port(4567)
    .addPathSegments("foldername/1234")
    .addQueryParameter("abc", "xyz")
    .build().url();

或者你可以简单地解析一个URL:

URL url = HttpUrl.parse("http://example.com:4567/foldername/1234?abc=xyz").url();

16
如果你只需要构建URL字符串,我建议避免使用完整的HTTP客户端。对于轻量级任务来说,这是一个重量级的依赖。 - NeuroXc
1
@NeuroXc,是的,你说的很有道理。我来自Node.js世界,在那里它是依赖地狱,所以我习惯于管理依赖关系。另一方面,这并不是那么糟糕,因为一个重量级的依赖关系不会使你的应用程序变慢。但它会让你的应用程序变得更大。所以这取决于情况。这可能是一个问题,但在某些情况下人们并不在意。 - Tyler Liu
我在从旧的Http客户端迁移到okhttp时使用了你的解决方案,在代码库中的一个地方必须手动构建Url。谢谢!此外,我们可以使用HttpUrl url而不是URL url - Skynet

31

一般来说,URL是URI的一种特殊类型。您可以使用URI类(比经典的URL类更新,自Java 1.0以来一直存在),可更可靠地创建URI,并使用URI的toURL方法将其转换为URL:

String protocol = "http";
String host = "example.com";
int port = 4567;
String path = "/foldername/1234";
String auth = null;
String fragment = null;
URI uri = new URI(protocol, auth, host, port, path, query, fragment);
URL url = uri.toURL();

请注意,path 需要以斜杠开头。


1
如果我需要在这段代码中使用片段和 "&",我该如何使用?例如:"http://IP:4567/foldername/1234?abc=xyz&def=stu" - rrr ppp
4
这不是一个片段,只是多个查询参数。不幸的是,目前URI没有简单的方法来组装它们;你需要自己构建查询字符串。请注意,查询参数值通常需要进行编码。 - VGR
1
正如其他人所述,对于简单的情况来说这是可以的,但如果你还需要转义参数,这将会有问题(&、?、=等)。 - Christophe Roussy
@ChristopheRoussy 这是一个未解决的错误,但出于某种原因,Oracle似乎不认为有必要解决它。 - VGR
@VGR 可能是为了向后兼容性? - Christophe Roussy
@ChristopheRoussy,向后兼容性至关重要,但添加新的构造函数和方法不会破坏现有代码。从Java EE中添加一个无模板版本的UriBuilder类会更好。 - VGR

13
如果您已经使用Spring,我发现org.springframework.web.util.UriComponentsBuilder非常方便。以下是在您的情况下如何使用它。
final URL myUrl = UriComponentsBuilder
        .fromHttpUrl("http://IP:4567/foldername/1234?abc=xyz")
        .build()
        .toUri()
        .toURL();

13
使用Spring框架:
UriComponentsBuilder.newInstance()
  .scheme(scheme)
  .host(host)
  .path(path)
  .build()
  .toUri()
  .toURL();

一个新的UriComponentsBuilder类通过提供对URI准备的所有方面的细粒度控制,包括构建、从模板变量扩展和编码,来帮助创建UriComponents实例。
► 阅读更多...
► JavaDoc

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接