Java 11 - HTTP Client i uruchamianie jednoplikowych programów
HTTP Client
W końcu wszedł do biblioteki standardowej (oficjalnie, a nie jako incubator
) porządny klient HTTP. Wcześniej Java posiadała API HttpURLConnection
, która jednak brzydko się zestarzała.
Dlaczego wyrzucamy HttpURLConnection do kosza
HttpURLConnection
był projektowany z myślą o protokołach, które dziś są już praktycznie nie używane (gopher, ftp etc)- API powstało przed HTTP/1.1 i jest zbyt abstrakcyjne
- trudno się go używa, a implementacja przejawia wiele nieudokumentowanych zachowań
- działa wyłącznie w trybie blokującym (na każde żądanie/odpowiedź wykorzystywany jest jeden wątek)
- istniejąca implementacja jest trudna do utrzymania
Jaki będzie nowy HTTP Client?
Cele, jakie przyświecały twórcom nowego kliena HTTP, to przede wszystkim:
- możliwość szybkiego i prostego wykonania najbardziej powszechnych zadań
- musi wspierać standardowe mechanizmy identyfikacyjne (na początek Basic auth)
- łatwe do użycia WebSockets
- wydajność tak dobra lub lepsza niż użycie Jetty bądź Netty
- zużycie pamięci porównywalne bądź niższe niż to w Apache HttpClient, Netty lub Jetty
- możliwość użycia asynchonicznego API pozwalającego na powiadomienie aplikacji o “przybyciu” kolejnego nagłówka czy porcji danych
Co oferują nowe klasy
Na stronie openjdk znajdują się przykłady użycia klasy HTTPClient w kilku użytecznych sytuacjach:
Wywołanie (synchroniczne) żądania GET
|
|
Wysłanie żądania wymaga zawsze podania, jaki BodyHandler
ma obsłużyć odpowiedź serwera. Jest on wywoływany po przybyciu nagłówków i przed nadejściem treści, a jego zadaniem jest stworzenie BodySubscriber
, subscribera (w nomenklaturze reactive-stream), który w sposób nieblokujący przekształci bajty odpowiedzi w typ Javy (np. String albo File).
HTTPResponse.BodyHandlers
oferuje różne typy handlerów: ofString
, ofFile
, ofInputStream
czy ofByteArrayConsumer
.
Ściągnięcie pliku
Poniższy kod ściąga i zapisuje odpowiedź z serwera do pliku:
|
|
Asynchroniczne żądanie GET
Takie żądanie wraca natychmiast, zwracając CompletableFuture
, co pozwala wskazać kod do wykonania asynchronicznego gdy już HttpResponse
będzie dostępny.
|
|
Wysłanie żądania POST
HTTPRequest.BodyPublisher
jest odpowiedzialny za przekształcenie napisu (danych) w bajty wysyłanie w żądaniu POST. BodyPublisher
jest publisherem w rozumieniu reactive-streams i “publikuje” dane umieszczone w body żądania w asynchronicznym strumieniu danych (być może w małych fragmentach, w zależności od rozmiaru danych i możliwoścu back-pressure).
|
|
Wysłanie całej listy żądań i otrzymanie asynchronicznych odpowiedzi:
Wysyłamy całą listę żądań, zgarniamy listę CompletableFuture i czekamy na zakończenie wszystkich:
|
|
To jedynie niektóre z możliwych scenariuszy użycia HttpClient
. Kod klienta http można teraz napisać w czystej Javie bez żadnych zewnętrznych zależności. Jeśli dodamy do tego możliwośc uruchamiania jednoplikowych programów, to okaże się, że w Javie stało się możliwe pisanie prostych skryptów pobierających dane z sieci. Popatrzcie:
Uruchamianie jednoplikowych programów
Nowy tryb uruchomienia
W Javie 10 istniały trzy tryby uruchomienia kodu przez program uruchomieiowy java
:
- uruchomienie klasy
- uruchomienie klasy głównej w jarze
- uruchomienie klasy głównej w module
Java 11 wprowadziła możliwość uruchamiania plików .java bezpośrednio przy użyciu programu java
(do programu java został dodany nowy tryb uruchomienia). Nie trzeba teraz wykonywać (jawnego) etapu kompilacji przy użyciu kompilatora javac
. Wcześniej należało najpierw plik .java skompilować, a dopiero w kolejnym kroku uruchamiać. Tę nową możliwość opisuje JEP-330.
… z wiersza poleceń
- przed Java 11 źródło Simple.java musiało zostać jawnie skompilowane:
|
|
- w Java 11 kompilacja jest niejawna:
|
|
… jako plik wykonywalny
W systemach wywodzących się z Uniksa (MacOS, Linux) istnieje mechanizm wskazania w pliku wykonywalnym, w jego pierwszym wierszu, ścieżki i ew. opcji do programu, do którego zostanie ten plik przekazany do uruchomienia/interpretacji. Można go wykorzystać do utworzenia “skryptów” pisanych w czystej javie. Plik ze źródłem musi jednak spełnić kilka warunków:
- musi być plikiem wykonywalnym, a więc należy nadać plikowi odpowiednie uprawnienia (
chmod +x Simple.java
) - dodać shebang (#!):
- wskazując ścieżkę do binarki java w pierwszym wierszu kodu oraz
- dodając - obowiązkową w tym przypadku - opcję
--source
wskazującą na wersję źródła Javy - zmienić nazwę (plik z pierwszym wierszem rozpoczynającym się od shebang nie może mieć rozszerzenia .java)
|
|
Trzeci powyższy punkt (konieczność zmiany nazwy) jest dość interesujący i wynika z nowego trybu działania programu-launchera (java
): przekaże on do kompilatora treść pliku bez pierwszego wiersza (a więc zawierającą poprawny CompilationUnit) tylko wówczas, gdy pierwszy wiersz będzie wierszem z shebangiem i jednocześnie nie będzie miał standardowego roszerzenia dla pliku źródłowego javy (.java).
Szczegóły: JEP-330: shebang files
Zastosowania
Szczerze mówiąc, nie wyobrażam sobie, aby ktoś powaźnie traktował możliwość pisania skryptów w Javie. Jeśli życie zetknęło kogoś z koniecznością oskryptowania czegokolwiek, to z pewnością był to język powłoki, python lub coś podobnego.
Nowy tryb uruchomienia może być jednak przydatny, głównie dla osób dopero uczących się programowania w Javie. Być może im spodoba się ta nowa możliwość.
Podobne wpisy:
- Java 8 - Mały przykład: przewidywanie kolejnej daty w serii dat i wyznaczenie średniej odległości między datami.
- Java 9 - Praktyczy przykład: trzy moduły
- Java 9 - Czy mogę stworzyć z mojej aplikacji binarkę?
- Java 9 - nowości w bibliotece
- Java 9 - co to jest JShell i dlaczego warto używać REPL-a
- Java 10 - var, nowe metody w klasie Optional, niemodyfikowalne kolekcje
Ten wpis jest częścią serii java.
- 2021-09-12 - Java 18: co nowego? - przegląd JEP-ów
- 2021-21-09 - Java 17 - RandomGenerator i spółka
- 2021-15-09 - Java 17 - co nowego?
- 2021-04-03 - Java 15 - czym są sealed classes?
- 2021-26-02 - Java 13 i 14: Bloki tekstowe i rekordy
- 2021-24-02 - Java 12 - wyrażenie switch (preview feature)
- 2021-23-02 - Java 11 - HTTP Client i uruchamianie jednoplikowych programów
- 2021-18-02 - Java 9 - co to jest JShell i dlaczego warto używać REPL-a w Javie
- 2021-12-02 - Java 10 - var, nowe metody w Optional, kolekcje "unmodifiable"
- 2021-11-02 - Java 9 - nowości w bibliotece
- 2021-10-02 - Java 9: czy mogę stworzyć z mojej aplikacji binarkę?
- 2021-10-02 - Java 9: praktyczny przykład - trzy moduły
- 2021-08-02 - Java 8: praktyczny przykład - przewidywanie kolejnej daty w serii