tete du loic

 Loïc YON [KIUX]

  • Enseignant-chercheur
  • Référent Formation Continue
  • Responsable des contrats pros ingénieur
  • Référent entrepreneuriat
  • Responsable de la filière F2 ingénieur
  • Secouriste Sauveteur du Travail
mail
loic.yon@isima.fr
phone
(+33 / 0) 4 73 40 50 42
location_on
ISIMA
  • twitter
  • linkedin
  • viadeo

eco Découverte eco

Date de première publication : 2019/10/21

Objectif et contexte

L'objectif de cet exercice est de mettre en oeuvre le "Hello World" de Spring Boot, puis de voir en action les servlets.

L'environnement de développement est le suivant :

Consulter la version de java avec javac -v. Si cette version du compilateur Java est au moins 17, vous pouvez utiliser la version 3 du framework. Dans le cas contraire, il faudra garder la version 2.7.

Découverte de SpringBoot

Mise en place des éléments

Cette partie est un extrait de la documentation officielle "serving web content"

Pour commencer, vous avez deux possibilités :

On a sélectionné les options suivantes :

Vous obtenez alors l'arborescence suivante :


.
├── HELP.md
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── app
    │   │       └── BonjourApplication.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── java
            └── app
                └── BonjourApplicationTests.java

Le couteau suisse à tout faire (compilation et déploiement) est Gradle et son wrapper (pour éviter l'installation) gradlew. Gradle téléchargera tous les éléments nécessaires au projet (sauf le JDK).

Fichier de configuration

Le fichier de configuration de notre application est build.gradle :

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.1'
	id 'io.spring.dependency-management' version '1.1.4'
}

group = 'app'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

Bien entendu, il faut adapter le fichier en fonction de la version de java que l'on veut utiliser ou bien encore en fonction de la version du framework.

Suivant les besoins, il faudra le compléter (par exemple, pour utiliser le moteur de template à la fin du TP)

Répertoire src

src est le répertoire source du projet. main contient le code principal. java le code écrit en java et app est le package.

Dès la première construction du projet, vous trouverez un répertoire build. Ce répertoire est regénéré à chaque build.

Page à afficher

Dans un premier temps, nous allons afficher une simple page web statique que vous devez placer dans le répertoire src/main/resources/static/index.html (vous pouvez remplacer static par public si vous voulez ...)


<!DOCTYPE HTML>
<html>
<head>
    <title>une premiere page web statique pour pring boot</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<p>Cette page statique est le point d'entree de l'application</p>
<p>Personnalisez avec votre PRENOM pour être sûr(e) que c'est bien votre page à VOUS !</p>
<!--
    <p>un lien pour plus tard <a href="/bonjour">ici</a></p>-->
</body>
</html>

Mais il est où le serveur de page Ouaib ? Hein ? C'est l'application Spring Boot elle-même ! Toute la magie est dans la classe BonjourApplication (la classe est trouvée automatiquement et il ne peut PAS y avoir deux classes avec l'annocation @SpringBootApplication

package app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
public class BonjourApplication {

    public static void main(String[] args) {
        SpringApplication.run(BonjourApplication.class, args);
    }

}

Compilation et exécution

Pour voir le tout en action, il suffit de "compiler" le projet :


gradle build

Puis de lancer le serveur :


gradle bootRun

On peut aussi executer le fichier jar qui se trouve dans le répertoire build/libs :

java -jar build/libs/bonjour-0.1.0.jar

Ouvrez un navigateur et demandez l'ouverture de la page http://localhost:8080 ou bien utilisez curl sur la même adresse.

Si vous avez une erreur de type "fallback", le serveur est bien fonctionnel mais vous avez oublié la page index.html.

Le port 8080, standard, risque déjà d'être pris lors des TPs alors on peut en changer... Voici comment spécifier le port 9090, par exemple :


java -Dserver.port=9090 -jar build/libs/bonjour-0.1.0.jar
java -jar build/libs/bonjour-0.1.0.jar --server.port=9090
gradle bootRun --args='--server.port=9090'

Si vous spécifiez la valeur de port 0, un port ouvert aléatoire sera choisi. On pourra le voir lors lancement de l'application (un Tomcat par défaut). Ce numéro de port peut aussi être récupéré par l'application elle-même.

La dernière possibilité consiste à préciser le numéro de port dans le fichier de configuration application.properties dans src/main/resources (la version en ligne de commande est prioritaire)


server.port=9090

Manipulation de servlet

Avec Java EE/Jakarta EE, le composant de base d'un conteneur de servlets est une ... servlet, c'est-à-dire une classe Java qui est compilée et exécutée pour rendre un "service".

Une première servlet

Voici le code d'une servlet de base :

package app;

import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/prems/*", loadOnStartup = 1)
public class PremsServlet extends HttpServlet   {
  private static final long serialVersionUID = 1L;
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
        doGet(request,response);
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("

Hello chers ZZ3!

"); } }

À la lecture du code, vous aurez compris qu'elle est dans un fichier src/main/java/app (vous pouvez également modifier le code pour faire un package spécifique app.servlets - c'est une bonne pratique. Les annotations précisent respectivement à quelle URL la servlet va être exécutée et à quel moment elle est chargée (et donc compilée) en mémoire.

Les méthodes doGet() et doPut() sont appelées en fonction de la requête HTTP fournie. Dans l'exemple, l'une appelle l'autre pour avoir la même réponse.

Pour accéder à la servlet, il faut taper une URL du type


  http://localhost:8080/prems

Si vous obtenez une erreur 404, vous pouvez vous être trompé de nom, mais il est aussi probable que vous ayez oublié l'annotation @ServletComponentScan sur l'application SpringBoot (le code de BonjourApplication n'est pas tout à fait celui qui a été généré :-))

Enrichissement de la servlet

Si le compteur n'est pas incrémenté, redéployez l'application et vérifiez que la page n'est pas mise en cache. Quand ce compteur est-il remis à 0 ?

Interaction avec la servlet

Ajouter un formulaire contenant un champ texte et un bouton submit par exemple dans le corps le fichier index.html. L'attribut action du formulaire fera appel à la servlet et l'attribut method représentera la valeur POST ou GET (mode de passage des paramètres au serveur).


<form action="prems" method="get">
  <input type="text" name="texte">
  <input type="submit">
</form>

L'attribut name (ou préférentiellemet id) est nécessaire.

Modifier la servlet pour qu'elle affiche le champ texte du formulaire avec la méthode getParameter(nom) de l'objet request). Le paramètre nom est la valeur de l'attribut name ou de l'identifiant id de l' élément du formulaire

On peut connaître le mode de passage des paramètres grâce à la méthode (getMethod() de request). La valeur est GET ou POST ( et conforme à l'attribut method de la balise form

Nous arrêtons là pour l'instant la découverte des servlets. Même si l'usage actuel consiste à les cacher, elles reviennent assez vite sur les choses qui sortent un peu du "facile et standard".

Vue et contrôleur

SpringBoot utilise un patron de conception MVC pour les applications (Spring MVC). Par la suite, on va s'intéresser uniquement à la vue : une page web et au contrôleur, un objet java que l'on appelle un bean...

Voici un exemple de contrôleur :

package app;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class BonjourController {

    // le nom de la méthode n'est pas important, mais les annotations si !
    @GetMapping("/bonjour")
    public String disBonjour(@RequestParam(name="name", required=false, defaultValue="Moi") String name, Model model) {
        model.addAttribute("name", name);
        return "bonjour";
    }

}

Le contrôleur est appelé lorsque l'URL mentionne /bonjour avec la méthode GET (on peut réagir aux différents verbes HTTP avec les noms d'annotations qui vont bien)

La méthode retourne le nom de la page web qui sera affichée par le contrôleur, soit bonjour. Des informations pourront être passées à cette page au travers de l'instance de Model. Dans le cas présent, on passe la valeur du paramètre "name" s'il est fourni ou une valeur par défaut sinon (par formulaire ou par modification d'URL)


  http://localhost:8080/bonjour?name=moi

Il faut encore créer la page web qui sera affichée : soit statique, soit affichée au travers d'un template qui permet de faciliter l'écriture de la page (par rapport à l'utilisation d'une servlet par exemple)

Voici la page bonjour.html du tutorial Spring :


<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Premiere page avec template</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Le code est généré quand c'est nécessaire </p>
    <p th:text="'Bonjour, ' + ${name} + '!'" />
</body>
</html>

Elle est à placer dans le répertoire src/main/resources/templates. Le moteur de template utilisé est Thymeleaf Il faut modifier le fichier de build pour ce faire :

dependencies {
	...
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}

Si vous oubliez de faire cela, vous aurez une erreur de référence circulaire à la demande de la page ; erreur affichée à la fois par le navigateur et dans la console.

 

That's all for now folk !!