Pengenalan HTTP Akka

1. Gambaran keseluruhan

Dalam tutorial ini, dengan bantuan model Akka & Stream Akka, kita akan belajar bagaimana mengatur Akka untuk membuat API HTTP yang menyediakan operasi CRUD asas.

2. Pergantungan Maven

Untuk memulakan, mari kita lihat kebergantungan yang diperlukan untuk mula bekerja dengan Akka HTTP:

 com.typesafe.akka akka-http_2.12 10.0.11   com.typesafe.akka akka-stream_2.12 2.5.11   com.typesafe.akka akka-http-jackson_2.12 10.0.11   com.typesafe.akka akka-http-testkit_2.12 10.0.11 test 

Sudah tentu kita dapat mencari versi terbaru perpustakaan Akka ini di Maven Central.

3. Menciptakan Pelakon

Sebagai contoh, kami akan membina API HTTP yang membolehkan kami mengurus sumber pengguna. API akan menyokong dua operasi:

  • mencipta pengguna baru
  • memuatkan pengguna yang ada

Sebelum kita dapat menyediakan API HTTP, kita perlu menerapkan pelaku yang menyediakan operasi yang kita perlukan:

class UserActor extends AbstractActor { private UserService userService = new UserService(); static Props props() { return Props.create(UserActor.class); } @Override public Receive createReceive() { return receiveBuilder() .match(CreateUserMessage.class, handleCreateUser()) .match(GetUserMessage.class, handleGetUser()) .build(); } private FI.UnitApply handleCreateUser() { return createUserMessage -> { userService.createUser(createUserMessage.getUser()); sender() .tell(new ActionPerformed( String.format("User %s created.", createUserMessage.getUser().getName())), getSelf()); }; } private FI.UnitApply handleGetUser() { return getUserMessage -> { sender().tell(userService.getUser(getUserMessage.getUserId()), getSelf()); }; } }

Pada asasnya, kami memperluas kelas AbstractActor dan menerapkan kaedah createReceive () .

Dalam createReceive () , kami memetakan jenis mesej masuk ke kaedah yang menangani mesej dari jenis masing-masing.

Jenis mesej adalah kelas wadah bersiri mudah dengan beberapa medan yang menggambarkan operasi tertentu . GetUserMessage dan mempunyai satu medan id pengguna untuk mengenalpasti pengguna untuk beban. CreateUserMessage mengandungi objek Pengguna dengan data pengguna yang kita perlukan untuk membuat pengguna baru.

Kemudian, kita akan melihat cara menerjemahkan permintaan HTTP masuk ke dalam mesej ini.

Pada akhirnya, kami mendelegasikan semua mesej ke contoh UserService , yang menyediakan logik perniagaan yang diperlukan untuk menguruskan objek pengguna yang berterusan.

Juga, perhatikan kaedah alat peraga () . Walaupun kaedah props () tidak diperlukan untuk memperluas AbstractActor , kaedah ini akan berguna kemudian semasa membuat ActorSystem .

Untuk perbincangan yang lebih mendalam mengenai pelakon, lihat pengenalan kami kepada Akka Actors.

4. Menentukan Laluan HTTP

Memiliki pelakon yang melakukan kerja sebenarnya, kita hanya perlu menyediakan API HTTP yang mendelegasikan permintaan HTTP masuk kepada pelakon kita.

Akka menggunakan konsep laluan untuk menerangkan API HTTP. Untuk setiap operasi, kami memerlukan laluan.

Untuk membuat pelayan HTTP, kami melanjutkan kelas kerangka HttpApp dan menerapkan kaedah laluan :

class UserServer extends HttpApp { private final ActorRef userActor; Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS)); UserServer(ActorRef userActor) { this.userActor = userActor; } @Override public Route routes() { return path("users", this::postUser) .orElse(path(segment("users").slash(longSegment()), id -> route(getUser(id)))); } private Route getUser(Long id) { return get(() -> { CompletionStage
    
      user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout) .thenApply(obj -> (Optional) obj); return onSuccess(() -> user, performed -> { if (performed.isPresent()) return complete(StatusCodes.OK, performed.get(), Jackson.marshaller()); else return complete(StatusCodes.NOT_FOUND); }); }); } private Route postUser() { return route(post(() -> entity(Jackson.unmarshaller(User.class), user -> { CompletionStage userCreated = PatternsCS.ask(userActor, new CreateUserMessage(user), timeout) .thenApply(obj -> (ActionPerformed) obj); return onSuccess(() -> userCreated, performed -> { return complete(StatusCodes.CREATED, performed, Jackson.marshaller()); }); }))); } } 
    

Sekarang, terdapat cukup banyak papan pemanas di sini, tetapi perhatikan bahawa kami mengikuti corak yang sama seperti sebelum operasi pemetaan, kali ini sebagai laluan. Mari pecahkan sedikit.

Dalam getUser () , kami hanya membungkus id pengguna masuk dalam mesej jenis GetUserMessage dan meneruskan mesej itu ke userActor kami .

Setelah pelakon memproses mesej, pengendali onSuccess dipanggil, di mana kami menyelesaikan permintaan HTTP dengan menghantar respons dengan status HTTP tertentu dan badan JSON tertentu. Kami menggunakan Jackson marshaller untuk menyusun jawapan yang diberikan oleh pelakon itu menjadi rentetan JSON.

Dalam postUser () , kami melakukan perkara yang sedikit berbeza, kerana kami mengharapkan badan JSON dalam permintaan HTTP. Kami menggunakan kaedah entiti () untuk memetakan badan JSON masuk ke objek Pengguna sebelum membungkusnya ke dalam CreateUserMessage dan meneruskannya kepada pelakon kami. Sekali lagi, kami menggunakan Jackson untuk memetakan antara Java dan JSON dan sebaliknya.

Oleh kerana HttpApp mengharapkan kami untuk menyediakan satu objek Laluan , kami menggabungkan kedua-dua laluan menjadi satu dalam satu kaedah laluan . Di sini, kami menggunakan arahan jalan untuk akhirnya memberikan laluan URL di mana API kami harus tersedia.

Kami mengikat laluan yang disediakan oleh postUser () ke laluan / pengguna . Sekiranya permintaan masuk bukan permintaan POST, Akka akan masuk ke cawangan orElse secara automatik dan mengharapkan jalan menjadi / users / dan kaedah HTTP akan DAPATKAN.

Sekiranya kaedah HTTP GET, permintaan akan diteruskan ke laluan getUser () . Sekiranya pengguna tidak ada, Akka akan mengembalikan status HTTP 404 (Tidak Ditemui). Sekiranya kaedah itu bukan POST atau GET, Akka akan mengembalikan status HTTP 405 (Kaedah Tidak Dibolehkan).

Untuk maklumat lebih lanjut mengenai cara menentukan laluan HTTP dengan Akka, lihat dokumen Akka.

5. Memulakan Pelayan

Setelah kami membuat implementasi HttpApp seperti di atas, kami dapat memulakan pelayan HTTP kami dengan beberapa baris kod:

public static void main(String[] args) throws Exception { ActorSystem system = ActorSystem.create("userServer"); ActorRef userActor = system.actorOf(UserActor.props(), "userActor"); UserServer server = new UserServer(userActor); server.startServer("localhost", 8080, system); }

Kami hanya membuat ActorSystem dengan pelakon tunggal jenis UserActor dan memulakan pelayan di localhost .

6. Kesimpulannya

Dalam artikel ini, kami telah mempelajari asas-asas Akka HTTP dengan contoh yang menunjukkan cara menyiapkan pelayan HTTP dan mengekspos titik akhir untuk membuat dan memuat sumber, serupa dengan REST API.

Seperti biasa, kod sumber yang disajikan di sini boleh didapati di GitHub.