用Java组合URL或URI的惯用方式是什么?


115

如何在Java中构建URL或URI?有没有惯用的方法,还是图书馆很容易做到这一点?

我需要允许从请求字符串开始,解析/更改各种URL部分(方案,主机,路径,查询字符串),并支持添加和自动编码查询参数。


7
在关闭该问题很久之后就对这个问题进行投票,因为尚不清楚是否存在针对该问题的流行的,不建议使用的解决方案。我通过搜索“ java URL parameter class”发现了这一点。
user1445967 2013年

4
我的目的是找到Java的URL构建器,这个问题至少对我有用。
whirlwin 2015年

Answers:


76

从Apache HTTP组件HttpClient 4.1.3开始,来自官方教程

public class HttpClientTest {
public static void main(String[] args) throws URISyntaxException {
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    qparams.add(new BasicNameValuePair("q", "httpclient"));
    qparams.add(new BasicNameValuePair("btnG", "Google Search"));
    qparams.add(new BasicNameValuePair("aq", "f"));
    qparams.add(new BasicNameValuePair("oq", null));
    URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
                                 URLEncodedUtils.format(qparams, "UTF-8"), null);
    HttpGet httpget = new HttpGet(uri);
    System.out.println(httpget.getURI());
    //http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
}
}

编辑:从v4.2 URIUtils.createURI()开始,不推荐使用URIBuilder

URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());

20
这可行,但是从v4.2开始,不推荐使用URIUtils.createURI(),而推荐使用URIBuilder。从正面来看,这个URIBuilder似乎有一个addParameter()方法,因此构建请求字符串现在至少应该更简单。
stian 2012年

6
URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);正如@stian所说
vanduc1102'3

上面的Println打印以下内容;google.com/...
Berkan埃尔詹

61

作为作者,我可能不是判断我的URL / URI生成器是否良好的最佳人选,但在这里仍然是:https : //github.com/mikaelhg/urlbuilder

我想要JDK外部零依赖的最简单,完整的解决方案,所以我不得不自己动手。


6
Mikael看起来不错,您是否考虑过将其发布到Maven Central?我知道它很小,但是使使用起来更容易。除了在JAX-RS中,我找不到类似的类。缺少依赖绝对是一个加号。
巴里·皮特曼

看起来不错,但是由于它是构建器,因此是可变的,为什么为什么只对参数而不是对主机,端口,协议和路径进行设置?而且,嗯,这些也没有吸气剂。UPD:哦,这不是可变的-setParameter创建一个克隆。好吧,仍然setHost / setPort / ...可以相同的方式工作。或者,也许可变的版本也将是不错的选择。
mvmn

3
“零依赖的最简单,完整的解决方案”-听起来您知道什么很重要!您的答案应该是被接受的一个恕我直言。包括所有HttpClient(及其所有版本更新,甚至不赞成使用此问题的所有API),仅用于构建url的原因就是那些臭名昭著的应用程序。
Stijn de Witt

2
终于在Maven Central上,我只花了四年时间就完成了工作。
Mikael Gueck

@mikaelhg谢谢!我正是在这一刻需要!
法比安·丹肯


29

使用HTTPClient效果很好。

protected static String createUrl(List<NameValuePair> pairs) throws URIException{

  HttpMethod method = new GetMethod("http://example.org");
  method.setQueryString(pairs.toArray(new NameValuePair[]{}));

  return method.getURI().getEscapedURI();

}

6
现在已弃用该功能。有谁知道如何使用新的HTTP Components程序包来做同样的事情,因为它使我很困惑。
Link19 2012年

3
新的4x版本不再支持此功能。
Joscha 2012年

13

有很多可以帮助您进行URI构建的库(请不要重新发明轮子)。这是三个让您入门的方法:


Java EE 7

import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();

org.apache.httpcomponents:httpclient:4.5.2

import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();

org.springframework:spring-web:4.2.5.RELEASE

import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();

另请参阅: GIST> URI构建器测试


2
EE 7是正确的答案。您要做的就是拉入整个EE库套件,选择一个JAX-RS实现,解决jax-rs版本冲突,作为奖励,您将获得一个方便使用的UriBuilder类,该类非常好用。除了讽刺,这正确的答案。:)
tekHedd


10

使用OkHttp

这是2020年,有一个名为一个非常受欢迎的库OkHttp已经出演35K GitHub上的时间。使用此库,您可以构建如下的URL:

import okhttp3.HttpUrl;

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

我修正了一个错字addPathSegment(不是addPathSegments)。
PapaFreud

1

由于建议URL类而受到抨击。我将接受评论者的建议,并建议使用URI类。我建议您仔细查看URI的构造函数,因为该类一旦创建就非常不可变。
我认为此构造函数允许您设置URI中可能需要的所有内容。

URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
          Constructs a hierarchical URI from the given components.

8
但是它不提供从一组名称值对中实际构造和编码查询字符串的功能。
Link19 2012年

4
正如这位儿童神童对艾伦·帕特里奇(Alan Partridge)所说的那样-不能改变不变性,要么是,要么不是;-) youtube.com/watch?v=_lvFns5Lubc
斯图尔特

URI的构造函数对路径执行讨厌的操作。有关详细信息,请参见blog.palominolabs.com/2013/10/03/…
mpierce 2013年

1
让这个答案作为一个例子,说明如何不这样做。
Mike Pone

1
字符串查询...感谢Sun / Oracle的详细信息。我们将用加号替换所有空格,对所有参数进行uri编码,然后自己将它们与“&”符号链接在一起,然后……重 击刘海
Stijn de Witt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.