Створення REST Microservices з Javalin

1. Вступ

Javalin - це легкий веб-фреймворк, написаний для Java та Kotlin. Він написаний поверх веб-сервера Jetty, що робить його високопродуктивним. Javalin точно моделюється з koa.js, а це означає, що він написаний з нуля, щоб бути простим для розуміння та вдосконалення.

У цьому підручнику ми пройдемо кроки побудови базового мікросервісу REST за допомогою цієї легкої основи.

2. Додавання залежностей

Щоб створити базовий додаток, нам потрібна лише одна залежність - сам Явалін:

 io.javalin javalin 1.6.1 

Поточну версію можна знайти тут.

3. Налаштування Javalin

Javalin полегшує створення базової програми. Ми почнемо з визначення нашого основного класу та налаштування простої програми “Hello World”.

Давайте створимо новий файл у нашому базовому пакеті під назвою JavalinApp.java .

Усередині цього файлу ми створюємо основний метод і додаємо наступний для налаштування базової програми:

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

Ми створюємо новий екземпляр Javalin, робимо його прослуховуванням через порт 7000, а потім запускаємо програму.

Ми також встановлюємо нашу першу кінцеву точку, що прослуховує запит GET, у кінцевій точці / hello .

Давайте запустимо цю програму та відвідаємо // localhost: 7000 / привіт, щоб побачити результати.

4. Створення UserController

Приклад “Hello World” чудово підходить для введення теми, але він не вигідний для реальних додатків. Давайте розглянемо більш реалістичний випадок використання Жаваліна зараз.

По-перше, нам потрібно створити модель об’єкта, з яким ми працюємо. Ми починаємо зі створення пакета під назвою user під кореневим проектом.

Потім ми додаємо новий клас User :

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

Крім того, нам потрібно налаштувати наш об’єкт доступу до даних (DAO). У цьому прикладі ми будемо використовувати об’єкт в пам’яті для зберігання наших користувачів.

Ми створюємо новий клас в пакеті користувача, який називається 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()); } }

Впровадження нашого DAO як єдиного елемента полегшує використання у прикладі. Ми також могли б оголосити його статичним членом нашого основного класу або скористатися ін’єкцією залежностей із такої бібліотеки, як Guice.

Нарешті, ми хочемо створити наш клас контролера. Javalin дозволяє нам бути дуже гнучкими, коли ми оголошуємо наші обробники маршрутів, тому це лише один із способів їх визначення.

Ми створюємо новий клас під назвою UserController.java в користувацькому пакеті:

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); } }; }

Оголошуючи обробники як статичні, ми гарантуємо, що сам контролер не має стану. Але в більш складних додатках ми можемо захотіти зберігати стан між запитами, і в цьому випадку нам потрібно буде видалити статичний модифікатор.

Також зауважте, що модульне тестування складніше із статичними методами, тому, якщо ми хочемо такий рівень тестування, нам потрібно буде використовувати нестатичні методи.

5. Додавання маршрутів

Зараз у нас є кілька способів отримання даних із нашої моделі. Останній крок - виставити ці дані через кінцеві точки REST. Нам потрібно зареєструвати два нових маршрути в основному додатку.

Давайте додамо їх до нашого основного класу додатків:

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

Після компіляції та запуску програми ми можемо зробити запит до кожної з цих нових кінцевих точок. Виклик // localhost: 7000 / users перерахує всіх користувачів, а виклик // localhost: 7000 / users / 0 отримає єдиний об'єкт JSON User з ідентифікатором 0. Тепер у нас є мікросервіс, який дозволяє нам отримувати дані користувача .

6. Розширення маршрутів

Отримання даних є життєво важливим завданням більшості мікросервісів.

Однак нам також потрібно мати можливість зберігати дані у нашому сховищі даних. Javalin надає повний набір обробників шляхів, необхідних для побудови служб.

Вище ми бачили приклад GET , але можливі також PATCH, POST, DELETE та PUT .

Крім того, якщо ми включимо Джексона як залежність, ми можемо автоматично проаналізувати тіла запитів JSON у наші класи моделей. Наприклад:

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

дозволить нам захопити об’єкт JSON User із тіла запиту та перевести його в об’єкт User User .

7. Висновок

Ми можемо поєднати всі ці методи, щоб зробити наш мікросервіс.

У цій статті ми побачили, як налаштувати Javalin та створити простий додаток. Ми також поговорили про те, як використовувати різні типи методів HTTP, щоб дозволити клієнтам взаємодіяти з нашою службою.

Щоб отримати більш досконалі приклади використання Javalin, обов’язково ознайомтеся з документацією.

Крім того, як завжди, код можна знайти на GitHub.