CodeGym/Blog Java/Random-FR/Créer une application Web simple à l'aide de servlets et ...
John Squirrels
Niveau 41
San Francisco

Créer une application Web simple à l'aide de servlets et de JSP (partie 2)

Publié dans le groupe Random-FR
membres
Créer une application web simple à l'aide de servlets et de JSP (partie 1) Connaissances nécessaires à la compréhension de l'article : Vous avez déjà plus ou moins compris Java Core et aimeriez vous intéresser aux technologies JavaEE et à la programmation web. Il serait plus logique que vous étudiiez actuellement la quête Java Collections, qui traite de sujets proches de l'article.
Créer une application Web simple à l'aide de servlets et de JSP (partie 2) - 1

Création d'entités

Dans le package d'entités , nous allons créer une Userclasse qui a deux variables de chaîne privées : name et password . Créez des constructeurs (par défaut et un qui prend les deux valeurs) et des getters/setters, et remplacez la toString()méthode au cas où, avec les méthodes equals()et hashCode(). En d'autres termes, nous ferons tout ce qu'un développeur Java respectable fait lors de la création d'une classe.
public class User {
    private String name;
    private String password;

    public User() {
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (name != null ? !name.equals(user.name) : user.name != null) return false;
        return password != null ? password.equals(user.password) : user.password == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (password != null ? password.hashCode() : 0);
        return result;
    }
}
Nous pouvons maintenant commencer à créer une liste d'utilisateurs. Nous y ajouterons des utilisateurs et en retirerons des utilisateurs pour les afficher. Cependant, nous avons un problème. Nous ne créons pas nos objets servlet. Tomcat le fait pour nous. Les méthodes que nous y redéfinissons sont déjà définies pour nous, et nous ne pouvons pas les paramétrer. Comment créer alors une liste partagée qui sera visible dans nos deux servlets ? Si nous créons simplement un objet de liste dans chaque servlet, nous ajouterions des utilisateurs à une liste, mais afficherions les utilisateurs d'une autre dans le ListServlet. Nous avons donc besoin d'un objet partagé par les deux servlets. De manière générale, nous avons besoin d'un objet partagé par toutes les classes de notre programme : un objet pour tout le programme. J'espère que vous avez entendu parler des modèles de conception. Pour certaines personnes, cela peut être le premier véritable besoin du modèle Singleton dans leur programme. Vous pourriez devenir farfelu et créer un joli Singleton avec des doubles vérifications et une synchronisation (oui, notre application est multithread, puisque les servlets Tomcat s'exécutent sur des threads séparés). Mais je vais utiliser la technique d'initialisation précoce, car elle est tout à fait adéquate pour nos besoins ici.

Création d'un modèle

Créez une classe (et implémentez le modèle Singleton ) dans le package de modèle et appelez-la quelque chose d'inhabituel. Par exemple, Modèle . Nous allons créer une liste privée d'utilisateurs dans notre classe et implémenter deux méthodes : une pour ajouter un utilisateur et une autre pour renvoyer une liste de chaînes (noms d'utilisateur). Étant donné que notre objet utilisateur se compose d'un nom d'utilisateur et d'un mot de passe, et que nous ne voulons pas révéler les mots de passe des utilisateurs, nous n'aurons qu'une liste de noms.
public class Model {
    private static Model instance = new Model();

    private List<User> model;

    public static Model getInstance() {
        return instance;
    }

    private Model() {
        model = new ArrayList<>();
    }

    public void add(User user) {
        model.add(user);
    }

    public List<String> list() {
        return model.stream()
                .map(User::getName)
                .collect(Collectors.toList());
    }
}

Un peu sur MVC

Puisque vous avez déjà entendu parler de singleton , vous avez probablement entendu parler d'un autre modèle de conception modèle-vue-contrôleur (MVC). Son but est de séparer la logique métier de la vue. Autrement dit, pour séparer le code qui détermine ce qu'il faut faire du code qui détermine comment afficher les choses. La vue est responsable de la façon dont les données sont présentées. Dans notre cas, les vues sont nos pages JSP . C'est précisément pourquoi je les ai mis dans un dossier nommé views . Le modèle est constitué des données avec lesquelles le programme fonctionne réellement. Dans notre cas, il s'agit des utilisateurs (liste des utilisateurs). Et les contrôleurs sont le lien entre eux. Ils prennent les données du modèle et les transmettent aux vues (ou obtiennent des données de Tomcat, traitez-le et transmettez-le au modèle). Vous définissez votre logique métier (ce que le programme doit faire) en eux, pas dans le modèle ou la vue. Ainsi, chaque partie gère ses propres affaires :
  • le modèle stocke des données ;
  • les vues rendent de belles représentations des données ;
  • les contrôleurs gèrent le traitement des données.
Cela permet au programme d'être assez simple et maintenable, plutôt qu'un tas monstrueux de tout le code dans une classe. MVC n'est pas seulement adapté à la programmation Web, mais il est utilisé particulièrement souvent dans ce domaine (presque toujours). Dans notre cas, les servlets agiront en tant que contrôleurs. Il s'agit d'une description très superficielle et brève du modèle, mais MVC n'est pas le sujet principal de cet article. Si quelqu'un veut en savoir plus, Google est votre ami ! Créez un formulaire pour ajouter un utilisateur. Ajoutez le formulaire à add.jsp . Il doit consister en deux champs de saisie de texte (l'un ordinaire, l'autre — un champ de mot de passe) et un bouton pour envoyer les données au serveur.
<form method="post">
    <label>Name:
        <input type="text" name="name"><br />
    </label>

    <label>Password:
        <input type="password" name="pass"><br />
    </label>
    <button type="submit">Submit</button>
</form>
Ici, le formulaire a un attribut method avec la valeur post . Cela indique que les données de ce formulaire iront au serveur en tant que requête POST . L' attribut action n'est pas spécifié, ce qui signifie que la demande sera envoyée à la même adresse que celle à partir de laquelle nous sommes arrivés sur cette page ( /add ). Ainsi, lors de la réception d'une requête GET , notre servlet liée à cette adresse renvoie la JSP avec le formulaire add-user. Et s'il reçoit une requête POST , alors nous savons que le formulaire a envoyé ses données ici (que nous extrayons de l'objet de requête dans ledoPost()méthode, processus et transmission au modèle pour enregistrement). Il convient de noter que les champs de saisie ont un paramètre appelé name (pour les noms d'utilisateur ou pass pour les mots de passe). C'est un point très important. Ainsi, pour recevoir ces données (le nom d'utilisateur et le mot de passe qui seront saisis) de la requête (à l'intérieur de la servlet), nous utiliserons ces champs name et pass . Mais plus là-dessus plus tard. Mon bouton d'envoi de données a de nouveau été conçu comme un bouton , et non comme un champ de sortie comme il est d'usage. Je ne sais pas à quel point cette approche est largement adoptée, mais cela fonctionne pour moi (navigateur Chrome).

Traitement par servlet des requêtes POST

Revenons au AddServlet . Je vous rappelle que pour permettre à notre servlet de "capturer" les requêtes GET , nous avons remplacé la doGet()méthode dans la classe HttpServlet . Pour apprendre à notre servlet à intercepter également les requêtes POST , nous devons également remplacer la doPost()méthode. Tomcat lui transmet des objets de requête et de réponse similaires avec lesquels nous travaillerons. Pour commencer, extrayez le nom de la requête et transmettez les paramètres envoyés par le formulaire (si vous avez spécifié des noms différents dans le formulaire, utilisez ces noms). Après cela, créez un objet utilisateur à l'aide des données reçues. Ensuite, nous obtenons l'objet modèle et ajoutons l'utilisateur créé au modèle.
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    String password = req.getParameter("pass");
    User user = new User(name, password);
    Model model = Model.getInstance();
    model.add(user);
}

Passer des données à la vue

Passons au ListServlet . La doGet()méthode est déjà implémentée. Il transfère simplement le contrôle à la vue ( list.jsp ). Si vous ne l'avez pas encore, créez-le par analogie avec la méthode dans le AddServlet . Maintenant, ce serait bien d'obtenir la liste des noms d'utilisateur du modèle et de les transmettre à la vue, qui les recevra et les affichera magnifiquement. Pour ce faire, nous utiliserons à nouveau l'objet de requête que nous avons reçu de Tomcat . Nous pouvons ajouter un attribut à cet objet, en lui donnant une sorte de nom. En fait, nous pouvons ajouter l'objet que nous voulons passer à la vue. En raison du fait que lors du transfert du contrôle de la servlet à la vue, nous transmettons à la vue les mêmes objets de requête et de réponse que la servlet a reçus, nous pouvons ajouter notre liste de noms à l'objet de requête, puis obtenir notre liste de noms d'utilisateur à partir de la requête objet dans la vue. Nous en avons terminé avec la classe ListServlet , je vais donc présenter le code de la classe entière ici :
package app.servlets;

import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class ListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Model model = Model.getInstance();
        List<String> names = model.list();
        req.setAttribute("userNames", names);

        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp");
        requestDispatcher.forward(req, resp);
    }
}

Exécution de code Java dans des fichiers JSP

Il est temps de regarder list.jsp . Il ne sera exécuté que lorsque ListServlet lui transférera le contrôle. De plus, nous avons déjà préparé la liste des noms d'utilisateur du modèle dans le servlet et l'avons transmise ici dans l'objet de requête. Puisque nous avons la liste des noms, nous pouvons la parcourir en utilisant une forboucle et afficher chaque nom. Comme je l'ai déjà dit, les fichiers JSP peuvent exécuter du code Java (ce qui les différencie des pages HTML statiques). Pour exécuter du code, il suffit de placer la construction suivante à l'endroit approprié :
<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
Au sein de ce construit, nous accédons à plusieurs variables :
  • request — notre objet de requête, que nous avons transmis depuis la servlet, où il s'appelait simplement req ;
  • réponse — l'objet de réponse (appelé resp dans la servlet) ;
  • out — un objet JspWriter (qui hérite d'un Writer ordinaire ), que nous pouvons utiliser pour "écrire" quelque chose directement dans la page HTML elle-même. L'instruction out.println("Hello, World!") est très similaire à System.out.println("Hello, World!") , mais ne les confondez pas !
  • out.println() "écrit" dans une page HTML , tandis que System.out.println écrit dans le flux de sortie du système . Si vous appelez System.out.println() dans une section JSP avec du code Java , vous verrez les résultats dans la console Tomcat , mais pas sur la page.
Vous pouvez rechercher d'autres objets disponibles dans une JSP ici . Nous pouvons utiliser l' objet request pour obtenir la liste des noms transmis par la servlet (nous avons attaché l'attribut correspondant à cet objet), et nous utilisons l' objet out pour afficher ces noms. Affichons-les (pour l'instant, sous la forme d'une simple liste HTML) :
<ul>
    <%
        List<String> names = (List<String>) request.getAttribute("userNames");

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
Si nous devons afficher la liste uniquement s'il y a des utilisateurs, et sinon afficher un avertissement qu'il n'y a pas encore d'utilisateurs, alors nous pouvons réécrire un peu cette section :
<%
    List<String> names = (List<String>) request.getAttribute("userNames");

    if (names != null && !names.isEmpty()) {
        out.println("<ui>");
        for (String s : names) {
            out.println("<li>" + s + "</li>");
        }
        out.println("</ui>");
    } else out.println("<p>There are no users yet!</p>");
%>
Maintenant que nous savons comment transmettre les données des servlets aux vues, nous pouvons améliorer notre AddServlet afin qu'il affiche une notification sur l'ajout réussi d'un utilisateur. Pour ce faire, dans la doPost()méthode, après avoir ajouté un nouvel utilisateur au modèle, nous pouvons ajouter ce nom d'utilisateur aux attributs de l'objet req et redonner le contrôle à une vue ( add.jsp ). Et maintenant, nous allons y ajouter une section avec du code Java, où nous vérifierons si la requête a un tel attribut, et si c'est le cas, nous afficherons alors un message indiquant que l'utilisateur a été ajouté avec succès. Après ces modifications, le code complet de AddServlet ressemblera à ceci :
package app.servlets;

import app.entities.User;
import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
        requestDispatcher.forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String password = req.getParameter("pass");
        User user = new User(name, password);
        Model model = Model.getInstance();
        model.add(user);

        req.setAttribute("userName", name);
        doGet(req, resp);
    }
}
Ici, à la fin de la doPost()méthode, nous créons un attribut avec le nom de l'utilisateur qui a été ajouté au modèle, puis appelons la doGet()méthode, à laquelle nous transmettons la requête et la réponse en cours. La doGet()méthode transfère maintenant le contrôle à la vue, qui reçoit également l'objet de requête avec le nom de l'utilisateur ajouté attaché en tant qu'attribut. Ce qu'il nous reste à faire est de corriger add.jsp afin qu'il affiche la notification s'il n'y a pas un tel attribut. Voici la version finale de add.jsp :
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<p>User '" + request.getAttribute("userName") + "' added!</p>");
                }
            %>
            <div>
                <div>
                    <h2>Add user</h2>
                </div>

                <form method="post">
                    <label>Name:
                        <input type="text" name="name"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass"><br />
                    </label>
                    <button type="submit">Submit</button>
                </form>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Le corps de la page se compose des éléments suivants :
  • un div avec un en-tête ;
  • un conteneur div pour le contenu, qui inclut une vérification de l'existence d'un attribut avec un nom d'utilisateur ;
  • un div avec le formulaire add-user ;
  • et en bas, un pied de page avec un bouton pour revenir à la page d'accueil.
Cela peut sembler trop de divs, mais nous les utiliserons plus tard lorsque nous ajouterons des styles. Voici la version finale de list.jsp :
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <div>
                <div>
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ui>");
                        for (String s : names) {
                            out.println("<li>" + s + "</li>");
                        }
                        out.println("</ui>");
                    } else out.println("<p>There are no users yet!</p>");
                %>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Ainsi, nous avons une application Web entièrement fonctionnelle qui peut enregistrer et ajouter des utilisateurs, et également afficher une liste de leurs noms. Maintenant, il ne reste plus qu'à le rendre joli... :) Créer une application Web simple à l'aide de servlets et de JSP (partie 2) - 2

Ajout de styles. Nous utiliserons le framework W3.CSS

Pour le moment, notre application fonctionne, mais elle a l'air absolument scandaleuse. Alors, ajoutons un arrière-plan, colorons le texte et les boutons, ajoutons du style aux listes, alignons les éléments, ajoutons des retraits, etc. Les styles d'écriture manuels peuvent prendre beaucoup de temps et mettre nos nerfs à rude épreuve. Je propose donc d'utiliser le framework W3.CSS . Il a déjà des classes prêtes à l'emploi avec des styles. Nous avons juste besoin d'organiser les classes CSS que nous voulons utiliser aux bons endroits. Pour les ajouter à nos pages, nous connectons d'abord le fichier de style. Il y a deux façons de faire ça:
  1. parcourez nos pages et insérez ci-dessous un lien direct vers le fichier de style dans la section d'en-tête

    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

    Cette option convient si vous disposez d'une connexion Internet permanente. Lorsque vous ouvrez vos pages sur le serveur local, les styles seront extraits d'Internet.

  2. Mais si vous voulez avoir tous les styles localement et ne pas dépendre d'une connexion Internet, téléchargez le fichier de style et placez-le quelque part dans le dossier web (par exemple web/styles/w3.css ). Parcourez ensuite toutes nos pages ( index.html, add.jsp, list.jsp ) et ajoutez le lien suivant vers le fichier de style dans la section head :

    <link rel="stylesheet" href="styles/w3.css">

    Après cela, parcourez simplement les balises et ajoutez les styles que vous aimez. Je ne m'attarderai pas là-dessus en détail. Au lieu de cela, je fournirai simplement des versions prêtes à l'emploi de trois de mes fichiers avec des classes de style raster.

index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Super app!</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center">
            <div class="w3-bar w3-padding-large w3-padding-24">
                <button class="w3-btn w3-hover-light-blue w3-round-large" onclick="location.href='/list'">List users</button>
                <button class="w3-btn w3-hover-green w3-round-large" onclick="location.href='/add'">Add user</button>
            </div>
        </div>
    </body>
</html>
ajouter.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-padding">
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<div class=\"w3-panel w3-green w3-display-container w3-card-4 w3-round\">\n" +
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-green w3-border w3-border-green w3-hover-border-grey\">×</span>\n" +
                            "   <h5>User '" + request.getAttribute("userName") + "' added!</h5>\n" +
                            "</div>");
                }
            %>
            <div class="w3-card-4">
                <div class="w3-container w3-center w3-green">
                    <h2>Add user</h2>
                </div>
                <form method="post" class="w3-selection w3-light-grey w3-padding">
                    <label>Name:
                        <input type="text" name="name" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <button type="submit" class="w3-btn w3-green w3-round-large w3-margin-bottom">Submit</button>
                </form>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
liste.jsp
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users list</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center w3-margin-bottom w3-padding">
            <div class="w3-card-4">
                <div class="w3-container w3-light-blue">
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ul class=\"w3-ul\">");
                        for (String s : names) {
                            out.println("<li class=\"w3-hover-sand\">" + s + "</li>");
                        }
                        out.println("</ul>");

                    } else out.println("<div class=\"w3-panel w3-red w3-display-container w3-card-4 w3-round\">\n"
+
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-red w3-border w3-border-red w3-hover-border-grey\">×</span>\n" +
                            "   <h5>There are no users yet!</h5>\n" +
                            "</div>");
                %>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Et c'est tout. :) Si vous avez encore des questions ou des commentaires, ou si quelque chose ne fonctionne pas, veuillez laisser un commentaire. Et je vais joindre quelques captures d'écran de la façon dont tout cela s'est avéré.
Créer une application Web simple à l'aide de servlets et de JSP (partie 2) - 3
Créer une application Web simple à l'aide de servlets et de JSP (partie 2) - 4
Créer une application Web simple à l'aide de servlets et de JSP (partie 2) - 5
Et enfin , si vous voulez vous entraîner avec ce projet, vous pouvez essayer ce qui suit :
  • créez une servlet et une JSP pour supprimer un utilisateur, et ajoutez une autre paire pour modifier un utilisateur existant. Le résultat sera une véritable application Web CRUD construite à l'aide de servlets. ;)
  • remplacez la liste par une base de données, afin que les utilisateurs ajoutés ne disparaissent pas après le redémarrage du serveur. :)
Bonne chance!
Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires