Каков идиоматический способ составить URL или URI в Java?

115

Как создать URL-адрес или URI в Java? Есть ли идиоматический способ или библиотеки, которые легко это делают?

Мне нужно разрешить запуск со строки запроса, анализировать / изменять различные части URL-адреса (схема, хост, путь, строка запроса) и поддерживать добавление и автоматическое кодирование параметров запроса.

jon077
источник
7
Голосовать за вопрос намного позже, чем он был закрыт, потому что неясно, существует ли популярное нерекомендуемое решение этой проблемы. Я нашел это в Google для "класса параметров URL-адреса java".
user1445967
4
Я намеревался найти построитель URL-адресов для Java, и этот вопрос, по крайней мере, для меня полезен.
Whirlwin

Ответы:

76

Что касается HTTP-компонента Apache HttpClient 4.1.3, из официального руководства :

public class HttpClientTest {
public static void main(String[] args) throws URISyntaxException {
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    qparams.add(new BasicNameValuePair("q", "httpclient"));
    qparams.add(new BasicNameValuePair("btnG", "Google Search"));
    qparams.add(new BasicNameValuePair("aq", "f"));
    qparams.add(new BasicNameValuePair("oq", null));
    URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
                                 URLEncodedUtils.format(qparams, "UTF-8"), null);
    HttpGet httpget = new HttpGet(uri);
    System.out.println(httpget.getURI());
    //http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
}
}

Изменить: начиная URIUtils.createURI()с версии 4.2 устарел в пользу URIBuilder:

URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
Chikei
источник
20
Это работает, но начиная с версии 4.2 URIUtils.createURI () устарел в пользу URIBuilder. С положительной стороны, этот URIBuilder, похоже, имеет метод addParameter (), поэтому создание строк запроса теперь должно быть, по крайней мере, проще.
stian
6
URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);как сказал @stian
vanduc1102
Println выше печатает следующее: google.com/…
Беркан Эрджан
61

Как автор, я, вероятно, не лучший человек, чтобы судить о том, хорош ли мой построитель URL / URI , но, тем не менее, вот он: https://github.com/mikaelhg/urlbuilder

Мне нужно было как можно более простое полное решение с нулевыми зависимостями вне JDK, поэтому мне пришлось применить собственное.

Микаэль Гек
источник
6
Выглядит здорово, Микаэль, вы не думали опубликовать его в maven central? Я знаю, что он маленький, но с ним проще пользоваться. Я не могу найти аналогичный класс, кроме JAX-RS. Отсутствие зависимостей однозначно плюс.
Барри Питман
Это выглядит красиво, но, поскольку это конструктор и, следовательно, изменяемый, почему существуют сеттеры только для параметров, а не для хоста, порта, протокола и пути? И для них тоже нет геттеров. UPD: Ой, это не изменяемо - setParameter создает клон. Ну, все же setHost / setPort / ... может работать так же. Или, возможно, было бы неплохо иметь изменяемую версию.
mvmn 01
3
«простейшее возможное полное решение с нулевыми зависимостями» - похоже, вы знаете, что важно! Ваш ответ должен быть принятым imho. Включение всего HttpClient (со всеми обновлениями его версий и даже отказом от того самого API, о котором идет речь) только для создания URL-адреса - вот что делает приложения с самыми тяжелыми ошибками.
Stijn de Witt
2
Наконец-то на Maven Central, и мне потребовалось всего четыре года, чтобы закончить.
Mikael Gueck
@mikaelhg Спасибо! Мне нужно именно в этот момент!
Фабиан Дамкен
29

Использование HTTPClient сработало.

protected static String createUrl(List<NameValuePair> pairs) throws URIException{

  HttpMethod method = new GetMethod("http://example.org");
  method.setQueryString(pairs.toArray(new NameValuePair[]{}));

  return method.getURI().getEscapedURI();

}
jon077
источник
6
Теперь это устаревшая функция. Кто-нибудь знает, как использовать новый пакет компонентов HTTP, чтобы сделать то же самое, потому что это меня озадачило.
Link19,
3
Новая версия 4x больше не поддерживает это.
Joscha
13

Существует множество библиотек, которые могут помочь вам в создании URI (не изобретайте велосипед). Вот три, с чего можно начать:


Java EE 7

import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();

org.apache.httpcomponents: HttpClient: 4.5.2

import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();

org.springframework: весна-страница: 4.2.5.RELEASE

import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();

См. Также: GIST> Тесты построителя URI

Ник Грили
источник
2
EE 7 - правильный ответ. Все, что вам нужно сделать, это задействовать весь набор библиотек EE, выбрать реализацию JAX-RS, разрешить конфликты версий jax-rs и в качестве награды получить удобный класс UriBuilder, который действительно хорошо работает. Сарказм в стороне, это является правильным ответом. :)
tekHedd
1
Начиная с весны 5 проверьте UriBuilder( docs.spring.io/spring-framework/docs/current/javadoc-api/org/… ) и UriBuilderFactory( docs.spring.io/spring-framework/docs/current/javadoc-api/org /… )
Брис Ронкаче
10

Используйте OkHttp

Это 2020 и есть очень популярная библиотека имени OkHttp которая помечено 35k раз на GitHub. С помощью этой библиотеки вы можете создать URL-адрес, как показано ниже:

import okhttp3.HttpUrl;

URL url = new HttpUrl.Builder()
    .scheme("http")
    .host("example.com")
    .port(4567)
    .addPathSegment("foldername/1234")
    .addQueryParameter("abc", "xyz")
    .build().url();
Тайлер Лонг
источник
Исправил опечатку, это addPathSegment(не addPathSegments).
PapaFreud
1

После критики за предложение класса URL. Я воспользуюсь советом комментатора и предложу вместо этого класс URI . Я предлагаю вам внимательно изучить конструкторы URI, поскольку после создания класс становится неизменным.
Я думаю, что этот конструктор позволяет вам установить в URI все, что вам может понадобиться.

URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
          Constructs a hierarchical URI from the given components.
Майк Поун
источник
8
Но он не предоставляет функциональных возможностей для фактического создания и кодирования строки запроса из набора пар имя-значение.
Link19 02
4
Как вундеркинд сказал Алану Партриджу - не может быть деградации неизменяемости, она либо есть, либо нет ;-) youtube.com/watch?v=_lvFns5Lubc
Стюарт
Конструктор URI делает с путем неприятные вещи. Подробности см. На сайте blog.palominolabs.com/2013/10/03/… .
mpierce
1
Пусть этот ответ будет примером того, как НЕ делать этого в таком случае.
Майк Поун,
1
Строковый запрос ... Спасибо Sun / Oracle за детализацию. Мы просто заменим все пробелы символами плюса, uri-закодируем все параметры и сами свяжем
Stijn de Witt