1. Ikhtisar
Pada artikel ini, kita akan melihat Pustaka Klien HTTP Google untuk Java, yang merupakan pustaka yang cepat dan diabstraksi dengan baik untuk mengakses sumber daya apa pun melalui protokol koneksi HTTP.
Fitur utama klien adalah:
- lapisan abstraksi HTTP yang memungkinkan Anda memisahkan pustaka tingkat rendah
- model penguraian JSON dan XML yang cepat, efisien, dan fleksibel dari respons HTTP dan konten permintaan
- penjelasan dan abstraksi yang mudah digunakan untuk pemetaan sumber daya HTTP
Library ini juga dapat digunakan di Java 5 ke atas, menjadikannya pilihan yang tepat untuk project legacy (SE dan EE).
Pada artikel ini, kami akan mengembangkan aplikasi sederhana yang akan terhubung ke GitHub API dan mengambil pengguna , sembari membahas beberapa fitur paling menarik dari pustaka.
2. Ketergantungan Maven
Untuk menggunakan perpustakaan kita membutuhkan ketergantungan google-http-client :
com.google.http-client google-http-client 1.23.0
Versi terbaru dapat ditemukan di Maven Central.
3. Membuat Permintaan Sederhana
Mari kita mulai dengan membuat permintaan GET sederhana ke halaman GitHub untuk menunjukkan bagaimana Klien Google Http bekerja di luar kotak:
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(); HttpRequest request = requestFactory.buildGetRequest( new GenericUrl("//github.com")); String rawResponse = request.execute().parseAsString()
Untuk membuat permintaan yang paling sederhana kita membutuhkan setidaknya:
- HttpRequestFactory ini digunakan untuk membuat permintaan kami
- HttpTransport merupakan abstraksi dari lapisan transport HTTP tingkat rendah
- GenericUrl kelas yang membungkus Url
- HttpRequest menangani eksekusi permintaan yang sebenarnya
Kami akan membahas semua ini dan contoh yang lebih kompleks dengan API aktual yang mengembalikan format JSON di bagian berikut.
4. Transportasi HTTP yang Dapat Dicolokkan
Pustaka memiliki kelas HttpTransport yang diabstraksi dengan baik yang memungkinkan kita membangun di atasnya dan mengubah ke pustaka transportasi HTTP tingkat rendah yang mendasari pilihan :
public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); }
Dalam contoh ini, kami menggunakan NetHttpTransport , yang didasarkan pada HttpURLConnection yang ditemukan di semua Java SDK. Ini adalah pilihan awal yang baik karena terkenal dan dapat diandalkan.
Tentu saja, mungkin ada kasus di mana kita memerlukan beberapa penyesuaian lanjutan, dan dengan demikian persyaratan pustaka tingkat rendah yang lebih kompleks.
Untuk kasus semacam ini, ada ApacheHttpTransport:
public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new ApacheHttpTransport(); }
The ApacheHttpTransport didasarkan pada populer Apache HttpClient yang mencakup berbagai pilihan untuk koneksi configure.
Selain itu, pustaka menyediakan opsi untuk membangun implementasi tingkat rendah Anda, membuatnya sangat fleksibel.
5. Parsing JSON
Klien Http Google menyertakan abstraksi lain untuk penguraian JSON. Keuntungan utama dari ini adalah bahwa pilihan pustaka penguraian tingkat rendah dapat dipertukarkan .
Ada tiga pilihan bawaan, yang semuanya memperluas JsonFactory, dan juga mencakup kemungkinan mengimplementasikan milik kita sendiri.
5.1. Library Parsing yang Dapat Dipertukarkan
Dalam contoh kami, kami akan menggunakan implementasi Jackson2, yang membutuhkan ketergantungan google-http-client-jackson2 :
com.google.http-client google-http-client-jackson2 1.23.0
Setelah ini, kami sekarang dapat menyertakan JsonFactory:
public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); staticJsonFactory JSON_FACTORY = new JacksonFactory(); }
The JacksonFactory adalah perpustakaan tercepat dan paling populer untuk operasi parsing / serialisasi.
Ini datang dengan mengorbankan ukuran perpustakaan (yang bisa menjadi perhatian dalam situasi tertentu). Untuk alasan ini, Google juga menyediakan GsonFactory , yang merupakan implementasi pustaka Google GSON , pustaka parsing JSON yang ringan.
Ada juga kemungkinan menulis implementasi parser tingkat rendah kami.
5.2. @ Anotasi Kunci
Kita dapat menggunakan anotasi @Key untuk menunjukkan bidang yang perlu diurai dari atau diserialkan ke JSON:
public class User { @Key private String login; @Key private long id; @Key("email") private String email; // standard getters and setters }
Di sini kita membuat abstraksi Pengguna , yang kita terima secara batch dari GitHub API (kita akan membahas penguraian sebenarnya nanti di artikel ini) .
Perhatikan bahwa bidang yang tidak memiliki anotasi @Key dianggap internal dan tidak diurai dari atau diserialkan ke JSON . Selain itu, visibilitas bidang tidak menjadi masalah, begitu pula keberadaan metode pengambil atau penyetel.
Kita dapat menentukan nilai anotasi @Key , untuk memetakannya ke kunci JSON yang benar.
5.3. GenericJson
Hanya bidang yang kita deklarasikan, dan tandai sebagai @Key yang diurai.
Untuk mempertahankan konten lainnya, kita dapat mendeklarasikan kelas kita untuk memperluas GenericJson:
public class User extends GenericJson { //... }
GenericJson mengimplementasikan antarmuka Map , yang berarti kita dapat menggunakan metode get dan put untuk menyetel / mendapatkan konten JSON dalam permintaan / respons.
6. Melakukan Panggilan
Untuk terhubung ke endpoint dengan Google Http Client, kita memerlukan HttpRequestFactory , yang akan dikonfigurasi dengan abstraksi sebelumnya HttpTransport dan JsonFactory:
public class GitHubExample { static HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); static JsonFactory JSON_FACTORY = new JacksonFactory(); private static void run() throws Exception { HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory( (HttpRequest request) -> { request.setParser(new JsonObjectParser(JSON_FACTORY)); }); } }
Hal berikutnya yang kita perlukan adalah URL untuk terhubung. Pustaka menangani ini sebagai kelas yang memperluas GenericUrl di mana bidang apa pun yang dideklarasikan diperlakukan sebagai parameter kueri:
public class GitHubUrl extends GenericUrl { public GitHubUrl(String encodedUrl) { super(encodedUrl); } @Key public int per_page; }
Di sini, di GitHubUrl kami , kami mendeklarasikan properti per_page untuk menunjukkan berapa banyak pengguna yang kami inginkan dalam satu panggilan ke GitHub API.
Mari lanjutkan membangun panggilan kita menggunakan GitHubUrl:
private static void run() throws Exception { HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory( (HttpRequest request) -> { request.setParser(new JsonObjectParser(JSON_FACTORY)); }); GitHubUrl url = new GitHubUrl("//api.github.com/users"); url.per_page = 10; HttpRequest request = requestFactory.buildGetRequest(url); Type type = new TypeToken
() {}.getType(); List users = (List)request .execute() .parseAs(type); }
Notice how we specify how many users we'll need for the API call, and then we build the request with the HttpRequestFactory.
Following this, since the GitHub API's response contains a list of users, we need to provide a complex Type, which is a List.
Then, on the last line, we make the call and parse the response to a list of our User class.
7. Custom Headers
One thing we usually do when making an API request is to include some kind of custom header or even a modified one:
HttpHeaders headers = request.getHeaders(); headers.setUserAgent("Baeldung Client"); headers.set("Time-Zone", "Europe/Amsterdam");
We do this by getting the HttpHeaders after we've created our request but before executing it and adding the necessary values.
Please be aware that the Google Http Client includes some headers as special methods. The User-Agent header for example, if we try to include it with just the set method it would throw an error.
8. Exponential Backoff
Another important feature of the Google Http Client is the possibility to retry requests based on certain status codes and thresholds.
We can include our exponential backoff settings right after we've created our request object:
ExponentialBackOff backoff = new ExponentialBackOff.Builder() .setInitialIntervalMillis(500) .setMaxElapsedTimeMillis(900000) .setMaxIntervalMillis(6000) .setMultiplier(1.5) .setRandomizationFactor(0.5) .build(); request.setUnsuccessfulResponseHandler( new HttpBackOffUnsuccessfulResponseHandler(backoff));
Exponential Backoff is turned off by default in HttpRequest, so we must include an instance of HttpUnsuccessfulResponseHandler to the HttpRequest to activate it.
9. Logging
The Google Http Client uses java.util.logging.Logger for logging HTTP request and response details, including URL, headers, and content.
Commonly, logging is managed using a logging.properties file:
handlers = java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = ALL com.google.api.client.http.level = ALL
In our example we use ConsoleHandler, but it's also possible to choose the FileHandler.
The properties file configures the operation of the JDK logging facility. This config file can be specified as a system property:
-Djava.util.logging.config.file=logging.properties
So after setting the file and system property, the library will produce a log like the following:
-------------- REQUEST -------------- GET //api.github.com/users?page=1&per_page=10 Accept-Encoding: gzip User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip) Nov 12, 2017 6:43:15 PM com.google.api.client.http.HttpRequest execute curl -v --compressed -H 'Accept-Encoding: gzip' -H 'User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)' -- '//api.github.com/users?page=1&per_page=10' Nov 12, 2017 6:43:16 PM com.google.api.client.http.HttpResponse -------------- RESPONSE -------------- HTTP/1.1 200 OK Status: 200 OK Transfer-Encoding: chunked Server: GitHub.com Access-Control-Allow-Origin: * ... Link: ; rel="next", ; rel="first" X-GitHub-Request-Id: 8D6A:1B54F:3377D97:3E37B36:5A08DC93 Content-Type: application/json; charset=utf-8 ...
10. Conclusion
In this tutorial, we've shown the Google HTTP Client Library for Java and its more useful features. Their Github contains more information about it as well as the source code of the library.
Seperti biasa, kode sumber lengkap dari tutorial ini tersedia di GitHub.