Introduzione a Jooby

1. Panoramica

Jooby è un micro framework web scalabile e veloce costruito sui server web NIO più utilizzati . È molto semplice e modulare, chiaramente progettato per l'architettura web dei giorni nostri. Viene fornito con il supporto anche per Javascript e Kotlin .

Per impostazione predefinita, Jooby viene fornito con un ottimo supporto per Netty, Jetty e Undertow .

In questo articolo, impareremo la struttura generale del progetto Jooby e come costruire una semplice applicazione web usando Jooby .

2. Architettura dell'applicazione

Di seguito una semplice struttura dell'applicazione Jooby :

├── public | └── welcome.html ├── conf | ├── application.conf | └── logback.xml └── src | ├── main | | └── java | | └── com | | └── baeldung | | └── jooby | | └── App.java | └── test | └── java | └── com | └── baeldung | └── jooby | └── AppTest.java ├── pom.xml

Punto da notare qui è che nella directory pubblica possiamo mettere file statici come css / js / html ecc. Nella directory conf , possiamo mettere qualsiasi file di configurazione di cui un'applicazione ha bisogno come logback.xml o application.conf ecc.

3. Dipendenza da Maven

Possiamo creare una semplice applicazione Jooby aggiungendo la seguente dipendenza nel nostro pom.xml:

 org.jooby jooby-netty 1.1.3 

Se vogliamo scegliere Jetty o Undertow possiamo utilizzare la seguente dipendenza:

 org.jooby jooby-jetty 1.1.3   org.jooby jooby-undertow 1.1.3 

Puoi controllare l'ultima versione del progetto Jooby nel Central Maven Repository.

Jooby ha anche un archetipo Maven dedicato. Possiamo usarlo per creare un progetto di esempio con tutte le dipendenze necessarie predefinite.

Possiamo utilizzare il seguente script per generare il progetto di esempio:

mvn archetype:generate -B -DgroupId=com.baeldung.jooby -DartifactId=jooby -Dversion=1.0 -DarchetypeArtifactId=jooby-archetype -DarchetypeGroupId=org.jooby -DarchetypeVersion=1.1.3

4. Creazione di un'applicazione

4.1. Avvio del server

Per avviare il server incorporato, dobbiamo utilizzare il seguente frammento di codice:

public class App extends Jooby { public static void main(String[] args) { run(App::new, args); } }

Una volta avviato, il server verrà eseguito sulla porta predefinita 8080 .

Possiamo anche configurare il server back-end con porta personalizzata e porta HTTPS personalizzata :

{ port( 8081 ); securePort( 8443 ); }

4.2. Implementazione del router

È molto facile creare un router basato sul percorso in Jooby . Ad esempio, possiamo creare un router per il percorso " / login " nel modo seguente:

{ get( "/login", () -> "Hello from Baeldung"); }

In modo simile, se vogliamo gestire altri metodi HTTP come POST, PUT, ecc., Possiamo usare il frammento di codice seguente:

{ post( "/save", req -> { Mutant token = req.param( "token" ); return token.intValue(); }); }

Qui, stiamo recuperando il token del nome del parametro della richiesta dalla richiesta. Per impostazione predefinita, tutti i params richiesta sono di tipo pressofuso in Jooby s' Mutant tipo di dati. In base alle aspettative, possiamo convertirlo in qualsiasi tipo di dati primitivo supportato.

Possiamo controllare qualsiasi parametro dell'URL nel modo seguente:

{ get( "/user/{id}", req -> "Hello user : " + req.param("id").value() ); get( "/user/:id", req -> "Hello user: " + req.param("id").value() ); }

Possiamo usare uno qualsiasi dei precedenti. È anche possibile trovare parametri che iniziano con un contenuto fisso. Ad esempio, possiamo trovare un parametro URL che inizia con " uid:" nel modo seguente:

{ get( "/uid:{id}", req -> "Hello User with id : uid" + req.param("id").value()); }

4.3. Implementazione del controller di pattern MVC

Per un'applicazione aziendale, Jooby viene fornito con un'API MVC molto simile a qualsiasi altro framework MVC come Spring MVC.

Ad esempio, possiamo gestire un percorso chiamato " / hello ":

@Path("/hello") public class GetController { @GET public String hello() { return "Hello Baeldung"; } }

In modo molto simile possiamo creare un gestore per gestire altri metodi HTTP con annotazioni @POST, @PUT, @DELETE , ecc.

4.4. Gestione del contenuto statico

Per servire qualsiasi contenuto statico come HTML, Javascript, CSS, immagine, ecc., Dobbiamo posizionare quei file nella directory pubblica .

Una volta posizionato, dal router possiamo mappare qualsiasi URL a queste risorse:

{ assets( "/employee" , "form.html" ); }

4.5. Modulo di manipolazione

L' interfaccia di richiesta di Jooby gestisce per impostazione predefinita qualsiasi oggetto modulo senza utilizzare alcun casting di tipo manuale.

Supponiamo di dover inviare i dettagli del dipendente tramite un modulo. Nella prima fase, dobbiamo creare un oggetto bean Employee che useremo per contenere i dati:

public class Employee { String id; String name; String email; // standard constructors, getters and setters }

Ora, dobbiamo creare una pagina per creare il modulo:

Successivamente, creeremo un gestore di post per indirizzare questo modulo e recuperare i dati inviati:

post( "/submitForm", req -> { Employee employee = req.params(Employee.class); // ... return "empoyee data saved successfullly"; });

Punto da notare qui è che dobbiamo dichiarare il form enctype come application / x-www-form-urlencoded per supportare l'associazione dinamica del modulo.

Con Request.file (String filename) possiamo recuperare il file caricato:

post( "/upload", req -> { Upload upload = req.file("file"); // ... upload.close(); });

4.6. Implementazione di un filtro

Fuori dagli schemi , Jooby offre la flessibilità di definire filtri globali e filtri basati sul percorso.

Implementing filter in Jooby is a little bit tricky since we need to configure the URL path twice, once for the filter and once again for the handler.

For example, if we have to implement a filter for a URL path called ‘/filter', we need to implement the filter in this path explicitly:

get( "/filter", ( req, resp, chain ) -> { // ... chain.next( req, resp ); });

The syntax is very similar to Servlet filter. It's possible to restrict the request and send back the response in the filter itself by calling Response.send(Result result) method.

Once the filter is implemented, we need to implement the request handler:

get("/filter", (req, resp) -> { resp.send("filter response"); });

4.7. Session

Jooby comes with two types of session implementation; in-memory and cookie-based.

Implementing in-memory session management is quite simple. We have the options to choose any of the high-throughput session stores available with Jooby like EhCache, Guava, HazleCast, Cassandra, Couchbase, Redis, MongoDB, and Memcached.

For example, to implement a Redis-based session storage, we need to add following Maven dependency:

 org.jooby jooby-jedis 1.1.3 

Now we can use below code snippet to enable session management:

{ use(new Redis()); session(RedisSessionStore.class); get( "/session" , req -> { Session session = req.session(); session.set("token", "value"); return session.get("token").value(); }); }

Point to note here is that we can configure Redis url as the ‘db' property in the application.conf.

To enable cookie based session management, we need to declare cookieSession(). If cookie based approach is selected, we must need to declare application.secret property in the application.conf file. Since each cookie will be signed will be signed with this secret key, it's always advisable to use long random string fragment as a secret key.

In both in-memory and cookie based approach, we must have to declare the necessary configuration parameter in the application.conf file, else the application will throw an IllegalStateException at start up.

5. Testing

Testing MVC route is indeed easy since a route is bound to a strategy for some class. This makes it easy to run unit tests against all routes.

For example, we can quickly create a test-case for default URL:

public class AppTest { @ClassRule public static JoobyRule app = new JoobyRule(new App()); @Test public void given_defaultUrl_expect_fixedString() { get("/").then().assertThat().body(equalTo("Hello World!")) .statusCode(200).contentType("text/html;charset=UTF-8"); } }

Point to note here is that using @ClassRule annotation will create only one instance of the server for all test-cases. If we need to build separate instances of the servers for every test-cases we have to use the @Rule annotation without the static modifier.

We can also use Jooby's MockRouter to test the path in the same way:

@Test public void given_defaultUrl_with_mockrouter_expect_fixedString() throws Throwable { String result = new MockRouter(new App()).get("/"); assertEquals("Hello World!", result); }

6. Conclusion

In this tutorial, we explored the Jooby project and its essential functionality.

Like always, the full source code is available over on GitHub.