将相对URL附加到java.net.URL

时间:2011-09-21 10:07:40

标签: java url

如果我有一个java.net.URL对象,指向让我们说

http://example.com/myItemshttp://example.com/myItems/

是否有某个帮助程序可以在某处添加一些相对URL? 例如,附加./myItemIdmyItemId来获取: http://example.com/myItems/myItemId

15 个答案:

答案 0 :(得分:25)

URLconstructor,其基数为URLString

或者,java.net.URI更贴近标准,并采用resolve方法做同样的事情。使用URL.toURIURI创建URL

答案 1 :(得分:24)

这个不需要任何额外的库或代码,并提供所需的结果:

URL url1 = new URL("http://petstore.swagger.wordnik.com/api/api-docs");
URL url2 = new URL(url1.getProtocol(), url1.getHost(), url1.getPort(), url1.getFile() + "/pet", null);
System.out.println(url1);
System.out.println(url2);

打印:

http://petstore.swagger.wordnik.com/api/api-docs
http://petstore.swagger.wordnik.com/api/api-docs/pet

只有在主持人之后没有路径(恕我直言,接受的答案错误)

时,接受的答案才有效

答案 2 :(得分:6)

这是我写的一个帮助函数,用于添加到url路径:

public static URL concatenate(URL baseUrl, String extraPath) throws URISyntaxException, 
                                                                    MalformedURLException {
    URI uri = baseUrl.toURI();
    String newPath = uri.getPath() + '/' + extraPath;
    URI newUri = uri.resolve(newPath);
    return newUri.toURL();
}

答案 3 :(得分:4)

我已经广泛搜索了这个问题的答案。我能找到的唯一实现是在Android SDK中:Uri.Builder。我已经为自己的目的提取了它。

private String appendSegmentToPath(String path, String segment) {
  if (path == null || path.isEmpty()) {
    return "/" + segment;
  }

  if (path.charAt(path.length() - 1) == '/') {
    return path + segment;
  }

  return path + "/" + segment;
}

This是我找到来源的地方。

Apache URIBuilder结合使用,这就是我使用它的方式:builder.setPath(appendSegmentToPath(builder.getPath(), segment));

答案 4 :(得分:3)

您可以使用URIBuilder和方法URI#normalize来避免URI中重复的/

URIBuilder uriBuilder = new URIBuilder("http://example.com/test");
URI uri = uriBuilder.setPath(uriBuilder.getPath() + "/path/to/add")
          .build()
          .normalize();
// expected : http://example.com/test/path/to/add

答案 5 :(得分:2)

<强>已更新

我相信这是最短的解决方案:

URL url1 = new URL("http://domain.com/contextpath");
String relativePath = "/additional/relative/path";
URL concatenatedUrl = new URL(url1.toExternalForm() + relativePath);

答案 6 :(得分:1)

使用Apache URIBuilder http://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html的一些示例:

练习1:

String url = "http://example.com/test";
URIBuilder builder = new URIBuilder(url);
builder.setPath((builder.getPath() + "/example").replaceAll("//+", "/"));
System.out.println("Result 1 -> " + builder.toString());

结果1 - &gt; http://example.com/test/example

练习2:

String url = "http://example.com/test";
URIBuilder builder = new URIBuilder(url);
builder.setPath((builder.getPath() + "///example").replaceAll("//+", "/"));
System.out.println("Result 2 -> " + builder.toString());

结果2 - &gt; http://example.com/test/example

答案 7 :(得分:1)

连接到URI的相对路径:

java.net.URI uri = URI.create("https://stackoverflow.com/questions")
java.net.URI res = uri.resolve(uri.getPath + "/some/path")

res将包含https://stackoverflow.com/questions/some/path

答案 8 :(得分:1)

您可以使用URI类:

import java.net.URI;
import org.apache.http.client.utils.URIBuilder;

URI uri = URI.create("http://example.com/basepath/");
URI uri2 = uri.resolve("./relative");
// => http://example.com/basepath/relative

请注意基本路径上的尾部斜杠以及要追加的段的基本相对格式。您还可以使用Apache HTTP客户端的URIBuilder类:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

...

import java.net.URI;
import org.apache.http.client.utils.URIBuilder;

URI uri = URI.create("http://example.com/basepath");
URI uri2 = appendPath(uri, "relative");
// => http://example.com/basepath/relative

public URI appendPath(URI uri, String path) {
    URIBuilder builder = new URIBuilder(uri);
    builder.setPath(URI.create(builder.getPath() + "/").resolve("./" + path).getPath());
    return builder.build();
}

答案 9 :(得分:1)

我对URI的编码有些困难。追加不适合我,因为它是一个内容://类型,它不喜欢&#34; /&#34;。这个解决方案假设没有查询,也没有片段(我们毕竟使用路径):

Kotlin代码:

  val newUri = Uri.parse(myUri.toString() + Uri.encode("/$relPath"))

答案 10 :(得分:0)

我的解决方案基于twhitbeck回答:

import java.net.URI;
import java.net.URISyntaxException;

public class URIBuilder extends org.apache.http.client.utils.URIBuilder {
    public URIBuilder() {
    }

    public URIBuilder(String string) throws URISyntaxException {
        super(string);
    }

    public URIBuilder(URI uri) {
        super(uri);
    }

    public org.apache.http.client.utils.URIBuilder addPath(String subPath) {
        if (subPath == null || subPath.isEmpty() || "/".equals(subPath)) {
            return this;
        }
        return setPath(appendSegmentToPath(getPath(), subPath));
    }

    private String appendSegmentToPath(String path, String segment) {
        if (path == null || path.isEmpty()) {
            path = "/";
        }

        if (path.charAt(path.length() - 1) == '/' || segment.startsWith("/")) {
            return path + segment;
        }

        return path + "/" + segment;
    }
}

测试:

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class URIBuilderTest {

    @Test
    public void testAddPath() throws Exception {
        String url = "http://example.com/test";
        String expected = "http://example.com/test/example";

        URIBuilder builder = new URIBuilder(url);
        builder.addPath("/example");
        assertEquals(expected, builder.toString());

        builder = new URIBuilder(url);
        builder.addPath("example");
        assertEquals(expected, builder.toString());

        builder.addPath("");
        builder.addPath(null);
        assertEquals(expected, builder.toString());

        url = "http://example.com";
        expected = "http://example.com/example";

        builder = new URIBuilder(url);
        builder.addPath("/");
        assertEquals(url, builder.toString());
        builder.addPath("/example");
        assertEquals(expected, builder.toString());
    }
}

要点:https://gist.github.com/enginer/230e2dc2f1d213a825d5

答案 11 :(得分:0)

对于Android,请务必使用.appendPath()

中的android.net.Uri

答案 12 :(得分:0)

在Android上,您可以使用android.net.Uri。以下内容允许从现有URL作为Uri.Builder创建一个String,然后附加:

Uri.parse(baseUrl) // Create Uri from String
    .buildUpon()   // Creates a "Builder"
    .appendEncodedPath("path/to/add")
    .build()

请注意,appendEncodedPath不希望前导/,仅包含检查“ baseUrl”是否以1结尾,否则在路径之前添加一个。

答案 13 :(得分:0)

下面给出了没有任何外部库的实用解决方案。

(评论:读完到目前为止给出的所有答案之后,我真的对提供的解决方案感到不满意-尤其是因为这个问题已有八年历史了。没有解决方案可以正确地处理查询,片段等。)< / p>

URL的扩展方法

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

class URLHelper {
        public static URL appendRelativePathToURL(URL base, String relPath) {
            /*
              foo://example.com:8042/over/there?name=ferret#nose
              \_/   \______________/\_________/ \_________/ \__/
               |           |            |            |        |
            scheme     authority       path        query   fragment
               |   _____________________|__
              / \ /                        \
              urn:example:animal:ferret:nose

            see https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
            */
            try {

                URI baseUri = base.toURI();

                // cut initial slash of relative path
                String relPathToAdd = relPath.startsWith("/") ? relPath.substring(1) : relPath;

                // cut trailing slash of present path
                String path = baseUri.getPath();
                String pathWithoutTrailingSlash = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;

                return new URI(baseUri.getScheme(),
                        baseUri.getAuthority(),
                        pathWithoutTrailingSlash + "/" + relPathToAdd,
                        baseUri.getQuery(),
                        baseUri.getFragment()).toURL();
            } catch (URISyntaxException e) {
                throw new MalformedURLRuntimeException("Error parsing URI.", e);
            } catch (MalformedURLException e) {
                throw new MalformedURLRuntimeException("Malformed URL.", e);
            }
        }

        public static class MalformedURLRuntimeException extends RuntimeException {
            public MalformedURLRuntimeException(String msg, Throwable cause) {
                super("Malformed URL: " + msg, cause);
            }
        }
    }

测试

    private void demo() {

        try {
            URL coolURL = new URL("http://fun.de/path/a/b/c?query&another=3#asdf");
            URL notSoCoolURL = new URL("http://fun.de/path/a/b/c/?query&another=3#asdf");
            System.out.println(URLHelper.appendRelativePathToURL(coolURL, "d"));
            System.out.println(URLHelper.appendRelativePathToURL(coolURL, "/d"));
            System.out.println(URLHelper.appendRelativePathToURL(notSoCoolURL, "d"));
            System.out.println(URLHelper.appendRelativePathToURL(notSoCoolURL, "/d"));

        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

答案 14 :(得分:0)

public String joinUrls(String baseUrl, String extraPath) {
        try {
            URI uri = URI.create(baseUrl+"/");//added additional slash in case there is no slash at either sides
            URI newUri = uri.resolve(extraPath);
            return newUri.toURL().toString();
        } catch (IllegalArgumentException | MalformedURLException e) {
            //exception
        }
}