我想解析一些网址。为此,我采用以下结果:
new URL(new URL(baseurl), link);
这种方法似乎在何时baseurl="http://www.site.com"
失败link="./"
您将得到以下结果http://www.site.com/./
,而不仅仅是http://www.site.com/
我该如何解决这个问题?
我想解析一些网址。为此,我采用以下结果:
new URL(new URL(baseurl), link);
这种方法似乎在何时baseurl="http://www.site.com"
失败link="./"
您将得到以下结果http://www.site.com/./
,而不仅仅是http://www.site.com/
我该如何解决这个问题?
import java.net.*;
class TestURL {
public static void main(String[] args) throws Exception {
String s = "http://www.site.com/./";
URL url = new URL(s);
System.out.println(url);
URI uri = url.toURI();
System.out.println(uri.normalize().toURL());
}
}
http://www.site.com/./
http://www.site.com/
也许这会起作用?
new URI(baseUrl).resolve(link).toURL()
java.net.URI有一个 resolve 方法,它可能是您正在寻找的方法和 toURL 以将其放入 URL 。
编辑
以下似乎对我有用..
import java.net.URL;
public class UrlTest {
private static URL resolve(URL base, String link) throws Exception {
if (base.getPath().isEmpty()) {
link = "/" + link;
}
URL u1 = base.toURI().resolve(link).normalize().toURL();
return u1;
}
private static void resolveUrls(URL baseUrl) throws Exception {
String link = "abcd";
String link2 = "./";
String link3 = "./foo";
System.out.println(resolve(baseUrl, link));
System.out.println(resolve(baseUrl, link2));
System.out.println(resolve(baseUrl, link3));
}
public static void main(String[] args) throws Exception {
String baseUrlStr = "http://www.somesite.com";
URL baseUrl = new URL(baseUrlStr);
resolveUrls(baseUrl);
baseUrl = new URL(baseUrlStr + "/index.html");
resolveUrls(baseUrl);
baseUrl = new URL(baseUrlStr + "/path/index.html");
resolveUrls(baseUrl);
}
}
你可以试试这个
new URL(new URL(baseurl), link.replace("./"), "");
这是一个很长的帖子,虽然内容丰富,但在很大程度上没有帮助,但实际上最后有一个答案。
这都是一个有点悲伤的故事。这显然是完全疯狂的:
URI base = new URI("http", "example.org", null, null);
URI link = new URI(null, null, "index.html", null);
System.out.println(base.resolve(link));
应该打印:
http://example.orgindex.html
而不是:
http://example.org/index.html
然而它确实如此。为什么?因为java.net.URI
...
表示由RFC 2396定义的 URI 引用:统一资源标识符 (URI):通用语法
并且忠实地这样做。特别是,该resolve
方法...
以符合 RFC 2396第 5.2 节的方式构造新的分层 URI
遗憾的是,第 5.2 节中指定的算法是错误的。具体来说,虽然它说...
路径组件永远不会未定义,尽管它可能为空
它不能确保针对具有空路径的基本 URI 解析相对 URI 的结果是有效的 URI。问题出在第 6 步,它处理将来自基本 URI 和相对 URI 的路径合并到一个缓冲区中,该缓冲区将用于形成解析的 URI。步骤 6 的前两个子步骤是:
a) 除了基 URI 的路径组件的最后一段之外的所有部分都被复制到缓冲区。换句话说,最后一个(最右边的)斜线字符之后的任何字符(如果有)都将被排除。
b) 引用的路径组件附加到缓冲区字符串。
如果基础 URI 的路径为空,则在子步骤 a 之后,缓冲区将为空。如果相对 URI 有一个不以 / 开头的路径,那么在子步骤 b 之后,缓冲区将包含一个不以 / 开头的字符串。以下步骤处理点规范化,并且不添加前导 /。最后一步是:
h) 剩余的缓冲区字符串是引用 URI 的新路径组件。
因此,解析的 URI 有一个不以 / 开头的路径。然后,第 7 步将其构建为已解析 URI 的最终字符串形式,而无需任何插入 / 的规定。因此,将没有前导 / 的相对 URI 解析为具有空路径的基本 URI 会导致胡说八道。这是 RFC 2396 指定的内容,也是java.net.URI
如此。
哎呀!
故事并没有就此结束。2005 年 1 月,发布了RFC 3986。此已过时的 RFC 2396,并在第 5.2 节中再次包含 URI 解析的新定义。这个定义以更严格(或至少看起来很严谨)的风格完全重写,并在5.2.3 节中指定了路径的合并,首先要做到这一点:
如果基本 URI 具有已定义的权限组件和空路径,则返回由“/”与引用路径连接的字符串
因此,如果更新 Java 以符合 8 年前的 RFC,而不是 14 年前的 RFC,整个问题就会得到解决。这样做是错误 6791060中所要求的,该错误于 2009 年开放,最后一次触及是在 2010 年。孙,我很失望。
无论如何,有了这种理解,我们可以看到正确的解决方案是:
public static URI fix(URI uri) {
if (uri.getPath().isEmpty()) {
try {
return new URI(uri.getScheme(), uri.getAuthority(), "/", uri.getQuery(), uri.getFragment());
}
catch (URISyntaxException e) {
AssertionError ae = new AssertionError("highly implausible error fixing URI " + uri);
ae.initCause(e);
throw ae;
}
}
else {
return uri;
}
}
fix(new URI(baseurl)).resolve(link);