Un guide sur le modèle de contrôleur frontal en Java

1. Vue d'ensemble

Dans ce didacticiel, nous allons approfondir le modèle de contrôleur frontal , qui fait partie des modèles d'entreprise définis dans le livre de Martin Fowler «Patterns of Enterprise Application Architecture».

Le contrôleur frontal est défini comme «un contrôleur qui gère toutes les demandes d'un site Web». Il se tient devant une application Web et délègue les demandes aux ressources suivantes. Il fournit également une interface pour des comportements courants tels que la sécurité, l'internationalisation et la présentation de vues particulières à certains utilisateurs.

Cela permet à une application de modifier son comportement lors de l'exécution. De plus, il aide à lire et à maintenir une application en empêchant la duplication de code.

Le contrôleur frontal consolide toute la gestion des demandes en canalisant les demandes via un seul objet gestionnaire.

2. Comment ça marche?

Le motif du contrôleur avant est principalement divisé en deux parties. Un seul contrôleur de répartition et une hiérarchie de commandes. L'UML suivant décrit les relations de classe d'une implémentation générique de Front Controller:

Ce contrôleur unique distribue les requêtes aux commandes afin de déclencher le comportement associé à une requête.

Pour démontrer son implémentation, nous implémenterons le contrôleur dans un FrontControllerServlet et des commandes en tant que classes héritées d'un FrontCommand abstrait .

3. Configuration

3.1. Dépendances de Maven

Tout d'abord, nous allons configurer un nouveau projet Maven WAR avec javax.servlet-api inclus:

 javax.servlet javax.servlet-api 4.0.0-b01 provided  

ainsi que jetty-maven-plugin :

 org.eclipse.jetty jetty-maven-plugin 9.4.0.M1   /front-controller   

3.2. Modèle

Ensuite, nous définirons une classe Model et un référentiel modèle . Nous utiliserons la classe Book suivante comme modèle:

public class Book { private String author; private String title; private Double price; // standard constructors, getters and setters }

Ce sera le référentiel, vous pouvez rechercher le code source pour une implémentation concrète ou en fournir un par vous-même:

public interface Bookshelf { default void init() { add(new Book("Wilson, Robert Anton & Shea, Robert", "Illuminati", 9.99)); add(new Book("Fowler, Martin", "Patterns of Enterprise Application Architecture", 27.88)); } Bookshelf getInstance();  boolean add(E book); Book findByTitle(String title); }

3.3. FrontControllerServlet

L'implémentation du Servlet lui-même est assez simple. Nous extrayons le nom de la commande d'une requête, créons dynamiquement une nouvelle instance d'une classe de commande et l'exécutons.

Cela nous permet d'ajouter de nouvelles commandes sans changer une base de code de notre contrôleur frontal .

Une autre option consiste à implémenter le servlet en utilisant une logique conditionnelle statique. Cela présente l'avantage de vérifier les erreurs lors de la compilation:

public class FrontControllerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { FrontCommand command = getCommand(request); command.init(getServletContext(), request, response); command.process(); } private FrontCommand getCommand(HttpServletRequest request) { try { Class type = Class.forName(String.format( "com.baeldung.enterprise.patterns.front." + "controller.commands.%sCommand", request.getParameter("command"))); return (FrontCommand) type .asSubclass(FrontCommand.class) .newInstance(); } catch (Exception e) { return new UnknownCommand(); } } }

3.4. FrontCommand

Implémentons une classe abstraite appelée FrontCommand , qui contient le comportement commun à toutes les commandes.

Cette classe a accès au ServletContext et à ses objets de requête et de réponse. De plus, il gérera la résolution de la vue:

public abstract class FrontCommand { protected ServletContext context; protected HttpServletRequest request; protected HttpServletResponse response; public void init( ServletContext servletContext, HttpServletRequest servletRequest, HttpServletResponse servletResponse) { this.context = servletContext; this.request = servletRequest; this.response = servletResponse; } public abstract void process() throws ServletException, IOException; protected void forward(String target) throws ServletException, IOException { target = String.format("/WEB-INF/jsp/%s.jsp", target); RequestDispatcher dispatcher = context.getRequestDispatcher(target); dispatcher.forward(request, response); } }

Une implémentation concrète de ce FrontCommand abstrait serait un SearchCommand . Cela inclura la logique conditionnelle pour les cas où un livre a été trouvé ou lorsque le livre est manquant:

public class SearchCommand extends FrontCommand { @Override public void process() throws ServletException, IOException { Book book = new BookshelfImpl().getInstance() .findByTitle(request.getParameter("title")); if (book != null) { request.setAttribute("book", book); forward("book-found"); } else { forward("book-notfound"); } } }

Si l'application est en cours d'exécution, nous pouvons accéder à cette commande en pointant notre navigateur sur // localhost: 8080 / front-controller /? Command = Search & title = patterns.

Le SearchCommand résout en deux vues, la deuxième vue peut être testée avec la requête suivante // localhost: 8080 / front-controller /? Command = Search & title = any-title.

Pour arrondir notre scénario, nous allons implémenter une deuxième commande, qui est déclenchée comme solution de secours dans tous les cas, une demande de commande est inconnue du servlet:

public class UnknownCommand extends FrontCommand { @Override public void process() throws ServletException, IOException { forward("unknown"); } }

Cette vue sera accessible à // localhost: 8080 / front-controller /? Command = Order & title = any-title ou en omettant complètement les paramètres d' URL .

4. Déploiement

Comme nous avons décidé de créer un projet de fichier WAR , nous aurons besoin d'un descripteur de déploiement Web. Avec ce fichier web.xml, nous pouvons exécuter notre application Web dans n'importe quel conteneur de servlet:

   front-controller  com.baeldung.enterprise.patterns.front.controller.FrontControllerServlet    front-controller /  

Comme dernière étape, nous exécuterons «mvn install jetty: run» et inspecterons nos vues dans un navigateur.

5. Conclusion

Comme nous l'avons vu jusqu'à présent, nous devons maintenant nous familiariser avec le modèle de contrôleur frontal et son implémentation en tant que servlet et hiérarchie de commandes.

Comme d'habitude, vous trouverez les sources sur GitHub.