Creazione di microservizi REST con Javalin

1. Introduzione

Javalin è un framework web leggero scritto per Java e Kotlin. È scritto sopra il server web Jetty, il che lo rende altamente performante. Javalin è modellato da vicino da koa.js, il che significa che è stato scritto da zero per essere semplice da capire e da sviluppare.

In questo tutorial, esamineremo i passaggi della creazione di un microservizio REST di base utilizzando questo framework leggero.

2. Aggiunta di dipendenze

Per creare un'applicazione di base, abbiamo solo bisogno di una dipendenza: Javalin stesso:

 io.javalin javalin 1.6.1 

La versione attuale può essere trovata qui.

3. Configurazione di Javalin

Javalin semplifica la configurazione di un'applicazione di base. Inizieremo definendo la nostra classe principale e impostando una semplice applicazione "Hello World".

Creiamo un nuovo file nel nostro pacchetto di base chiamato JavalinApp.java .

All'interno di questo file, creiamo un metodo principale e aggiungiamo quanto segue per configurare un'applicazione di base:

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

Stiamo creando una nuova istanza di Javalin, facendola ascoltare sulla porta 7000 e quindi avviando l'applicazione.

Stiamo anche configurando il nostro primo endpoint in ascolto di una richiesta GET sull'endpoint / hello .

Eseguiamo questa applicazione e visitiamo // localhost: 7000 / hello per vedere i risultati.

4. Creazione di un UserController

Un esempio "Hello World" è ottimo per introdurre un argomento, ma non è vantaggioso per un'applicazione reale. Esaminiamo ora un caso d'uso più realistico per Javalin.

Innanzitutto, dobbiamo creare un modello dell'oggetto con cui stiamo lavorando. Iniziamo creando un pacchetto chiamato user sotto il progetto root.

Quindi, aggiungiamo una nuova classe utente :

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

Inoltre, dobbiamo impostare il nostro DAO (Data Access Object). Useremo un oggetto in memoria per memorizzare i nostri utenti in questo esempio.

Creiamo una nuova classe nel pacchetto utente chiamata 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()); } }

L'implementazione del nostro DAO come singleton lo rende più facile da usare nell'esempio. Potremmo anche dichiararlo come un membro statico della nostra classe principale o usare l'inserimento di dipendenze da una libreria come Guice se volessimo.

Infine, vogliamo creare la nostra classe controller. Javalin ci permette di essere molto flessibili quando dichiariamo i nostri gestori di rotte, quindi questo è solo un modo per definirli.

Creiamo una nuova classe chiamata UserController.java nel pacchetto utente :

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

Dichiarando i gestori come statici, ci assicuriamo che il controller stesso non abbia uno stato. Ma, in applicazioni più complesse, potremmo voler memorizzare lo stato tra le richieste, nel qual caso avremmo bisogno di rimuovere il modificatore statico.

Si noti inoltre che il test unitario è più difficile con i metodi statici, quindi se vogliamo quel livello di test avremo bisogno di usare metodi non statici.

5. Aggiunta di percorsi

Ora abbiamo diversi modi per recuperare i dati dal nostro modello. L'ultimo passaggio consiste nell'esposizione di questi dati tramite gli endpoint REST. Dobbiamo registrare due nuove rotte nella nostra applicazione principale.

Aggiungiamoli alla nostra classe di applicazione principale:

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

Dopo aver compilato ed eseguito l'applicazione, possiamo fare una richiesta a ciascuno di questi nuovi endpoint. Chiamando // localhost: 7000 / users elencherà tutti gli utenti e chiamando // localhost: 7000 / users / 0 otterrà il singolo oggetto JSON utente con l'ID 0. Ora abbiamo un microservizio che ci consente di recuperare i dati dell'utente .

6. Estensione delle rotte

Il recupero dei dati è un'attività vitale della maggior parte dei microservizi.

Tuttavia, dobbiamo anche essere in grado di memorizzare i dati nel nostro datastore. Javalin fornisce il set completo di gestori di percorso necessari per creare servizi.

Abbiamo visto un esempio di GET sopra, ma sono possibili anche PATCH, POST, DELETE e PUT .

Inoltre, se includiamo Jackson come dipendenza, possiamo analizzare automaticamente i corpi della richiesta JSON nelle nostre classi modello. Per esempio:

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

ci consentirebbe di prendere l' oggetto utente JSON dal corpo della richiesta e tradurlo nell'oggetto modello utente .

7. Conclusione

Possiamo combinare tutte queste tecniche per creare il nostro microservizio.

In questo articolo abbiamo visto come configurare Javalin e creare una semplice applicazione. Abbiamo anche parlato di come utilizzare i diversi tipi di metodi HTTP per consentire ai client di interagire con il nostro servizio.

Per esempi più avanzati di come utilizzare Javalin, assicurati di controllare la documentazione.

Inoltre, come sempre, il codice può essere trovato su GitHub.