Apa cara idiomatik untuk menulis URL atau URI di Java?

115

Bagaimana cara membuat URL atau URI di Java? Adakah cara idiomatik, atau perpustakaan yang dengan mudah melakukan ini?

Saya perlu mengizinkan mulai dari string permintaan, mengurai / mengubah berbagai bagian URL (skema, host, jalur, string kueri) dan mendukung penambahan dan pengkodean parameter kueri secara otomatis.

jon077
sumber
7
Memberikan suara positif untuk pertanyaan lama setelah ditutup karena tidak jelas apakah solusi populer yang tidak digunakan lagi untuk masalah ini ada. Saya menemukan ini dengan googling untuk 'kelas parameter URL java'.
pengguna1445967
4
Maksud saya adalah menemukan pembuat URL untuk Java, dan pertanyaan ini setidaknya berguna bagi saya.
pusaran angin

Jawaban:

76

Pada Apache HTTP Component HttpClient 4.1.3, dari tutorial resmi :

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=
}
}

Edit: sejak v4.2 URIUtils.createURI()sudah tidak digunakan lagi dan mendukung 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
sumber
20
Ini berfungsi, tetapi mulai v4.2 URIUtils.createURI () sudah tidak digunakan lagi dan mendukung URIBuilder. Sisi positifnya, URIBuilder ini tampaknya memiliki metode addParameter () sehingga membuat string permintaan setidaknya harus lebih sederhana sekarang.
stian
6
URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);seperti yang dikatakan @stian
vanduc1102
Println di atas mencetak berikut ini; google.com/…
Berkan Ercan
61

Sebagai penulis, saya mungkin bukan orang terbaik untuk menilai apakah pembuat URL / URI saya bagus , tetapi ini dia: https://github.com/mikaelhg/urlbuilder

Saya menginginkan solusi lengkap yang paling sederhana dengan nol dependensi di luar JDK, jadi saya harus menggulir sendiri.

Mikael Gueck
sumber
6
Kelihatannya bagus Mikael, apakah Anda sudah berpikir untuk menerbitkannya ke maven central? Saya tahu ini kecil tetapi membuatnya lebih mudah. Saya tidak dapat menemukan kelas serupa selain di JAX-RS. Kurangnya ketergantungan jelas merupakan nilai tambah.
Barry Pitman
Kelihatannya bagus, tetapi karena ini adalah pembangun dan bisa berubah, mengapa ada penyetel hanya untuk parameter, tetapi tidak untuk host, port, protokol dan jalur? Dan, yah, tidak ada getter untuk itu juga. UPD: Oh, ini tidak bisa berubah - setParameter membuat tiruan. Yah, tetap saja setHost / setPort / ... bisa bekerja dengan cara yang sama. Atau, mungkin, versi yang bisa berubah akan menyenangkan untuk dimiliki juga.
mvmn
3
"solusi lengkap sesederhana mungkin tanpa ketergantungan" - Sepertinya Anda tahu apa yang penting! Jawaban Anda harus diterima imho. Menyertakan semua HttpClient (dengan semua pembaruan versinya dan bahkan menolak API yang menjadi inti pertanyaan ini) hanya untuk membangun url adalah alasan mengapa aplikasi penuh bug paling berat.
Stijn de Witt
2
Akhirnya di Maven Central, dan hanya butuh empat tahun untuk menyelesaikannya.
Mikael Gueck
@mikaelhg Terima kasih! Saya perlu tepat pada saat ini!
Fabian Damken
29

Penggunaan HTTPClient bekerja dengan baik.

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
sumber
6
Fungsi ini sekarang sudah tidak digunakan lagi. Apakah ada yang tahu bagaimana menggunakan paket Komponen HTTP baru untuk melakukan hal yang sama karena itu membuat saya bingung.
Link19
3
Versi 4x baru tidak mendukung ini lagi.
Joscha
13

Ada banyak pustaka yang dapat membantu Anda dengan pembuatan URI (jangan menemukan kembali roda). Berikut tiga hal untuk Anda mulai:


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: spring-web: 4.2.5.RELEASE

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

Lihat juga: GIST> URI Builder Tests

Nick Grealy
sumber
2
EE 7 adalah jawaban yang benar. Yang harus Anda lakukan adalah menarik seluruh rangkaian pustaka EE, memilih implementasi JAX-RS, menyelesaikan konflik versi jax-rs, dan sebagai imbalannya Anda akan memiliki kelas UriBuilder praktis yang bekerja dengan sangat baik. Terlepas dari sarkasme, ini adalah jawaban yang benar. :)
tekHedd
1
Mulai Musim Semi 5, periksa UriBuilder( docs.spring.io/spring-framework/docs/current/javadoc-api/org/… ) dan UriBuilderFactory( docs.spring.io/spring-framework/docs/current/javadoc-api/org /… )
Brice Roncace
10

Gunakan OkHttp

Ini tahun 2020 dan ada perpustakaan yang sangat populer bernama OkHttp yang telah dibintangi 35K kali di GitHub. Dengan perpustakaan ini, Anda dapat membuat url seperti di bawah ini:

import okhttp3.HttpUrl;

URL url = new HttpUrl.Builder()
    .scheme("http")
    .host("example.com")
    .port(4567)
    .addPathSegment("foldername/1234")
    .addQueryParameter("abc", "xyz")
    .build().url();
Tyler Long
sumber
Saya memperbaiki kesalahan ketik, itu addPathSegment(bukan addPathSegments).
PapaFreud
1

Setelah dikecam karena menyarankan kelas URL. Saya akan menerima saran pemberi komentar dan menyarankan kelas URI sebagai gantinya. Saya sarankan Anda melihat lebih dekat konstruktor untuk URI karena kelasnya sangat tidak berubah setelah dibuat.
Saya rasa konstruktor ini memungkinkan Anda untuk mengatur segala sesuatu di URI yang mungkin Anda perlukan.

URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
          Constructs a hierarchical URI from the given components.
Mike Pone
sumber
8
Tapi itu tidak menyediakan fungsionalitas untuk benar-benar membangun dan menyandikan string kueri dari sekumpulan pasangan nilai nama.
Link19
4
Seperti yang dikatakan anak ajaib kepada Alan Partridge - seseorang tidak dapat memiliki degradasi keabadian, baik itu atau bukan ;-) youtube.com/watch?v=_lvFns5Lubc
Stewart
Konstruktor URI melakukan hal-hal buruk pada jalur. Lihat blog.palominolabs.com/2013/10/03/… untuk detailnya.
mpierce
1
Biarkan jawaban ini berdiri sebagai contoh bagaimana TIDAK melakukan ini.
Mike Pone
1
Kueri string ... Terima kasih Sun / Oracle atas perinciannya. Kami hanya akan mengganti semua spasi dengan simbol plus, uri-encode semua parameter dan menghubungkan semuanya bersama dengan simbol ampersand sendiri lalu ... poni kepala di atas meja berulang kali
Stijn de Witt