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
Institut d'informatique 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 :

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 :

Le fichier qui nous intéresse le plus est build.gradle qui contient la configuration de notre projet et qui ressemble à quelque chose comme cela :

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.7'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
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 (3.0.1 en janvier 2023), ce qui donne :

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

Ce qui est sympa avec un outil comme Gradle (et surtout Gradlew, le wrapper de Gradle sans install) et SpringBoot, c'est qu'il n'est pas nécessaire d'installer quoi que ce soit car tout est téléchargé au besoin (bon faut internet tout de même et un JDK)

Il est ensuite nécessaire de vérifier que l'aborescence suivante existe :

mkdir -p src/main/java/hello
mkdir -p src/main/resources/static

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

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>Getting Started: Serving Web Content</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>Get your greeting <a href="/greeting">here</a></p>-->
</body>
</html>

Mais il est où le serveur de page Ouaib ? Hein ? C'est l'application Spring Boot elle-même ! Il faut ajouter la classe src/main/java/hello/Application.java

package hello;

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

@ServletComponentScan
@SpringBootApplication
public class Application {

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

}

Compilation et exécution

Pour voir le tout en action, il suffit de "compiler" le projet et d'exécuter :


gradle build
gradle bootRun

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

java -jar build/libs/gs-serving-web-content-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/gs-spring-boot-0.1.0.jar
java -jar build/libs/gs-spring-boot-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, 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 hello;

import java.io.IOException;
import java.io.PrintWriter;
// Pour la branche 2.7 de Spring Boot
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Pour la branche 3 de Spring Boot
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/simple/*", loadOnStartup = 1)
public class SimpleServlet 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/hello (vous pouvez également modifier le code pour faire un package spécifique hello.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/simple

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

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="simple" 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 hello;

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 GreetingController {

    @GetMapping("/greeting")
    public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
        model.addAttribute("name", name);
        return "greeting";
    }

}

Le contrôleur est appelé lorsque l'URL mentionne /greeting 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 greeting. 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/greeting?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'un servlet par exemple)

Voici la page greeting.html du tutorial Spring :


<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Getting Started: Serving Web Content</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>

Elle est à placer dans le répertoire src/main/resources/templates. Le moteur de template utilisé est Thymeleaf.

That's all for now folk !!