Tomcat 04 Deploiement Gestion Applications Tomcat

Déploiement et gestion des applications

1. Arborescence standard d’une application Web

Une application Web est définie comme une hiérarchie de répertoires et de fichiers dans un agencement standard. Une telle hiérarchie peut être accédée sous sa forme “décompressée”, où chaque répertoire et fichier existent séparément dans le système de fichiers, ou sous une forme “emballée” connue comme Web ARchive, ou fichier WAR. Le premier format est plus utile pendant le développement, tandis que le second est utilisé lorsque vous distribuez l’application à installer.

Le répertoire de niveau supérieur de la hiérarchie de l’application Web est également la racine du document de l’application. Ici, on placera les fichiers HTML et les pages JSP qui composent l’interface utilisateur de l’application. Lorsque l’administrateur système déploie l’application sur un serveur particulier, il affecte un chemin de contexte à celle-ci. Par exemple, si l’application est configurée avec le chemin de contexte /catalog, une requête URI se référant à /catalog/index.html récupère le fichier index.html à la racine du document.

Sample Application

dans le dossier $CATALINA_HOME/webapps :

ls /opt/tomcat/latest/webapps/
docs  examples  host-manager  manager  ROOT

Pour simplifier la création d’un fichier d’archive d’application Web dans le format standard, il est pratique d’organiser les fichiers “exécutables” de l’application Web (c’est-à-dire les fichiers que Tomcat utilise réellement pour exécuter l’application) dans la même organisation que le format WAR même l’exige.

  • Fichiers *.html, *.jsp, etc.
  • Fichier /WEB-INF/web.xml

Fichiers HTML, JSP et autres

Fichiers *.html, *.jsp, etc. Les pages HTML et JSP, ainsi que les autres fichiers qui doivent être visibles par le navigateur client (tels que JavaScript, fichiers de feuilles de style et images) pour l’application. Dans les applications plus grandes, on peut choisir de diviser ces fichiers dans une hiérarchie de sous-répertoires, mais pour les applications plus petites, il est généralement beaucoup plus simple de maintenir un seul répertoire pour ces fichiers.

Fichier /WEB-INF/web.xml

Le fichier /WEB-INF/web.xml est le descripteur de déploiement d’application Web pour l’application. Il s’agit d’un fichier XML décrivant les servlets et autres composants qui composent l’application, ainsi que les paramètres d’initialisation et les contraintes de sécurité gérées par conteneur que vous voulez que le serveur applique pour vous.

Comme l’extension du nom de fichier l’implique, ce fichier est un document XML, et définit tout ce qu’un serveur doit savoir sur l’application (à l’exception du chemin du contexte, qui est attribué par l’administrateur système lorsque l’application est déployée).

La syntaxe et la sémantique complètes du descripteur de déploiement sont définies au chapitre 13 de la spécification de l’API de servlet, version 2.3.

Voici un fichier de base pour l’exemple :

curl https://tomcat.apache.org/tomcat-9.0-doc/appdev/web.xml.txt

Et on obtient un exemple.

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>


    <!-- General description of your web application -->

    <display-name>My Web Application</display-name>
    <description>
      This is version X.X of an application to perform
      a wild and wonderful task, based on servlets and
      JSP pages.  It was written by Dave Developer
      (dave@mycompany.com), who should be contacted for
      more information.
    </description>


    <!-- Context initialization parameters that define shared
         String constants used within your application, which
         can be customized by the system administrator who is
         installing your application.  The values actually
         assigned to these parameters can be retrieved in a
         servlet or JSP page by calling:

             String value =
               getServletContext().getInitParameter("name");

         where "name" matches the <param-name> element of
         one of these initialization parameters.

         You can define any number of context initialization
         parameters, including zero.
    -->

    <context-param>
      <param-name>webmaster</param-name>
      <param-value>myaddress@mycompany.com</param-value>
      <description>
        The EMAIL address of the administrator to whom questions
        and comments about this application should be addressed.
      </description>
    </context-param>


    <!-- Servlet definitions for the servlets that make up
         your web application, including initialization
         parameters.  With Tomcat, you can also send requests
         to servlets not listed here with a request like this:

           http://localhost:8080/{context-path}/servlet/{classname}

         but this usage is not guaranteed to be portable.  It also
         makes relative references to images and other resources
         required by your servlet more complicated, so defining
         all of your servlets (and defining a mapping to them with
         a servlet-mapping element) is recommended.

         Servlet initialization parameters can be retrieved in a
         servlet or JSP page by calling:

             String value =
               getServletConfig().getInitParameter("name");

         where "name" matches the <param-name> element of
         one of these initialization parameters.

         You can define any number of servlets, including zero.
    -->

    <servlet>
      <servlet-name>controller</servlet-name>
      <description>
        This servlet plays the "controller" role in the MVC architecture
        used in this application.  It is generally mapped to the ".do"
        filename extension with a servlet-mapping element, and all form
        submits in the app will be submitted to a request URI like
        "saveCustomer.do", which will therefore be mapped to this servlet.

        The initialization parameter names for this servlet are the
        "servlet path" that will be received by this servlet (after the
        filename extension is removed).  The corresponding value is the
        name of the action class that will be used to process this request.
      </description>
      <servlet-class>com.mycompany.mypackage.ControllerServlet</servlet-class>
      <init-param>
        <param-name>listOrders</param-name>
        <param-value>com.mycompany.myactions.ListOrdersAction</param-value>
      </init-param>
      <init-param>
        <param-name>saveCustomer</param-name>
        <param-value>com.mycompany.myactions.SaveCustomerAction</param-value>
      </init-param>
      <!-- Load this servlet at server startup time -->
      <load-on-startup>5</load-on-startup>
    </servlet>

    <servlet>
      <servlet-name>graph</servlet-name>
      <description>
        This servlet produces GIF images that are dynamically generated
        graphs, based on the input parameters included on the request.
        It is generally mapped to a specific request URI like "/graph".
      </description>
    </servlet>


    <!-- Define mappings that are used by the servlet container to
         translate a particular request URI (context-relative) to a
         particular servlet.  The examples below correspond to the
         servlet descriptions above.  Thus, a request URI like:

           http://localhost:8080/{contextpath}/graph

         will be mapped to the "graph" servlet, while a request like:

           http://localhost:8080/{contextpath}/saveCustomer.do

         will be mapped to the "controller" servlet.

         You may define any number of servlet mappings, including zero.
         It is also legal to define more than one mapping for the same
         servlet, if you wish to.
    -->

    <servlet-mapping>
      <servlet-name>controller</servlet-name>
      <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
      <servlet-name>graph</servlet-name>
      <url-pattern>/graph</url-pattern>
    </servlet-mapping>


    <!-- Define the default session timeout for your application,
         in minutes.  From a servlet or JSP page, you can modify
         the timeout for a particular session dynamically by using
         HttpSession.getMaxInactiveInterval(). -->

    <session-config>
      <session-timeout>30</session-timeout>    <!-- 30 minutes -->
    </session-config>


</web-app>

Ou encore celui d’une application locale “examples”

cat /opt/tomcat/latest/webapps/examples/WEB-INF/web.xml

Répertoire /WEB-INF/classes/

Le répertoire /WEB-INF/classes/ contient tous les fichiers de classes Java (et les ressources associées) nécessaires à l’application, y compris les classes de servlets et de non-servlets, qui ne sont pas combinés en fichiers JAR. Si les classes sont organisées en paquets Java, on doit le refléter dans la hiérarchie des répertoires sous /WEB-INF/classes/. Par exemple, une classe Java nommée com.mycompany.mypackage.mypackage.myServlet devrait être stockée dans un fichier nommé /WEB-INF/classes/com/mycompany/mypackage/MyServlet.class.

Répertoire /WEB-INF/lib/

Le répertoire /WEB-INF/lib/ contient les fichiers JAR qui contiennent les fichiers de classe Java (et les ressources associées) requis pour l’application, tels que les bibliothèques de classe tierces ou les pilotes JDBC.

Lorsqu’on installe une application dans Tomcat (ou tout autre conteneur de Servlet 2.2 ou ultérieur), les classes du répertoire WEB-INF/classes/, ainsi que toutes les classes des fichiers JAR du répertoire WEB-INF/lib/, sont rendues visibles aux autres classes de l’application Web particulière. Ainsi, si on inclue toutes les classes de bibliothèque requises à l’un de ces endroits, on simplifiera l’installation de l’application Web - aucun ajustement au chemin de la classe système (ou installation des fichiers de bibliothèque globale dans le serveur) ne sera nécessaire.

Descripteur de contexte

Un fichier /META-INF/context.xml peut être utilisé pour définir les options de configuration spécifiques à Tomcat, telles qu’un journal des accès, les sources de données, la configuration du gestionnaire de session, etc. Ce fichier XML doit contenir un élément “Contexte”, qui sera considéré comme l’enfant de l’élément Hôte correspondant à l’Hôte sur lequel l’application Web est déployée.

La page Tomcat configuration documentation donne plus d’informations sur la configuration des contextes.

2. Méthodes de déploiement avec Tomcat

Tomcat 9.0 Application Developer’s Guide, Deployment

La description ci-dessous utilise le nom de variable $CATALINA_BASE pour référencer le répertoire de base à partir duquel la plupart des chemins relatifs sont résolus. Si vous n’avez pas configuré Tomcat pour plusieurs instances en définissant un répertoire CATALINA_BASE, alors $CATALINA_BASE sera mis à la valeur $CATALINA_HOME, le répertoire dans lequel vous avez installé Tomcat.

Pour être exécutée, une application Web doit être déployée sur un conteneur de servlet. Ceci est vrai même pendant le développement. Nous décrirons l’utilisation de Tomcat pour fournir un environnement d’exécution. Une application web peut être déployée dans Tomcat par l’une des approches suivantes.

  1. Copier la hiérarchie des répertoires décompressés.
  2. Copier le fichier d’archive de l’application Web.
  3. Via l’application Web “Tomcat Manager”.
  4. Avec des tâches de Ant “Manager” dans le script de construction.
  5. Avec Tomcat Deployer
  6. À partir de projets Maven

Copier la hiérarchie des répertoires décompressés

On peut copier la hiérarchie des répertoires décompressés dans un sous-répertoire du répertoire $CATALINA_BASE/webapps/. Tomcat assignera un chemin de contexte à l’application en fonction du nom du sous-répertoire qui a été choisi. On utilisera cette technique dans le fichier build.xml que l’on construit, car c’est l’approche la plus rapide et la plus simple lors du développement. Il faut s’assurer du redémarrage de Tomcat après avoir installé ou mis à jour l’application.

Copier le fichier d’archive de l’application Web

On peut copier le fichier d’archive de l’application Web dans le répertoire $CATALINA_BASE/webapps/. Lorsque Tomcat est démarré, il développera automatiquement le fichier d’archive de l’application Web dans sa forme décompressée et exécutera l’application de cette façon. Cette approche est généralement utilisée pour installer une application supplémentaire, fournie par un fournisseur tiers ou par votre équipe de développement interne, dans une installation Tomcat existante. REMARQUE - Si on utilise cette approche et que l’on souhaite mettre à jour l’application ultérieurement, on doit remplacer le fichier d’archive de l’application Web ET supprimer le répertoire étendu que Tomcat a créé, puis redémarrer Tomcat, afin de refléter les modifications.

Via l’application Web “Tomcat Manager”

Tomcat inclut une application Web, déployée par défaut sur le chemin de contexte /manager, qui permet de déployer et de désinstaller des applications sur un serveur Tomcat en cours d’exécution sans redémarrer celui-ci. Pour plus d’informations sur l’utilisation de l’application Web Manager, voir plus bas.

Avec des tâches de Ant “Manager” dans le script de construction

Tomcat inclut un ensemble de définitions de tâches personnalisées pour l’outil de construction Ant qui permettent d’automatiser l’exécution des commandes de l’application web “Manager”. Ces tâches sont utilisées dans le déploiement Tomcat.

Avec Tomcat Deployer

Tomcat inclut un outil packagé regroupant les tâches Ant, et peut être utilisé pour pré-compiler automatiquement les JSPs qui font partie de l’application web avant le déploiement sur le serveur.

À partir de projets Maven

3. Déploiement par copie

Le scénario est le suivant. Les développeurs vous fournissent un fichier war prêt à être déployé.

Livraison du fichier JAR.

wget https://tomcat.apache.org/tomcat-9.0-doc/appdev/sample/sample.war -O /opt/tomcat/latest/work/sample.war
chown tomcat: /opt/tomcat/latest/work/sample.war

Examen du fichier JAR.

mkdir tmp
cd tmp/
jar -xvf /opt/tomcat/latest/work/sample.war
  created: META-INF/
 inflated: META-INF/MANIFEST.MF
  created: WEB-INF/
  created: WEB-INF/classes/
  created: WEB-INF/classes/mypackage/
  created: WEB-INF/lib/
  created: images/
 inflated: WEB-INF/classes/mypackage/Hello.class
 inflated: WEB-INF/web.xml
 inflated: hello.jsp
 inflated: images/tomcat.gif
 inflated: index.html
[root@tomcatdev0 tmp]# tree ./
./
├── hello.jsp
├── images
│   └── tomcat.gif
├── index.html
├── META-INF
│   └── MANIFEST.MF
└── WEB-INF
    ├── classes
    │   └── mypackage
    │       └── Hello.class
    ├── lib
    └── web.xml

6 directories, 6 files

Visualisation des logs.

tail -f /opt/tomcat/latest/logs/catalina.out &

Déploiement de l’application.

mv /opt/tomcat/latest/work/sample.war /opt/tomcat/latest/webapps/

Affichage des logs.

30-Mar-2019 11:32:49.002 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/opt/tomcat/apache-tomcat-9.0.17/webapps/sample.war]
30-Mar-2019 11:32:49.098 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [/opt/tomcat/apache-tomcat-9.0.17/webapps/sample.war] has finished in [96] ms

Retirer une application

mv /opt/tomcat/latest/webapps/sample.war /opt/tomcat/latest/work/

Affichage des logs.

30-Mar-2019 11:34:09.615 INFO [Catalina-utility-1] org.apache.catalina.startup.HostConfig.undeploy Undeploying context [/sample]

4. L’application Tomcat Manager

Source : Manager App How-To

Dans de nombreux environnements de production, il est très utile d’avoir la capacité de déployer une nouvelle application Web, ou de retirer une application existante sans avoir à arrêter et redémarrer le conteneur entier. En outre, on peut demander à une application existante de se recharger elle-même, même si on ne l’a pas déclarée rechargeable dans le fichier de configuration de serveur Tomcat.

Pour prendre en charge ces fonctionnalités, Tomcat inclut une application Web (installée par défaut sur le chemin de contexte /manager) qui prend en charge les fonctions suivantes :

  • Déployer une nouvelle application Web à partir du contenu téléchargé d’un fichier WAR.
  • Déployer une nouvelle application Web, sur un chemin de contexte spécifié, à partir du système de fichiers du serveur.
  • Énumérer les applications Web actuellement déployées, ainsi que les sessions qui sont actuellement actives pour ces applications Web.
  • Recharger une application Web existante, pour refléter les changements dans le contenu de /WEB-INF/classes ou /WEB-INF/lib.
  • Énumérer les valeurs des propriétés OS et JVM.
  • Énumérer les ressources JNDI globales disponibles, à utiliser dans les outils de déploiement qui préparent des éléments <ResourceLink> imbriqués dans un <Contexte> description de déploiement.
  • Démarrer une application arrêtée (la rendant ainsi à nouveau disponible).
  • Arrêter une application existante (pour qu’elle devienne indisponible).
  • Retirer une application Web déployée et supprimer son répertoire de base de documents (à moins qu’elle n’ait été déployée à partir du système de fichiers).

Il y a trois façons d’utiliser l’application Web Manager.

  • En tant qu’application avec une interface utilisateur que vous utilisez dans votre navigateur. Voici un exemple d’URL où vous pouvez remplacer localhost par le nom d’hôte de votre site web : http://localhost:8080/manager/html.
  • Une interface texte. Une version minimale utilisant uniquement des requêtes HTTP qui convient à l’utilisation par les administrateurs système pour la configuration des scripts. Les commandes sont données dans le cadre de l’URI de la requête, et les réponses se présentent sous la forme d’un texte simple qui peut être facilement analysé et traité. Voir Commandes Manager supportées pour plus d’informations.
  • Un ensemble pratique de définitions de tâches pour l’outil de construction Ant (version 1.4 ou supérieure).

5. Interface texte

Le rôle manager-script doit être associé à l’utilisateur dans le fichier tomcat-users.xml

   <role rolename="manager-script"/>
   <user username="usertext" password="testtest" roles="manager-script"/>

Charger l’url authentifiée en variable :

url="http://usertext:testtest@127.0.0.1:8080/manager/text"

Liste des informations sur la version Tomcat, de l’OS et des propriétés de la JVM

curl $url/serverinfo
OK - Server info
Tomcat Version: [Apache Tomcat/9.0.17]
OS Name: [Linux]
OS Version: [4.4.127-mainline-rev1]
OS Architecture: [amd64]
JVM Version: [11.0.2+7-LTS]
JVM Vendor: [Oracle Corporation]

La liste des ressources JNDI globales disponibles

curl $url/resources
OK - Listed global resources of all types
UserDatabase:org.apache.catalina.users.MemoryUserDatabase

VM Info

curl $url/vminfo
OK - VM info

Thread Dump

curl $url/threaddump -o dump.txt

Sauvegarde

Si elle est spécifiée sans aucun paramètre, cette commande enregistre la configuration actuelle du serveur dans server.xml. Le fichier existant sera renommé en tant que sauvegarde si nécessaire.

Si elle est spécifiée avec un paramètre de chemin qui correspond au chemin d’accès d’une application Web déployée, la configuration de cette application Web sera enregistrée dans un fichier context.xml nommé de manière appropriée dans xmlBase pour l’hôte courant.

curl $url/save

Pour utiliser la commande, un StoreConfig MBean doit être présent. En règle générale, cela se configure à l’aide du StoreConfigLifecycleListener.

Si la commande échoue, la réponse commencera par FAIL et inclura un message d’erreur.

Statut du serveur

curl http://usertext:testtest@127.0.0.1:8080/manager/status?XML=true
curl http://usertext:testtest@127.0.0.1:8080/manager/status/all?XML=true

Liste des applications

curl $url/list
OK - Listed applications for virtual host [localhost]
/:running:0:ROOT
/examples:running:0:examples
/host-manager:running:0:host-manager
/manager:running:2:manager
/docs:running:0:docs

Redémarrer une application

curl $url/reload?path=/examples
OK - Reloaded application at context path [/examples]
curl $url/reload?path=/test
FAIL - No context exists named [&#47;test]

Arrêter une application

curl $url/stop?path=/examples
OK - Stopped application at context path [/examples]

Démarrer une application

curl $url/start?path=/examples
OK - Started application at context path [/examples]

Statistiques des sessions

curl $url/sessions?path=/examples

Sessions expirées

curl $url/expire?path=/examples&idle=num

Déployer un nouveau WAR à distance

curl --upload-file /opt/tomcat/latest/work/sample.war "$url/deploy?path=/sample&update=true"
OK - Deployed application at context path [/sample]
curl --upload-file /opt/tomcat/latest/work/sample.war "$url/deploy?path=/sample2&update=true"
OK - Deployed application at context path [/sample2]

Retirer une application (undeploy)

curl $url/undeploy?path=/sample2

Déployer une nouvelle application à partir d’un chemin local

5. Interface HTML GUI

Tomcat Web Application Manager How To

6. Déploiement avec ANT et un fichier build.xml

Apache Ant

Executing Manager Commands With Ant

Source Organization et Development Processes

Déploiement à partir d’un IDE local : https://stackoverflow.com/questions/1056829/netbeans-deploying-java-app-to-remote-tomcat

Voir aussi 2.7 STEP 6: Write a “Hello-world” Java Servlet

6. Application avec base de donnée

Exemple

Source de l’exemple : MySQL DBCP 2 Example

Installation de MariaDB

yum install -y mariadb mariadb-server
systemctl start mariadb && systemctl enable mariadb

Il s’agit de profiter de l’absence de mot de passe sur le compte root pour créer la base et l’utilisateur de la base de données.

dbuser="user"
dbuser_password="testtest"
dbroot_password="testtest"
db_name="javatest"

Création de l’utilisateur et de la base de donnée

database_creation() {
# Create dbuser
mysql -e "CREATE USER ${dbuser}@localhost IDENTIFIED BY '${dbuser_password}';"
# Create database
mysql -e "CREATE DATABASE ${db_name};"
mysql -e "USE ${db_name}; CREATE table testdata (id int not null auto_increment primary key,foo varchar(25),bar int); INSERT into testdata values(null, 'hello', 12345);"
# Fix dbuser rights on database
mysql -e "GRANT ALL ON ${db_name}.* TO ${dbuser}@localhost;"
# Make our changes take effect
mysql -e "FLUSH PRIVILEGES"
}

Sécurisation de type mysql_secure

mysql_secure() {
# mysql_secure_installation as model
# Make sure that NOBODY can access the server without a password
mysql -e "UPDATE mysql.user SET Password = PASSWORD('${dbroot_password}') WHERE User = 'root'"
# Kill the anonymous users
mysql -e "DROP USER ''@'localhost'"
# Because our hostname varies we'll use some Bash magic here.
mysql -e "DROP USER ''@'$(hostname)'"
# Kill off the demo database
mysql -e "DROP DATABASE test"
# Make our changes take effect
mysql -e "FLUSH PRIVILEGES"
}

Installation du connecteur mysql

wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.15.tar.gz
tar xvfz mysql-connector-java-8.0.15.tar.gz
cp mysql-connector-java-8.0.15/mysql-connector-java-8.0.15.jar /opt/tomcat/latest/lib/

Arborescence de l’application

.
├── META-INF
│   └── context.xml
├── test.jsp
└── WEB-INF
    └── web.xml

Création de l’arborescence :

mkdir DBTest
mkdir -p DBTest/META-INF
mkdir -p DBTest/WEB-INF
touch DBTest/test.jsp
touch DBTest/META-INF/context.xml
touch DBTest/WEB-INF/web.xml

Fichier META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/TestDB" docBase="TestDB" reloadable="true" crossContext="true">
  <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxTotal="100" maxIdle="30" maxWaitMillis="10000"
               username="user" password="testtest" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>
</Context>

Fichier WEB-INF/web.xml

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
  <description>MySQL Test App</description>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

Fichier test.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<sql:query var="rs" dataSource="jdbc/TestDB">
select id, foo, bar from testdata
</sql:query>

<html>
  <head>
    <title>DB Test</title>
  </head>
  <body>

  <h2>Results</h2>

<c:forEach var="row" items="${rs.rows}">
    Foo ${row.foo}<br/>
    Bar ${row.bar}<br/>
</c:forEach>

  </body>
</html>

L’application utilise la libraire JSTL qu’il est nécessaire d’installer. JavaServer Pages Standard Tag Library (JSTL) encapsule comme de simples balises la fonctionnalité de base commune à de nombreuses applications Web. JSTL prend en charge les tâches structurelles courantes telles que les itérations et les conditionnels, les balises pour manipuler les documents XML, les balises d’internationalisation et les balises SQL. Il fournit également un cadre pour l’intégration des balises personnalisées existantes avec les balises JSTL.

wget http://central.maven.org/maven2/javax/servlet/jstl/1.2/jstl-1.2.jar -o /opt/tomcat/latest/lib/
cd
cp -R DBTest /opt/tomcat/latest/webapps/
chown tomcat: /opt/tomcat/latest/webapps/DBTest
tail /opt/tomcat/latest/logs/catalina.out
curl http://127.0.0.1:8080/DBTest/test.jsp
<html>
  <head>
    <title>DB Test</title>
  </head>
  <body>

  <h2>Results</h2>


    Foo hello<br/>
    Bar 12345<br/>


  </body>
</html>