Introduction à ActiveWeb

Haut Java

Je viens d'annoncer le nouveau cours Learn Spring , axé sur les principes de base de Spring 5 et Spring Boot 2:

>> VOIR LE COURS

1. Vue d'ensemble

Dans cet article, nous allons illustrer Activeweb - un framework Web full stack de JavaLite - fournissant tout le nécessaire pour le développement d'applications Web dynamiques ou de services Web REST-ful.

2. Concepts et principes de base

Activeweb tire parti de la «convention sur la configuration» - ce qui signifie qu'il est configurable, mais a des valeurs par défaut sensibles et ne nécessite pas de configuration supplémentaire. Nous avons juste besoin de suivre quelques conventions prédéfinies, comme nommer les classes, les méthodes et les champs dans un certain format prédéfini.

Cela simplifie également le développement en recompilant et en rechargeant la source dans le conteneur en cours d'exécution (Jetty par défaut).

Pour la gestion des dépendances, il utilise Google Guice comme framework DI; pour en savoir plus sur Guice, consultez notre guide ici.

3. Configuration de Maven

Pour commencer, ajoutons d'abord les dépendances nécessaires:

 org.javalite activeweb 1.15  

La dernière version peut être trouvée ici.

De plus, pour tester l'application, nous aurons besoin de la dépendance activeweb-testing :

 org.javalite activeweb-testing 1.15 test 

Découvrez la dernière version ici.

4. Structure de l'application

Comme nous l'avons vu, la structure de l'application doit suivre une certaine convention; voici à quoi cela ressemble pour une application MVC typique:

Comme nous pouvons le voir, les contrôleurs , le service , la configuration et les modèles doivent être situés dans leur propre sous-package dans le package d' application .

Les vues doivent être situées dans le répertoire WEB-INF / views , chacune ayant son propre sous-répertoire basé sur le nom du contrôleur. Par exemple, app.controllers.ArticleController doit avoir un article / sous-répertoire contenant tous les fichiers de vue pour ce contrôleur.

Le descripteur de déploiement ou le fichier web.xml doit généralement contenir unet le correspondant . Puisque le framework est un filtre de servlet, au lieu d'unconfiguration il y a une configuration de filtre:

...  dispatcher org.javalite.activeweb.RequestDispatcher ...  ...

Nous avons également besoin d'un root_controller pour définir le contrôleur par défaut de l'application - semblable à un contrôleur domestique :

...  root_controller home  ...

5. Contrôleurs

Les contrôleurs sont les principaux composants d'une application ActiveWeb; et, comme mentionné précédemment, tous les contrôleurs doivent être situés dans le package app.controllers :

public class ArticleController extends AppController { // ... }

Notez que le contrôleur étend org.javalite.activeweb.AppController.

5.1. Mappage d'URL du contrôleur

Les contrôleurs sont automatiquement mappés à une URL en fonction de la convention. Par exemple, ArticleController sera mappé à:

//host:port/contextroot/article

Maintenant, cela leur serait mappé à l'action par défaut par défaut dans le contrôleur. Les actions ne sont rien d'autre que des méthodes à l'intérieur du contrôleur. Nommez la méthode par défaut comme index ():

public class ArticleController extends AppController { // ... public void index() { render("articles"); } // ... }

For other methods or actions append the method name to the URL:

public class ArticleController extends AppController { // ... public void search() { render("search"); } }

The URL:

//host:port/contextroot/article/search

We can even have controller actions based on HTTP methods. Just annotate the method with either of @POST, @PUT, @DELETE, @GET, @HEAD. If we don't annotate an action, it's considered a GET by default.

5.2. Controller URL Resolution

The framework uses controller name and the sub-package name to generate the controller URL. For example app.controllers.ArticleController.java the URL:

//host:port/contextroot/article

If the controller is inside a sub-package, the URL simply becomes:

//host:port/contextroot/baeldung/article

For a controller name having more than a single word (for example app.controllers.PublishedArticleController.java), the URL will get separated using an underscore:

//host:port/contextroot/published_article

5.3. Retrieving Request Parameters

Inside a controller, we get access to the request parameters using the param() or params() methods from the AppController class. The first method takes a String argument – the name of the param to retrieve:

public void search() { String keyword = param("key"); view("search",articleService.search(keyword)); }

And we can use the later to get all parameters if we need to:

public void search() { Map criterion = params(); // ... }

6. Views

In ActiveWeb terminology, views are often referred as templates; this is mostly because it uses Apache FreeMarker template engine instead of JSPs. You can read more about FreeMarker in our guide, here.

Place the templates in WEB-INF/views directory. Every controller should have a sub-directory by its name holding all templates required by it.

6.1. Controller View Mapping

When a controller is hit, the default action index() gets executed and the framework will choose the WEB-INF/views/article/index.ftl template the from views directory for that controller. Similarly, for any other action, the view would be chosen based on the action name.

This isn't always what we would like. Sometimes we might want to return some views based on internal business logic. In this scenario, we can control the process with the render() method from the parent org.javalite.activeweb.AppController class:

public void index() { render("articles"); }

Note that the location of the custom views should also be in the same view directory for that controller. If it is not the case, prefix the template name with the directory name where the template resides and pass it to the render() method:

render("/common/error");

6.3. Views With Data

To send data to the views, the org.javalite.activeweb.AppController provides the view() method:

view("articles", articleService.getArticles());

This takes two params. First, the object name used to access the object in the template and second an object containing the data.

We can also use assign() method to pass data to the views. There is absolutely no difference between view() and assign() methods – we may choose any one of them:

assign("article", articleService.search(keyword));

Let's map the data in the template:

Articles ...  ${article.title}${article.author}${article.words}${article.date}

7. Managing Dependencies

In order to manage objects and instances, ActiveWeb uses Google Guice as a dependency management framework.

Let's say we need a service class in our application; this would separate the business logic from the controllers.

Let's first create a service interface:

public interface ArticleService { List getArticles(); Article search(String keyword); }

And the implementation:

public class ArticleServiceImpl implements ArticleService { public List getArticles() { return fetchArticles(); } public Article search(String keyword) { Article ar = new Article(); ar.set("title", "Article with "+keyword); ar.set("author", "baeldung"); ar.set("words", "1250"); ar.setDate("date", Instant.now()); return ar; } }

Now, let's bind this service as a Guice module:

public class ArticleServiceModule extends AbstractModule { @Override protected void configure() { bind(ArticleService.class).to(ArticleServiceImpl.class) .asEagerSingleton(); } }

Finally, register this in the application context and inject it into the controller, as required:

public class AppBootstrap extends Bootstrap { public void init(AppContext context) { } public Injector getInjector() { return Guice.createInjector(new ArticleServiceModule()); } }

Note that this config class name must be AppBootstrap and it should be located in the app.config package.

Finally, here's how we inject it into the controller:

@Inject private ArticleService articleService;

8. Testing

Unit tests for an ActiveWeb application are written using the JSpec library from JavaLite.

We'll use the org.javalite.activeweb.ControllerSpec class from JSpec to test our controller, and we'll name the test classes following a similar convention:

public class ArticleControllerSpec extends ControllerSpec { // ... }

Notice, that the name is similar to the controller it is testing with a “Spec” at the end.

Here's the test case:

@Test public void whenReturnedArticlesThenCorrect() { request().get("index"); a(responseContent()) .shouldContain("Introduction to Mule"); }

Notice that the request() method simulates the call to the controller, and the corresponding HTTP method get(), takes the action name as an argument.

We can also pass parameters to the controller using the params() method:

@Test public void givenKeywordWhenFoundArticleThenCorrect() { request().param("key", "Java").get("search"); a(responseContent()) .shouldContain("Article with Java"); }

To pass multiple parameters, we can chain method as well, with this fluent API.

9. Deploying the Application

Il est possible de déployer l'application dans n'importe quel conteneur de servlet comme Tomcat, WildFly ou Jetty. Bien sûr, le moyen le plus simple de déployer et de tester serait d'utiliser le plugin Maven Jetty:

...  org.eclipse.jetty jetty-maven-plugin 9.4.8.v20171121  manual 10000   ...

La dernière version du plugin est ici.

Maintenant, enfin - nous pouvons le lancer:

mvn jetty:run

10. Conclusion

Dans cet article, nous avons découvert les concepts et conventions de base du framework ActiveWeb. En plus de ceux-ci, le cadre a plus de fonctionnalités et de capacités que ce dont nous avons discuté ici.

Veuillez consulter la documentation officielle pour plus de détails.

Et, comme toujours, l'exemple de code utilisé dans l'article est disponible à l'adresse over sur GitHub.

Fond Java

Je viens d'annoncer le nouveau cours Learn Spring , axé sur les principes de base de Spring 5 et Spring Boot 2:

>> VOIR LE COURS