JavaRush /Blog Java /Random-FR /Application Web en Java
Viacheslav
Niveau 3

Application Web en Java

Publié dans le groupe Random-FR
Application Web en Java - 1

Introduction

Autrefois, Java renforçait sa position du fait qu'il choisissait en priorité les applications Web. Depuis ses débuts, Java a eu du mal à trouver sa voie. Tout d’abord, j’ai suggéré des applets. Cela a fourni de nombreuses opportunités aux développeurs pour créer du contenu dynamique (contenu) sur des pages HTML statiques. Cependant, les applets n'ont pas répondu aux attentes pour de nombreuses raisons : sécurité, frais généraux, etc. Ensuite, les développeurs du langage Java ont proposé une alternative - l'API Servlet . Et cela s’est avéré être la bonne décision. L'API Servlet est la spécification sur laquelle toute application Web Java est construite, qu'il s'agisse d'une application Web ou d'un service Web qui renvoie les informations demandées. Par conséquent, le chemin pour comprendre le fonctionnement des applications Web Java commence par la compréhension de l’API Servlet.
Application Web en Java - 2

API de servlets

Ainsi, l'API Servlet est ce que les développeurs de langage ont proposé aux développeurs Java. L'API Servlet est une spécification qui devrait répondre à nos principales questions. Vous pouvez le trouver ici : " JSR-000340 JavaTM Servlet 3.1 Final Release for Evaluation ". Le chapitre « 1.1 Qu'est-ce qu'un Servlet ? » dit qu'un servlet est un composant web basé sur la technologie Java qui crée du contenu dynamique (c'est-à-dire du contenu). « Basé sur Java » signifie qu'un servlet est une classe Java compilée en bytecode . Les servlets sont gérés par un conteneur de servlets, parfois appelé Servlet Engine. Un conteneur de servlet est une extension de serveur Web qui fournit des fonctionnalités de servlet. À leur tour, les servlets fournissent une interaction avec le client dans le paradigme requête/réponse, qui est implémenté par le conteneur de servlets. Dans le chapitre " 1.2 Qu'est-ce qu'un conteneur de servlets ? " il est dit qu'un conteneur de servlets fait partie d'un serveur Web ou d'un serveur d'applications qui fournit des services réseau à travers lesquels les requêtes et les réponses sont envoyées, les requêtes et réponses basées sur MIME sont générées et traitées. . De plus, les conteneurs de servlets gèrent le cycle de vie des servlets (c'est-à-dire décider quand les créer, les supprimer, etc.). Tous les conteneurs de servlets doivent prendre en charge le protocole HTTP pour recevoir des requêtes et envoyer des réponses. Ici, je voudrais ajouter que MIME est une norme, une spécification qui indique comment les informations doivent être codées et les messages formatés afin qu'ils puissent être envoyés sur Internet.
Application Web en Java - 3

Serveur Web

Un serveur Web est un serveur qui accepte les requêtes HTTP des clients et leur fournit des réponses HTTP (généralement accompagnées d'une page HTML, d'une image, d'un fichier ou d'autres données). Les ressources demandées sont identifiées par des URL. L'un des serveurs Web les plus populaires prenant en charge l'API Servlet est Apache Tomcat . La plupart des serveurs Web sont des machines complexes composées de divers composants, chacun remplissant des fonctions spécifiques. Par exemple:
Application Web en Java - 4

Connecteurs

— En entrée, nous avons des connecteurs (c'est-à-dire des connecteurs) qui acceptent les demandes entrantes des clients. Le connecteur HTTP dans Tomcat est implémenté à l'aide du composant "Coyote". Les connecteurs reçoivent les données du client et les transmettent au moteur Tomcat. Conteneur de servlets - Tomcat Engine, à son tour, traite la demande reçue du client à l'aide du composant "Catalina", qui est un conteneur de servlets. Voir la documentation Tomcat : " Architecture Overview " pour plus de détails. Il existe d'autres serveurs Web qui prennent en charge la spécification de l'API Servlet. Par exemple, " Jetty " ou " Undertow ". Leur architecture est similaire, donc en comprenant le principe de travailler avec un conteneur de servlet, vous pouvez passer à un autre.
Application Web en Java - 5

Application Web

Ainsi, pour pouvoir exécuter une application Web, nous avons besoin d'un serveur Web prenant en charge l'API Servlet (c'est-à-dire un serveur doté d'un composant d'extension qui implémente la prise en charge de l'API Servlet pour le serveur Web). Bien. Au fait, qu’est-ce qu’une application Web ? Selon le chapitre « 10 Applications Web » de la spécification de l'API Servlet, une application Web est un ensemble de servlets, de pages HTML, de classes et d'autres ressources qui constituent une application finale sur un serveur Web. Selon le chapitre « 10.6 Fichier d'archive d'application Web », une application Web peut être empaquetée dans Web ARchive (une archive avec une extension WAR). Comme indiqué sur la page " Glossaire-219 " :
Application Web en Java - 6
Autrement dit, WAR est créé à la place de JAR pour montrer qu'il s'agit d'une application Web. Le prochain fait important : nous devons avoir une certaine structure de répertoires dans notre archive WAR. Dans la spécification de l'API Servlet au chapitre " 10.5 Structure des répertoires ". Ce chapitre indique qu'il existe un répertoire spécial appelé "WEB-INF". Ce répertoire a la particularité de n'être pas visible par le client et ne lui est pas directement présenté, mais il est accessible au code du servlet. Il indique également ce que peut contenir le répertoire WEB-INF :
Application Web en Java - 7
De toute cette liste, nous ne connaissons pas et ne comprenons pas l'élément concernant un fichier web.xml appelé descripteur de déploiement . Qu'est-ce que c'est? Le chapitre « 14. Descripteur de déploiement » est consacré au descripteur de déploiement. En bref, un descripteur de déploiement est un fichier XML qui décrit comment déployer (c'est-à-dire exécuter) notre application Web sur un serveur Web. Par exemple, le descripteur de déploiement indique quelles URL doivent être utilisées pour accéder à notre application, les paramètres de sécurité liés à notre application, etc. sont indiqués. Le chapitre " 14.2 Règles de traitement du déploiement " indique que le schéma web.xml sera validé avant que notre application ne soit configurée et lancée (c'est-à-dire qu'une vérification sera effectuée que le contenu de web.xml est écrit correctement selon le schéma) . Et dans le chapitre « 14.3 Descripteur de déploiement » il est indiqué que le schéma est ici : http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd Si on regarde le contenu du fichier, on peut voir :
Application Web en Java - 8
Quel est le schéma utilisé pour les fichiers XML ? Les schémas indiquent comment remplir correctement un document XML : quels éléments peuvent être utilisés, quel type de données peut être spécifié dans les éléments, dans quel ordre les éléments doivent être placés, quels éléments sont requis, etc. Vous pouvez comparer le schéma d'un document XML avec une interface en Java, car le schéma en Java spécifie également comment les classes qui satisfont une interface donnée (c'est-à-dire qui implémentent une interface donnée) doivent être écrites. Nous sommes donc armés de connaissances secrètes et sommes prêts à créer notre première application web !
Application Web en Java - 9

Création d'une application Web

Il est difficile d’imaginer travailler avec une application Java moderne sans utiliser des systèmes de création automatique de projets. Certains des systèmes les plus populaires sont Maven et Gradle . Nous utiliserons Gradle pour cette revue. L'installation de Gradle est décrite sur le site officiel . Pour créer une nouvelle application, nous avons besoin d'un plugin intégré à Gradle : " Build Init Plugin ". Pour créer une application Java, vous devez exécuter la commande suivante : gradle init --type java-application
Application Web en Java - 10
Après avoir créé le projet, nous devrons éditer le fichier build.gradle . Il s'agit de ce qu'on appelle Build Script (pour plus de détails, voir la documentation Gradle : " Writing Build Scripts "). Ce fichier décrit comment assembler le projet et d'autres aspects de l'utilisation d'un projet Java. Le bloc plugins décrit quels " plugins Gradle " doivent être utilisés pour le projet Gradle actuel. Les plugins élargissent les capacités de notre projet. Par exemple, le plugin par défaut est « java ». Ce plugin est toujours utilisé si nous avons besoin du support Java. Mais nous n'avons pas besoin du plugin « application », car... sa description indique qu'il est utilisé pour créer une "application JVM exécutable", c'est-à-dire exécutant des applications JVM. Nous devons créer une application Web sous la forme d'une archive WAR. Et si nous cherchons le mot WAR dans la documentation Gradle, nous trouverons « War Plugin ». Nous préciserons donc les plugins suivants :
plugins {
    id 'java'
    id 'war'
}
Également dans les " Paramètres par défaut du plugin War ", il est dit que le répertoire avec tout le contenu de l'application Web doit être " src/main/webapp ", il doit y avoir le même répertoire WEB-INF dans lequel le web.xml doit être situé. Créons un tel fichier. Nous le remplirons un peu plus tard, car... nous n'avons pas encore suffisamment d'informations pour cela. Dans le bloc "dépendances", nous indiquons les dépendances de notre projet, c'est-à-dire les bibliothèques/frameworks sans lesquels notre application ne peut pas fonctionner. Dans ce cas, nous écrivons une application web, ce qui signifie que nous ne pouvons pas travailler sans l'API Servlet :
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testCompile 'junit:junit:4.12'
}
provideCompile signifie que la dépendance n'a pas besoin d'être incluse dans notre archive WAR de l'application Web : elle n'est nécessaire que pour la compilation. Et une fois exécutée, cette dépendance sera fournie par quelqu'un d'autre (c'est-à-dire le serveur Web). Eh bien, nous laissons des informations dans le script de construction sur le référentiel de dépendances que nous souhaitons utiliser - toutes les dépendances spécifiées seront téléchargées à partir de celui-ci :
repositories {
    jcenter()
}
Nous supprimons tout le reste du fichier de script de construction. Modifions maintenant la classe src\main\java\App.java. Faisons-en une servlet. La spécification de l'API Servlet dans le chapitre " CHAPITRE 2. L'interface servlet " indique que l'interface servlet a une implémentation de base de HttpServlet , ce qui devrait être suffisant dans la plupart des cas et les développeurs doivent simplement en hériter. Et dans le chapitre " 2.1.1 Méthodes de traitement des requêtes spécifiques HTTP " les principales méthodes qui traitent les requêtes entrantes sont indiquées. Ainsi, réécrivons la classe App.java :
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.IOException;

public class App extends HttpServlet {
    public String getGreeting() {
        return "Hello world.";
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 		// https://www.oracle.com/technetwork/java/servlet-142430.html
 		PrintWriter out = resp.getWriter();
 		out.println(this.getGreeting());
 		out.close();
 	}
}
Il semble donc que tout soit prêt. Il ne reste plus qu'à écrire correctement le descripteur de déploiement. À partir du diagramme, copiez le texte suivant dans web.xml :
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="..."
      version="3.1">
      ...
</web-app>
Et aussi le chemin d'accès au schéma qui y est indiqué : http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd regardons maintenant un exemple de ce à quoi devrait ressembler web.xml dans la spécification de l'API Servlet. Cet exemple est donné dans le chapitre " 14.5.1 Un exemple de base ". Combinons ce qui est indiqué dans le schéma avec l'exemple indiqué dans le cahier des charges. Nous obtenons ce qui suit :
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
      version="3.1">
      <display-name>A Simple Web Application</display-name>
      <servlet>
		<servlet-name>app</servlet-name>
		<servlet-class>App</servlet-class>
	  </servlet>
	  <servlet-mapping>
		<servlet-name>app</servlet-name>
		<url-pattern>/app</url-pattern>
	  </servlet-mapping>
</web-app>
Comme vous pouvez le voir, nous avons utilisé le schéma et le schémaLocation spécifiés précédemment. Et la description des éléments eux-mêmes est tirée de l'exemple du chapitre 14.5.1. Si nous avons tout fait correctement, nous exécuterons la tâche Gradle War sans erreur :
Application Web en Java - 11
Application Web en Java - 12

Lancer une application Web

Comment se lance une application web ? Parlons d'abord de l'option la plus complexe. Nous avons déjà dit qu'il existe un serveur Web Apache Tomcat qui prend en charge l'API Servlet. Cela signifie que nous pouvons déployer nos archives de guerre collectées (on dit aussi « déployer ») sur ce serveur. Sur la page « Télécharger Tomcat », téléchargez depuis la section « Distributions binaires » la livraison de type « Core » au format zip. Et décompressez l'archive téléchargée dans un répertoire, par exemple dans C:\apache-tomcat-9.0.14. Avant de démarrer le serveur, ouvrons le fichier pour l'éditer conf\tomcat-users.xmlet ajoutons-y la ligne suivante : <user username="tomcat" password="tomcat" roles="tomcat,manager-gui,admin-gui"/> Maintenant, sur la ligne de commande, allez dans le répertoire bin et exécutez catalina.bat start. Par défaut, la console du serveur sera disponible sur http://localhost:8080/manager. Le login et le mot de passe sont les mêmes que ceux que nous avons spécifiés dans tomcat-users.xml. Tomcat possède un répertoire "webapps", qui contient des applications Web. Si nous voulons déployer les nôtres, nous devons y copier nos archives de guerre. Lorsque nous avons précédemment exécuté la commande gradle war, \build\libs\une archive war a été créée dans le répertoire. C'est ce que nous devons copier. Après la copie, actualisez la page http://localhost:8080/manageret voyez :
Application Web en Java - 13
Après avoir terminé http://localhost:8080/javaweb/app, nous nous tournons vers notre servlet, car Nous avons précédemment « mappé » (c'est-à-dire mappé) la requête /app au servlet App. Il existe un moyen plus rapide de vérifier le fonctionnement de l'application. Et le système d’assemblage nous y aide encore une fois. Dans le script de build de notre projet Gradle, nous pouvons ajouter un nouveau plugin " Gretty " à la section plugins : id "org.gretty" version "2.3.1" Et maintenant nous pouvons effectuer une tâche gradle pour exécuter notre application :gradle appRun
Application Web en Java - 14
Voir « Ajouter le plugin Gretty et exécuter l'application » pour plus de détails.
Application Web en Java - 15

API Spring et Servlet

Les servlets sont la base de tout. Et même le désormais populaire Spring Framework n'est rien de plus qu'un module complémentaire à l'API Servlet. Pour commencer, le Spring Framework est une nouvelle dépendance pour notre projet. Par conséquent, ajoutons-le au script de construction dans le bloc de dépendances : compile 'org.springframework:spring-webmvc:5.1.3.RELEASE' Dans la documentation Spring Framework, il y a un chapitre " 1.1. DispatcherServlet ". Il indique que Spring Framework est construit sur le modèle "contrôleur frontal" - c'est-à-dire lorsqu'il existe un servlet central appelé " DispatcherServlet ". Toutes les requêtes parviennent à cette servlet et elle délègue les appels aux composants nécessaires. Vous voyez, même ici, il y a des servlets. Vous devez ajouter un écouteur au descripteur de déploiement :
<listener>
	&ltlistener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Il s'agit d'un écouteur d'événements contextuels de servlet. Autrement dit, lorsque le contexte de servlet démarre, le contexte Spring (WebApplicationContext) démarre également. Qu'est-ce que le contexte de servlet ? Elle est décrite dans la spécification Servle API dans le chapitre « CHAPITRE 4. Contexte du servlet ». Un contexte de servlet est une « vue » d'une servlet de l'application Web dans laquelle les servlets s'exécutent. Chaque application Web possède son propre contexte de servlet. Ensuite, pour activer Spring Framework, vous devez spécifier context-param - le paramètre d'initialisation pour le contexte du servlet.
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
Et la définition DispatcherServlet complète la configuration :
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
 		<param-value></param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>
Et maintenant, il ne nous reste plus qu'à remplir le fichier spécifié dans contextConfigLocation. La façon de procéder est décrite dans la documentation Spring Framework au chapitre « 1.3.1. Déclaration » :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="ru.javarush.javaweb"/>
    <mvc:annotation-driven/>
</beans>
Il est important ici non seulement d'indiquer quel paquet analyser, mais aussi que nous voulons être piloté par les annotations, c'est-à-dire contrôler les annotations sur le fonctionnement de Spring. Il ne reste plus qu'à créer le package ru.javarush.javaweb et à y placer la classe du contrôleur Spring :
package ru.javarush.javaweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SpringController {

    @GetMapping("/app")
    @ResponseBody
    public String getGreeting() {
        return "Hello world.";
    }
}
Maintenant, en exécutant Gradle AppRun et en allant à l'adresse, http://127.0.0.1:8080/javaweb/appnous obtiendrons le même Hello World. Comme vous pouvez le constater, Spring Framework est étroitement lié à l'API Servlet et l'utilise pour travailler dessus.
Application Web en Java - 16

Annotations

Comme nous l'avons vu, les annotations sont pratiques. Et nous n’étions pas les seuls à le penser. Par conséquent, dans la spécification de l'API Servlet, à partir de la version 3.0, le chapitre « CHAPITRE 8 Annotations et pluggabilité » est apparu, qui précise que les conteneurs de servlets doivent prendre en charge la possibilité de spécifier ce qui a été précédemment spécifié dans le descripteur de déploiement via des annotations. Ainsi, web.xml peut être complètement supprimé du projet, et au-dessus de la classe de servlet, vous pouvez spécifier l' annotation @WebServlet et indiquer le chemin vers lequel mapper le servlet. Tout semble clair ici. Mais et si nous connections Spring au projet, ce qui nécessite des réglages plus complexes ? Ici, tout est un peu plus compliqué. Tout d'abord, la documentation Spring indique que pour configurer Spring sans web.xml, vous devez utiliser votre propre classe qui implémentera WebApplicationInitializer. Pour plus de détails, voir le chapitre « 1.1. DispatcherServlet ». Il s'avère qu'il s'agit d'un cours de printemps. Comment alors l’API Servlet est-elle utilisée ici ? En fait, le ServletContainerInitializer a été ajouté à l'API Servlet 3.0 . À l'aide d'un mécanisme spécial en Java (appelé SPI ), Spring spécifie son initialiseur de conteneur de servlet appelé SpringServletContainerInitializer. À son tour, il recherche déjà les implémentations de WebApplicationInitializer, appelle les méthodes nécessaires et effectue les paramètres nécessaires. Voir « Comment le conteneur de servlet trouve les implémentations de WebApplicationInitializer » pour plus de détails. Les paramètres ci-dessus peuvent être effectués comme ceci :
package ru.javarush.javaweb.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class AppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        // регистрируем конфигурацию созданую высше
        ctx.register(AppConfig.class);
        // добавляем в контекст слушателя с нашей конфигурацией
        servletContext.addListener(new ContextLoaderListener(ctx));

        ctx.setServletContext(servletContext);

        // настраиваем маппинг Dispatcher Servlet-а
        ServletRegistration.Dynamic servlet =
                servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    }
}
Maintenant, en utilisant " Configuration basée sur Java ", nous indiquerons quel package analyser + activer les annotations :
package ru.javarush.javaweb.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ru.javarush.javaweb.controllers")
public class AppConfig {
}
Et le SpringController lui-même a été déplacé vers ru.javarush.javaweb.controllers, de sorte que lors de l'analyse, la configuration ne se retrouve pas, mais recherche uniquement les contrôleurs.
Application Web en Java - 17

Résumer

J'espère que cet aperçu a éclairé le fonctionnement des applications Web en Java. Ce n’est que la pointe de l’iceberg, mais sans comprendre les bases, il est difficile de comprendre comment fonctionnent les technologies basées sur ces fondations. L'API Servlet est la partie centrale de toute application Web Java, et nous avons examiné comment d'autres frameworks s'y intègrent. Pour continuer, vous pouvez consulter les documents suivants : #Viacheslav
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION