【问题标题】:How to build an absolute URL from a relative URL using Java?如何使用 Java 从相对 URL 构建绝对 URL?
【发布时间】:2018-08-14 07:39:25
【问题描述】:

我有一个相对的 url 字符串,知道主机和协议。如何构建绝对 url 字符串?

看起来很简单?乍一看是的,但直到转义字符出现。我必须从 302 代码 http(s) 响应位置标头构建绝对 url。

让我们考虑一个例子

protocol: http
host: example.com
location: /path/path?param1=param1Data&param2= " 

首先我尝试构建 url 字符串,例如:

Sting urlString = protocol+host+location

URL 类的构造函数不转义空格和双引号:

new URL(urlString)

URI 类的构造函数失败并出现异常:

new URI(urlString)

URI.resolve 方法也因异常而失败

然后我发现 URI 可以转义查询字符串中的参数,但只有少数构造函数,例如:

URI uri = new URI("http", "example.com", 
    "/path/path", "param1=param1Data&param2= \"", null);

这个构造函数需要路径和查询是单独的参数,但我有一个相对 URL,它没有被路径和查询部分分割。

我可以考虑检查相对 URL 是否包含“?”问题标志并认为它之前的所有内容都是路径,并且它之后的所有内容都是查询,但是如果相对 url 不包含路径,而只包含查询,并且查询包含“?”怎么办?标志?那么这将不起作用,因为部分查询将被视为路径。

现在我无法了解如何从相对 url 构建绝对 url。

这些公认的答案似乎是错误的:

当相对 url 与主机和某些路径部分的 url 相关时,考虑这种情况可能会很好:

初始地址http://example.com/...some路径... relative /home?...在此处查询...

获得java核心解决方案会很棒,尽管仍然可以使用一个好的库。

【问题讨论】:

  • @AustinSchäfer 你确定吗?你读过这个问题吗?
  • 不完全。我错认为它是重复的,但问题名称可能应该更新以反映它是一种特殊情况。
  • @AustinSchäfer 我认为这个问题实际上是正确的,因为我问的不是特殊情况,而是更笼统地说,然后是我提到的其他主题。相反,重命名它们可能是有意义的,以免混淆。你怎么看?
  • 我认为您已经回答了自己的问题,请使用带有单独路径、查询和片段参数的 URI 构造函数。第一个? 应该定义路径和查询之间的限制,第一个# 应该定义片段的限制
  • @whoever who put:这个问题在这里可能已经有了答案:在我的问题之上。在你做这些事情之前,你能帮我一个忙并阅读这个问题吗?谢谢。

标签: java http url


【解决方案1】:

第一个? 表示查询字符串的开始位置:

3.4. Query

[...] 查询组件由第一个问号 (?) 字符指示,并以数字符号 (#) 字符或 URI 结尾。

一种简单的方法(不处理片段并假设查询字符串始终存在)很简单:

String protocol = "http";
String host = "example.com";
String location = "/path/path?key1=value1&key2=value2";

String path = location.substring(0, location.indexOf("?"));
String query = location.substring(location.indexOf("?") + 1);

URI uri = new URI(protocol, host, path, query, null);

也可以处理片段的更好方法是:

String protocol = "http";
String host = "example.com";
String location = "/path/path?key1=value1&key2=value2#fragment";

// Split the location without removing the delimiters
String[] parts = location.split("(?=\\?)|(?=#)");

String path = null;
String query = null;
String fragment = null;

// Iterate over the parts to find path, query and fragment
for (String part : parts) {
    
    // The query string starts with ?
    if (part.startsWith("?")) {
        query = part.substring(1); 
        continue;
    }
    
    // The fragment starts with #
    if (part.startsWith("#")) {
        fragment = part.substring(1);
        continue;
    }
    
    // Path is what's left
    path = part;
}

URI uri = new URI(protocol, host, path, query, fragment);

【讨论】:

  • 谢谢。因为之前对 RFC3986 不熟悉,所以没能解决。
【解决方案2】:

最好的方法似乎是使用多部分构造函数创建一个 URI 对象,然后将其转换为如下所示的 URL:

URI uri = new URI("https", "sitename.domain.tld", "/path/goes/here", "param1=value&param2=otherValue");
URL url = uri.toURL();

【讨论】:

  • 正如问题中提到的,我认为这是一种可能的方法,但我将如何按部分拆分相对 url 以了解路径和查询?
  • 在你的字符串中找到第三个 / 来找到子路径,然后找到第一个 ?查找查询参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-10
  • 2019-03-14
  • 2016-01-05
  • 2012-03-31
  • 2011-09-09
  • 1970-01-01
相关资源
最近更新 更多