在 Java 中编写 URL 或 URI 的惯用方式是啥?
Posted
技术标签:
【中文标题】在 Java 中编写 URL 或 URI 的惯用方式是啥?【英文标题】:What is the idiomatic way to compose a URL or URI in Java?在 Java 中编写 URL 或 URI 的惯用方式是什么? 【发布时间】:2010-10-27 08:33:21 【问题描述】:如何在 Java 中构建 URL 或 URI?有没有一种惯用的方式或库可以轻松做到这一点?
我需要允许从请求字符串开始,解析/更改各种 URL 部分(方案、主机、路径、查询字符串)并支持添加和自动编码查询参数。
【问题讨论】:
在该问题关闭很久后对其进行投票,因为尚不清楚是否存在针对此问题的流行且不弃用的解决方案。我通过谷歌搜索“java URL 参数类”找到了这一点。 我的目的是为 Java 找到一个 URL 构建器,这个问题至少对我有用。 【参考方案1】:截至Apache HTTP Component HttpClient 4.1.3,来自官方tutorial:
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());
【讨论】:
这可行,但从 v4.2 开始,URIUtils.createURI() 已被弃用,取而代之的是 URIBuilder。从积极的方面来说,这个 URIBuilder 似乎有一个 addParameter() 方法,所以现在构建请求字符串应该更简单了。URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);
正如@stian所说的
Println 上面打印以下内容; google.com/…
教程链接失效
要给出多条路径时如何设置路径?例如。 "localhost/api/customer" + "/" +Id1 + "/" + "summary?invoiceId=" + Id2 + "&page=0&pageSize=10&q=" + Id3;【参考方案2】:
作为作者,我可能不是判断我的 URL/URI 构建器是否好的最佳人选,但这里仍然是:https://github.com/mikaelhg/urlbuilder
我想要最简单的完整解决方案,在 JDK 之外零依赖,所以我不得不自己动手。
【讨论】:
它看起来很棒 Mikael,你有没有想过将它发布到 maven Central?我知道它很小,但使用起来更容易。除了在 JAX-RS 中,我找不到类似的课程。缺乏依赖绝对是一个加分项。 看起来不错,但既然它是一个构建器,因此是可变的,为什么只有参数的设置器,而不是主机、端口、协议和路径的设置器?而且,好吧,那些也没有吸气剂。 UPD:哦,它不是可变的 - setParameter 创建一个克隆。好吧,仍然 setHost/setPort/... 可以以相同的方式工作。或者,也许,一个可变版本也很不错。 “零依赖的最简单的完整解决方案” - 听起来你知道什么是重要的!您的答案应该是公认的恕我直言。包括所有的 HttpClient(包括它的所有版本更新,甚至弃用这个问题所涉及的 API)只是为了构建一个 url 是导致头重脚轻的 bug 困扰的应用程序的原因。 终于在 Maven Central 上,我只花了四年时间就完成了。 @mikaelhg 谢谢!我正是在这一刻需要!【参考方案3】:Apache HTTPClient?
【讨论】:
截至 2015 年 6 月:hc.apache.org/httpcomponents-client-ga/tutorial/html/…【参考方案4】:使用 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();
【讨论】:
现在已弃用此功能。有谁知道如何使用新的 HTTP 组件包来做同样的事情,因为它难倒我。 新的4x版本不再支持这个了。【参考方案5】:有很多库可以帮助您构建 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 Builder Tests
【讨论】:
EE 7 是正确答案。您所要做的就是引入整套 EE 库,选择一个 JAX-RS 实现,解决 jax-rs 版本冲突,作为奖励,您将拥有一个运行良好的方便的 UriBuilder 类。撇开讽刺不谈,这是正确答案。 :) 从 Spring 5 开始,请查看UriBuilder
(docs.spring.io/spring-framework/docs/current/javadoc-api/org/…) 和 UriBuilderFactory
(docs.spring.io/spring-framework/docs/current/javadoc-api/org/…)【参考方案6】:
使用 OkHttp
现在是 2021,有一个非常受欢迎的库,名为 OkHttp,它在 GitHub 上已被加星标 40K 次。使用这个库,您可以构建一个如下所示的 url:
import okhttp3.HttpUrl;
URL url = new HttpUrl.Builder()
.scheme("http")
.host("example.com")
.port(4567)
.addPathSegments("foldername/1234")
.addQueryParameter("abc", "xyz")
.build().url();
【讨论】:
我修正了一个错字,它是addPathSegment
(不是addPathSegments
)。
@PapaFreud 都因不同的原因而存在,已恢复修复。【参考方案7】:
在因建议 URL 类而受到抨击之后。我会采纳评论者的建议并建议使用URI class。我建议您仔细查看 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.
【讨论】:
但它不提供从一组名称值对中实际构造和编码查询字符串的功能。 正如神童对艾伦·帕特里奇所说的那样——不变性不能退化,要么是,要么不是;-) youtube.com/watch?v=_lvFns5Lubc URI 的构造函数对路径做了一些讨厌的事情。详情请见blog.palominolabs.com/2013/10/03/…。 让这个答案作为一个例子来说明如何不这样做。 字符串查询...感谢 Sun/Oracle 提供的粒度。我们将用加号替换所有空格,对所有参数进行 uri 编码,然后自己用 & 符号将它们链接在一起...... 反复敲击桌面以上是关于在 Java 中编写 URL 或 URI 的惯用方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章
Java URL 类 getPath()、getQuery() 和 getFile() 与 RFC3986 URI 语法不一致