Exercice 1 - Développement de l'application - V1.0⚓︎
Ca y est, on peut commencer à développer notre application.
1. Création du projet dans eclipse⚓︎
Il faut commencer par créer un projet Web dynamic, qu'on appelera Boutique. Il faut penser à vérifier le runtime utilisé (tomcat9) et à cocher la case Generate web.xml deployment descriptor :
Pas de web.xml ?
Si vous avez oublié de cocher cette case, il faudra soit supprimer ce projet et recommencer à l'étape 1, soit ajouter manuellement le fichier 📄web.xml
, en respectant la structure attendue.
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.
- Dans la vue
Project Explorer
, sur le projet Boutique, faire un clic droit, puis :material-mouse:New > Other
. Dans l'arborescence, naviguer ensuite vers :material-file-tree:Java > Class
. - Cliquer sur
Next > . -
Indiquer le package :
fr.univtours.polytech.boutique.model
.Warning
On ne laisse jamais le package par défaut lorsqu'on développe une application avec JEE.
-
Indiquer le nom de classe :
CartBean
.Remarque
Il est pratique d'indiquer ce qu'est la classe dans son nom, ici, un bean.
-
Cette classe est un bean, c'est-à-dire qu'elle implémente l'interface
java.io.Serializable
. Il faut donc l'ajouter (avec le boutonAdd... ). - Dans ce bean, il faut créer tous les attributs :
☕ Code Java 1 2 3 4 5 6
private Integer penNumber; private Integer feltNumber; private Integer rubberNumber; private Double cartPrice; private Double shippingCost; private Double totalPrice;
-
Il faut ensuite générer les getters/setters en faisant un clic droit avec la souris, puis :material-mouse:
Source > Generate Getters and Setters...
Raccourci
Il peut être très utile de mémoriser le raccourci qui amène directement à :material-mouse:
Source
: c'est Alt+Shift+S. -
Enfin, pour ne pas avoir de warning, on ajoute le champ static tout au début de la classe :
☕ Code Java 1
private static final long serialVersionUID = 1L;
Astuce : bonnes pratiques
Prenez l'habitude, à chaque modification d'une classe, de faire deux choses :
- Ctrl+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+F : 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. Ce site vous indique comment configurer eclipse pour faire cela.
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.
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.
- Dans la vue
Project Explorer
, sur le projet Boutique, faire un clic droit, puis :material-mouse:New > Other
. Dans l'arborescence, naviguer ensuite vers :material-file-tree:Java > Interface
. - Cliquer sur
Next > . - Indiquer le package :
fr.univtours.polytech.boutique.business
. - Indiquer le nom de l'interface :
StoreBusiness
, puis cliquer surFinish . - 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);
- En effectuant la même opération, créer une classe
StoreBusinessImpl
, dans ce même packagefr.univtours.polytech.boutique.business
, qui implémente cette interface. - Cette classe va contenir 3 champs statiques, qui correspondent au prix de nos trois produits :
☕ 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;;
-
Voici l'implémentation de
computePrices
:☕ Code Java - Méthode computePrices de StoreBusinessImpl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public CartBean computePrices(CartBean cart) { // 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+Shift+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.Note
À chaque fois que vous verrez des
...
dans le code fourni, il faudra compléter ce code ...
C'est bon, notre modèle est en place.
4. Implémentation du contrôleur⚓︎
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 :
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
.
C'est pour cela que nous travaillons avec tomcat9 (qui implémente JEE 8), et pas tomcat10 (qui implémente JEE 9) ... 😫 Vous suivez toujours ?
Bref, utiliser JEE 9 présente quelques risques, puisque c'est récent, et il y a souvent des configurations à aller changer manuellement (aller trouver des javax
cachés pour les modifier en jakarta
) ...
- Via le descrtipteur de déploiement, c'est-à-dire le fichier 📄
web.xml
(c'est ce que nous avons fait jusqu'à présent). - Via des annotations : c'est ce que nous allons faire maintenant !
Remarque importante !
Dans tous les cas, on choisit une seule de ces deux méthodes, jamais les deux.
- On commence par créer la servlet : dans la vue
Project Explorer
, sur le projet Boutique, faire un clic droit, puis :material-mouse:New > Other
. Dans l'arborescence, naviguer ensuite vers :material-file-tree:Web > Servlet
. - Cliquer sur
Next . - Indiquer le package :
fr.univtours.polytech.boutique.controller
. -
Indiquer le nom de classe :
StoreServlet
.On remarque au passage que l'héritage de
javax.servlet.HttpServlet
est déjà indiqué. -
Cliquer sur
Next . - Modifier le champ
Name
en indiquantcontroller
, puis cliquer surNext . -
Décocher tout sauf
Inherited abstract methods
etdoGet
, puis cliquer surFinish .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. Nous verrons un peu plus tard comment faire ce choix de méthode.
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@WebServlet(name = "controller", urlPatterns = { "/controller" }) public class StoreServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
Avec cette méthodes des annotations, il n'y a plus besoin de modifier le fichier 📄
web.xml
!La propriété
urlPatterns
(on peut lui donner plusieurs valeurs) de l'annotation@WebServlet
nous indique comment accéder à cette servlet. Elle a exactement le même rôle que la balise<url-pattern>
qu'on utilisait dans le fichier 📄web.xml
. - 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.
-
Modifier la méthode
doGet
pour qu'elle redirige vers la vuestore.jsp
.
Pourquoi avoir un web.xml?
Maintenant que nous n'avons plus besoin de déclarer les Servlets dans le 📄web.xml
, on peut se demander si ce fichier est toujours utile ...
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/controller.
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>controller</welcome-file>
</welcome-file-list>
Après un redémarrage du serveur, l'application est maintenant disponible ici : http://localhost:8080/Boutique
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. Ce dossier est défini lorsqu'on créée le projet web dynamique. Par défaut, c'est le dossier 📂src/main/webapp
:
Java Server Page | |
---|---|
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.