Exercice 1 - Développement de l'application - V1.0⚓︎
Ça y est, on peut commencer à développer notre application.
1. Création du projet⚓︎
Créer un projet, qu'on appelera boutique.
Création du projet
Comme dans le TD1, auquel on pourra se reporter si besoin, on utilisera Maven et l'archetype webapp-jakartaee10
.
- Le group id sera toujours
fr.univtours.polytech
. - L'artefact id sera donc
boutique
(c'est toujours le nom du projet). - Dans le fichier
pom.xml
, ne pas oublier d'ajouter<finalName>boutique</finalName>
dans la balise<build>
.
2. Implémentation du modèle⚓︎
Dans cette première version, le modèle n'est constitué que d'une seule classe, qui modéliser le panier. Il s'agit d'un bean. Nous l'appellerons CartBean
.
Remarque
Il est pratique d'indiquer ce qu'est la classe dans son nom, ici, un bean (exactement comme ce que nous avons fait précédemment pour les Servlets).
- Il faut tout d'abord créer le package qui va contenir le modèle :
fr.univtours.polytech.boutique.model
. - Dans ce package, créer la classe
CartBean
. C'est un bean, c'est-à-dire qu'elle doit implémenter l'interfacejava.io.Serializable
. Il faut donc l'ajouter. - Dans ce bean, il faut créer tous les attributs :
☕ Code Java 1 2 3 4 5 6
private Integer penNumber; // Le nombre de stylo. private Integer feltNumber; // Le nombre de feutre. private Integer rubberNumber; // Le nombre de gomme. private Double cartPrice; // Le prix du panier. private Double shippingCost; // Les éventuels frais de livraison. private Double totalPrice; // Le prix total.
- Il faut ensuite générer les getters/setters. Le menu
Sources Actions...
permet d'automatiser tout cela.
Astuce : bonnes pratiques
Prenez l'habitude, à chaque modification d'une classe, de faire deux choses :
- Alt+Shift+o : Permet de faire du ménage dans les imports pour ne conserver que ceux utiles.
Lesimport java.io.*
par exemple sont remplacés par l'import des classes utilisées uniquement. - Ctrl+Shift+i : Permet de formater le code, de la même façon pour tout le monde.
C'est vraiment un plus si le code de tout le monde est formaté de la même façon. Cela permet de le comprendre beaucoup plus rapidement !
Ne pas utiliser de tabulations
De manière générale, quel que soit le langage (Java, Python, XML, ...) il faut remplacer les Tab par des espaces.
3. Implémentation de la couche métier⚓︎
Par rapport au paradigme MVC, on peut considérer que cette couche fait partie du modèle. En effet, son rôle est de mettre à jour ce dernier.
La couche métier
Cette couche est la couche centrale de l'application. Lorsqu'on la développe, on se demande quels sont les services métiers qu'elle doit fournir. Ici, il y en a un seul, il s'agit de calculer les différents prix affichés sur le panier, c'est-à-dire d'appliquer les 3 règles de gestions.
De manière générale, c'est dans cette couche que les différentes règles de gestion seront implémentées.
La couche métier est toujours accessible via une interface. Cette interface indique la liste des services disponibles. Depuis l'extérieur, c'est-à-dire depuis le contrôleur, on souhaite savoir quels sont les services offerts (l'interface), mais on ne veut pas savoir comment ils sont implémentés (la classe qui implémente cette interface).
Nous allons donc créer une interface, proposant une méthode computePrices
, qui va prendre le panier en paramètre, appliquer les 3 règles de gestions, et renvoyer le panier mis à jour. Cette interface va être implémentée par une classe.
- Créer le package représentant la couche métier :
fr.univtours.polytech.boutique.business
. - Créer l'interface permettant d'exposer les services :
StoreBusiness
. - Elle contient une méthode
computePrices
, qui prend un objetCartBean
(le panier) en paramètre, et qui renvoie ce même objet modifié :☕ Code Java 1
public CartBean computePrices(CartBean cart);
- Dans ce même package, créer une classe
StoreBusinessImpl
, qui implémente cette interface. -
Une erreur apparaît. En effet la méthode
computePrices
, qui doit être implémentée, est absente.Pour l'ajouter automatiquement, il est possible de placer le curseur sur l'erreur, puis avec Ctrl+Shift+;, de sélectionner Add unimplemented methods. 7. Cette classe va contenir 3 champs statiques, qui correspondent au prix de nos trois produits :
8. Enfin, voici une grande partie de l'implémentation de la méthode☕ Code Java 1 2 3
private final static Double PEN_PRICE = 1.2D; private final static Double FELT_PRICE = 1.8D; private final static Double RUBBER_PRICE = 2D;;
computePrices
:☕ Code Java - Méthode computePrices de StoreBusinessImpl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Application de la RG1 : Double cartPrice = cart.getPenNumber() * PEN_PRICE + ...; // Application de la RG2 : Double shippingCost = 5D; if (cartPrice > ...) { shippingCost = ...; } // Application de la RG3 : Double totalPrice = ...; // Mise à jour du panier : cart.setCartPrice(cartPrice); ... ... return cart;
Rappel des 3 règles de gestion
Pour rappel, les trois RG sont :
- RG1 : Calcul du prix du panier, sachant que :
- un styo coûte 1,20€,
- un feutre coûte 1,80€,
- une gomme coûte 2€.
- RG2 : Les frais de livraison sont de 5€ si la commande est de moins de 15€, et sont offerts sinon.
- RG3 : Le prix total de la commande est la somme du prix du panier et des évenutels frais de livraison.
Remarque
Lorsqu'on fait un copier/coller du code, les imports ne sont pas toujours faits. S'il y a des erreurs (
CartBean
est par exemple inconnu), pensez à faire un Ctrl+Alt+O pour les mettre à jour ! - RG1 : Calcul du prix du panier, sachant que :
-
Compléter les
...
dans la méthodecomputePrices
pour appliquer correctement les 3 RG.
C'est bon, notre modèle est en place.
4. Implémentation du contrôleur⚓︎
Nouvelle version de JEE
JEE, pour Java Entreprise Edition, a changé de nom après la version 8. À partir de la version 9, JEE signifie Jakarta Entreprise Edition.
Il n'y a pas que le nom qui a changé, tous les packages qui commencait par javax
commencent maintenant par jakarta
. Par exemple, javax.servlet.http.HttpSession
a été renommé en jakarta.servlet.http.HttpSession
.
Le contrôleur est une servlet. Une servlet est une classe qui hérite de HttpServlet
de l'API servlet
. Il y a ensuite deux façons de déployer une servlet :
- Via le descrtipteur de déploiement, c'est-à-dire le fichier 📄
web.xml
(c'est ce que nous avons vu dans le cours). - Via des annotations (c'est ce que nous avons toujours fait en TD).
Remarque importante !
Dans tous les cas, on choisit une seule de ces deux méthodes, jamais les deux.
- Créer le package :
fr.univtours.polytech.boutique.controller
. - Créer la Servlet :
StoreServlet
. - Indiquer qu'elle étend
HttpServlet
. - Déployer la Servlet en ajoutant l'annotation. L'url pour y acceder sera
/store
-
Surcharger la méthode
doGet
(via Source Actions...). N'oublie pas de renommer les paramètresreq
etresp
.Note
La servlet n'implémentant que cette méthode, cela signifie qu'elle ne va pouvoir intercepter que les requêtes HTTP dont la méthode est GET. Comme nous le verrons juste après, si nous envoyons une requête HTTP POST, nous obtiendrons une erreur.
Rappel sur les méthodes HTTP
-
La méthode GET est la méthode par défaut lorsqu'on exécute une requête HTTP depuis son navigateur, c'est-à-dire lorsqu'on saisit l'URL dans la barre du navigateur et qu'on appuie sur Entrée.
On peut envoyer des paramètres au serveur qui traite cette requete en ajoutant les couples (clef, valeur) dans l'URL, après un
?
, séparés par des&
.Par exemple :
http://url_de_mon_appli?param1=valeur1¶m2=valeur2&...
-
La méthode POST est appelée lorsqu'on soumet un formulaire, afin d'envoyer des valeurs au serveur, c'est-à-dire lorsqu'on clique sur un bouton. Les paramètres sont alors placés dans le corps de la requête.
Seule la requête pour afficher la page d'accueil (c'est-à-dire à la première connexion) sera un GET. Lorsque l'utilisateur cliquera sur le bouton
Valider
après avoir sélectionné ses produits, une méthode POST sera exécutée.C'est cela qui nous permet de différencier le premier affichage des autres, sans avoir à définir plusieurs Servlets.
On en est là :
Si tout va bien, ta Servlet doit ressemble à ça :
☕ Code Java - StoreServlet@WebServlet(name = "storeServlet", urlPatterns = {"/store"}) public class StoreServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub super.doGet(request, response); } }
-
-
Modifier la méthode
doGet
pour qu'elle redirige vers la vuestore.jsp
.
Pourquoi avoir un web.xml?
Nous n'avons vu qu'il n'était pas nécessaire de déclarer les Servlets dans le 📄web.xml
, on peut se demander si ce fichier est bien utile ...
Oui ! Car il va nous permettre d'ajouter d'autres informations, par exemple, de définir une page par défaut !
Ici par exemple, on souhaiterait pouvoir ne saisir que http://localhost:8080/boutique comme URL, plutôt que http://localhost:8080/boutique/store.
Pour cela, dans le fichier 📄web.xml
, il suffit de positionner le code suivant à l'intérieur de la balise <web-app>
:
<welcome-file-list>
<welcome-file>store</welcome-file>
</welcome-file-list>
Ce welcome-file
peut être une page HTML, une page JSP, ou comme ici, une Servlet !
5. Implémentation de la vue⚓︎
Pour l'instant, il n'y a qu'une seule vue. C'est 📄store.jsp
. Cette JSP ne contient pour l'instant que du code HTML :
Où placer les JSP ?
Les JSP (ainsi que les pages HTML, le javascript, le CSS, ...) doivent être placées dans le dossier contenu web. Par défaut, c'est le dossier 📂src/main/webapp
.
📄store.jsp | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
|
-
Le formulaire HTML (balise
<form>
) permet à l'utilisateur de saisir des informations, et de les envoyer au serveur en cliquant sur le bouton valider (on dit qu'on "soumet" le formulaire.)Toutes les balises
<input type="*">
permettent d'envoyer une information au serveur, que nous allons pouvoir récupérer grace à la valeur de l'attributname
.La propriété
action
permet d'indiquer quelle URL va être exécutée à la soumission du formulaire (on fait le lien avec le<url-pattern>
dans le 📄web.xml
).Enfin, la propriété
method
indique avec quelle méthode la requête HTTP est envoyée. Ici, c'est POST, ce qui nous permettra de différencier le premier affichage de la page (méthode GET), et la soumission du formulaire.