1. Overview
1.概述
In this short article, we’ll take a look at the main differences between URIs and URLs and implement examples to highlight those differences.
在这篇短文中,我们将看一下URI和URL之间的主要区别,并实施例子来强调这些区别。
2. URI and URL
2.URI和URL
The difference between them is straightforward after knowing their definitions:
在了解它们的定义之后,它们之间的区别就很直接了。
- Uniform Resource Identifier (URI) − a sequence of characters that allows the complete identification of any abstract or physical resource
- Uniform Resource Locator (URL) − a subset of URI that, in addition to identifying where a resource is available, describes the primary mechanism to access it
Now we can conclude that every URL is a URI, but the opposite is not true, as we’ll see later.
现在我们可以得出结论,每个URL都是一个URI,但事实并非如此,我们将在后面看到。
2.1. Syntax
2.1.语法
Every URI, regardless if it’s a URL or not, follows a particular form:
每个URI,不管它是否是一个URL,都遵循一个特定的形式。
scheme:[//authority][/path][?query][#fragment]
Where each part is described as follows:
其中每个部分的描述如下。
- scheme − for URLs, is the name of the protocol used to access the resource, for other URIs, is a name that refers to a specification for assigning identifiers within that scheme
- authority − an optional part comprised of user authentication information, a host and an optional port
- path − it serves to identify a resource within the scope of its scheme and authority
- query − additional data that, along with the path, serves to identify a resource. For URLs, this is the query string
- fragment − an optional identifier to a specific part of the resource
To easily identify if a particular URI is also a URL, we can check its scheme. Every URL has to start with any of these schemes: ftp, http, https, gopher, mailto, news, nntp, telnet, wais, file, or prospero. If it doesn’t start with it, then it’s not a URL.
为了方便识别一个特定的URI是否也是一个URL,我们可以检查其方案。每个URL都必须以这些方案中的任何一个开始。ftp, http, https, gopher, mailto, news, nntp, telnet, wais, file, 或prospero。如果它不是以它开头,那么它就不是一个URL。
Now that we know the syntax, let’s look at some examples. Here is a list of URIs, where only the first three are URLs:
现在我们知道了这个语法,让我们看看一些例子。下面是一个URI列表,其中只有前三个是URLs。
ftp://ftp.is.co.za/rfc/rfc1808.txt
https://tools.ietf.org/html/rfc3986
mailto:john@doe.com
tel:+1-816-555-1212
urn:oasis:names:docbook:dtd:xml:4.1
urn:isbn:1234567890
3. URI and URL Java API Differences
3.URI和URL的Java API差异
In this section, we’ll demonstrate with examples the main differences between the URI and URL classes provided by Java.
在这一节中,我们将用实例证明Java提供的URI和URL类之间的主要区别。
3.1. Instantiation
3.1.实例化
Creating URI and URL instances is very similar, both classes provide several constructors that accept most of its parts, however, only the URI class has a constructor to specify all parts of the syntax:
创建URI和URL实例非常相似,两个类都提供了几个接受其大部分部分的构造函数,然而,只有URI类有一个构造函数来指定语法的所有部分。
@Test
public void whenCreatingURIs_thenSameInfo() throws Exception {
URI firstURI = new URI(
"somescheme://theuser:thepassword@someauthority:80"
+ "/some/path?thequery#somefragment");
URI secondURI = new URI(
"somescheme", "theuser:thepassword", "someuthority", 80,
"/some/path", "thequery", "somefragment");
assertEquals(firstURI.getScheme(), secondURI.getScheme());
assertEquals(firstURI.getPath(), secondURI.getPath());
}
@Test
public void whenCreatingURLs_thenSameInfo() throws Exception {
URL firstURL = new URL(
"http://theuser:thepassword@somehost:80"
+ "/path/to/file?thequery#somefragment");
URL secondURL = new URL("http", "somehost", 80, "/path/to/file");
assertEquals(firstURL.getHost(), secondURL.getHost());
assertEquals(firstURL.getPath(), secondURL.getPath());
}
The URI class also provides a utility method to create a new instance that does not throw a checked exception:
URI类还提供了一个实用方法来创建一个新的实例,该方法不会抛出一个检查过的异常。
@Test
public void whenCreatingURI_thenCorrect() {
URI uri = URI.create("urn:isbn:1234567890");
assertNotNull(uri);
}
The URL class doesn’t provide such a method.
URL类并没有提供这样的方法。
Since a URL has to start with one of the previously mentioned schemes, trying to create an object with a different one will result in an exception:
由于一个URL必须以前面提到的方案之一开始,试图用不同的方案创建一个对象将导致一个异常。
@Test(expected = MalformedURLException.class)
public void whenCreatingURLs_thenException() throws Exception {
URL theURL = new URL("otherprotocol://somehost/path/to/file");
assertNotNull(theURL);
}
There are other constructors in both classes, to discover them all, please refer to the URI and URL documentation.
在这两个类中还有其他构造函数,要发现它们,请参考URI和URL文档。
3.2. Converting Between URI and URL Instances
3.2.在URI和URL实例之间进行转换
Conversion between URI and URL is pretty straightforward:
URI和URL之间的转换是非常直接的。
@Test
public void givenObjects_whenConverting_thenCorrect()
throws MalformedURLException, URISyntaxException {
String aURIString = "http://somehost:80/path?thequery";
URI uri = new URI(aURIString);
URL url = new URL(aURIString);
URL toURL = uri.toURL();
URI toURI = url.toURI();
assertNotNull(url);
assertNotNull(uri);
assertEquals(toURL.toString(), toURI.toString());
}
However, trying to convert a non-URL URI results in an exception:
然而,试图转换一个非URL的URI时,会出现一个异常。
@Test(expected = MalformedURLException.class)
public void givenURI_whenConvertingToURL_thenException()
throws MalformedURLException, URISyntaxException {
URI uri = new URI("somescheme://someauthority/path?thequery");
URL url = uri.toURL();
assertNotNull(url);
}
3.3. Opening a Remote Connection
3.3.打开一个远程连接
Since a URL is a valid reference to a remote resource, Java provides methods for opening a connection to that resource and obtain its contents:
由于URL是对远程资源的有效引用,Java提供了打开与该资源的连接并获取其内容的方法。
@Test
public void givenURL_whenGettingContents_thenCorrect()
throws MalformedURLException, IOException {
URL url = new URL("http://courses.baeldung.com");
String contents = IOUtils.toString(url.openStream());
assertTrue(contents.contains("<!DOCTYPE html>"));
}
It should be noted that the implementation of the URL equals() and hashcode() functions may trigger the DNS naming service to resolve the IP address. This is inconsistent and can give different results depending on the network connection and also takes a long time to run. The implementation is known to be incompatible with virtual hosting and should not be used. We recommend using URI instead.
应该注意的是,URL equals()和hashcode()函数的实现可能会触发DNS命名服务来解析IP地址。这是不一致的,可能会根据网络连接情况给出不同的结果,而且还需要很长的时间来运行。众所周知,该实现与虚拟主机不兼容,不应使用。我们建议使用URI代替。
4. Conclusion
4 结语
In this quick article, we presented a few examples to demonstrate the differences between URI and URL in Java.
在这篇快速文章中,我们介绍了几个例子来证明Java中URI和URL之间的区别。
We highlighted the differences when creating instances of both objects and while converting one object to the other. We also showed that a URL has methods to open a remote connection to the pointed resource.
我们强调了在创建这两个对象的实例以及将一个对象转换为另一个对象时的差异。我们还展示了一个URL具有打开指向资源的远程连接的方法。
As always, complete source code for this article can be found over on Github.
一如既往,本文的完整源代码可以在Github上找到over。