Membuat Perkhidmatan Mikro REST dengan Javalin

1. Pengenalan

Javalin adalah kerangka web ringan yang ditulis untuk Java dan Kotlin. Ia ditulis di atas pelayan web Jetty, yang menjadikannya sangat berprestasi. Javalin dimodelkan dari koa.js, yang bermaksud ia ditulis dari bawah hingga mudah difahami dan dibina.

Dalam tutorial ini, kita akan melalui langkah-langkah membina perkhidmatan mikro REST asas menggunakan rangka cahaya ini.

2. Menambah Ketergantungan

Untuk membuat aplikasi asas, kita hanya memerlukan satu pergantungan - Javalin sendiri:

 io.javalin javalin 1.6.1 

Versi semasa boleh didapati di sini.

3. Menubuhkan Javalin

Javalin menjadikan penyediaan aplikasi asas menjadi mudah. Kami akan memulakan dengan menentukan kelas utama kami dan menyediakan aplikasi "Hello World" yang mudah.

Mari buat fail baru dalam pakej asas kami yang bernama JavalinApp.java .

Di dalam fail ini, kami membuat kaedah utama dan menambahkan yang berikut untuk menyediakan aplikasi asas:

Javalin app = Javalin.create() .port(7000) .start(); app.get("/hello", ctx -> ctx.html("Hello, Javalin!"));

Kami sedang membuat contoh baru Javalin, membuatnya mendengarkan di port 7000, dan kemudian memulakan aplikasinya.

Kami juga menyiapkan endpoint pertama kami untuk mendengar permintaan GET di endpoint / hello .

Mari jalankan aplikasi ini dan lawati // localhost: 7000 / hello untuk melihat hasilnya.

4. Membuat Pengawal Pengguna

Contoh "Hello World" bagus untuk memperkenalkan topik, tetapi tidak bermanfaat untuk aplikasi sebenar. Mari lihat kes penggunaan yang lebih realistik untuk Javalin sekarang.

Pertama, kita perlu membuat model objek yang sedang kita bekerjasama. Kami mulakan dengan membuat pakej yang dipanggil pengguna di bawah projek root.

Kemudian, kami menambah kelas Pengguna baru :

public class User { public final int id; public final String name; // constructors }

Kita juga perlu menyediakan objek akses data (DAO) kita. Kami akan menggunakan objek dalam memori untuk menyimpan pengguna kami dalam contoh ini.

Kami membuat kelas baru dalam pakej pengguna yang disebut UserDao.java:

class UserDao { private List users = Arrays.asList( new User(0, "Steve Rogers"), new User(1, "Tony Stark"), new User(2, "Carol Danvers") ); private static UserDao userDao = null; private UserDao() { } static UserDao instance() { if (userDao == null) { userDao = new UserDao(); } return userDao; } Optional getUserById(int id) { return users.stream() .filter(u -> u.id == id) .findAny(); } Iterable getAllUsernames() { return users.stream() .map(user -> user.name) .collect(Collectors.toList()); } }

Melaksanakan DAO kami sebagai singleton menjadikannya lebih mudah digunakan dalam contoh. Kami juga boleh menyatakannya sebagai ahli statik kelas utama kami atau menggunakan suntikan ketergantungan dari perpustakaan seperti Guice jika kami mahu.

Akhirnya, kami ingin membuat kelas pengawal kami. Javalin membolehkan kita menjadi sangat fleksibel ketika kita menyatakan pengendali laluan kita, jadi ini hanya satu cara untuk menentukannya.

Kami membuat kelas baru bernama UserController.java dalam pakej pengguna :

public class UserController { public static Handler fetchAllUsernames = ctx -> { UserDao dao = UserDao.instance(); Iterable allUsers = dao.getAllUsernames(); ctx.json(allUsers); }; public static Handler fetchById = ctx -> { int id = Integer.parseInt(Objects.requireNonNull(ctx.param("id"))); UserDao dao = UserDao.instance(); User user = dao.getUserById(id); if (user == null) { ctx.html("Not Found"); } else { ctx.json(user); } }; }

Dengan menyatakan pengendali sebagai statik, kami memastikan bahawa pengawal itu sendiri tidak mempunyai keadaan. Tetapi, dalam aplikasi yang lebih rumit, kita mungkin ingin menyimpan keadaan antara permintaan, dalam hal ini kita perlu mengeluarkan pengubah statik.

Perhatikan juga bahawa pengujian unit lebih sukar dengan kaedah statik, jadi jika kita menginginkan tahap pengujian itu, kita perlu menggunakan kaedah bukan statik.

5. Menambah Laluan

Kami kini mempunyai pelbagai cara untuk mengambil data dari model kami. Langkah terakhir adalah untuk mendedahkan data ini melalui titik akhir REST. Kita perlu mendaftarkan dua laluan baru dalam aplikasi utama kita.

Mari tambahkan mereka ke kelas aplikasi utama kami:

app.get("/users", UserController.fetchAllUsernames); app.get("/users/:id", UserController.fetchById);

After compiling and running the application, we can make a request to each of these new endpoints. Calling //localhost:7000/users will list all users and calling //localhost:7000/users/0 will get the single User JSON object with the id 0. We now have a microservice that allows us to retrieve User data.

6. Extending Routes

Retrieving data is a vital task of most microservices.

However, we also need to be able to store data in our datastore. Javalin provides the full set of path handlers that are required to build services.

We saw an example of GET above, but PATCH, POST, DELETE, and PUT are possible as well.

Also, if we include Jackson as a dependency, we can parse JSON request bodies automatically into our model classes. For instance:

app.post("/") { ctx -> User user = ctx.bodyAsClass(User.class); }

akan membolehkan kita mengambil objek Pengguna JSON dari badan permintaan dan menerjemahkannya ke dalam objek Model pengguna .

7. Kesimpulannya

Kita boleh menggabungkan semua teknik ini untuk membuat perkhidmatan mikro kita.

Dalam artikel ini, kami melihat cara menyiapkan Javalin dan membina aplikasi mudah. Kami juga membincangkan cara menggunakan pelbagai jenis kaedah HTTP untuk membolehkan pelanggan berinteraksi dengan perkhidmatan kami.

Untuk contoh yang lebih maju mengenai cara menggunakan Javalin, pastikan untuk melihat dokumentasinya.

Juga, seperti biasa, kodnya boleh didapati di GitHub.