Подтвердить что ты не робот

Добавить относительный URL-адрес в java.net.URL

Если у меня есть объект java.net.URL, указывающий, что можно сказать

http://example.com/myItems или http://example.com/myItems/

Есть ли какой-нибудь помощник, чтобы добавить к нему какой-то относительный URL? Например, добавьте ./myItemId или myItemId, чтобы получить: http://example.com/myItems/myItemId

4b9b3361

Ответ 1

URL имеет конструктор, который принимает базовый URL и спецификацию String.

В качестве альтернативы, java.net.URI придерживается более строгих стандартов и имеет метод resolve сделать то же самое. Создайте URI из вашего URL используя URL.toURI.

Ответ 2

Для этого нет необходимости в дополнительных libs или code и дает желаемый результат:

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

Принятый ответ работает только в том случае, если после хоста нет пути (IMHO принятый ответ неверен)

Ответ 3

Вот вспомогательная функция, которую я написал для добавления к 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();
}

Ответ 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;
}

Это, где я нашел источник.

В сочетании с Apache URIBuilder, вот как я его использую: builder.setPath(appendSegmentToPath(builder.getPath(), segment));

Ответ 5

Вы можете использовать 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

Ответ 6

ОБНОВЛЕНО

Я считаю, что это кратчайшее решение:

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

Ответ 7

Некоторые примеры с использованием Apache URIBuilder http://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html:

Ex1:

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 → http://example.com/test/example

Ex2:

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 → http://example.com/test/example

Ответ 8

Объединить относительный путь к 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

Ответ 9

Вы можете просто использовать класс 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

Обратите внимание на косую черту на базовом пути и базовый относительный формат добавляемого сегмента. Вы также можете использовать класс URIBuilder из HTTP-клиента Apache:

<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();
}

Ответ 10

У меня были некоторые трудности с кодировкой URI. Аппендинг не работал для меня, потому что он имел тип содержимого://и ему не нравился символ "/". Это решение не предполагает ни запроса, ни фрагмента (в конце концов, мы работаем с путями):

Код Котлина:

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

Ответ 11

Мое решение на основе ответа 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());
    }
}

Gist: https://gist.github.com/enginer/230e2dc2f1d213a825d5

Ответ 12

Для android убедитесь, что вы используете .appendPath() от android.net.Uri

Ответ 13

На Android вы можете использовать android.net.Uri. Следующее позволяет создать Uri.Builder из существующего URL как String а затем добавить:

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

Обратите внимание, что appendEncodedPath не ожидает начала / и содержит только проверку, заканчивается ли "baseUrl" на единицу, в противном случае он добавляется перед путем.