Programmation Web Tomcat et les Servlets
Feb 07, 2016
Programmation Web
Tomcat et les Servlets
Spécification J2EE
• Servlet, JSP
• JAX (JAX-P, JAX-B, JAX-R, JAX-RPC)
• JNDI, JMS
• EJB, JTA, JTS
• JavaMail, JDBC
• JMX, J2EE Connector, etc.
Application multi-tiers
L’application Web est décomposée
en plusieurs parties (tiers)
Conteneurs de Servlet
• Tomcat 4.1
• IronFlare Orion 1.5
• Jetty 4.1
• Caucho Resin 2.1
• Sun ONE 7.0
• IBM WebSphere 4.0
• BEA WebLogic 7.0
Tomcat
• Tomcat 4.1 (Catalina)
• Projet Apache (Apache Apache Httpd)
• Open source
• Implantation de référence de la spécification
• Spécification Servlet 2.3 et JSP 1.2(bientôt Servlet 2.4 et JSP 2.0)
Servlet & ConteneurLe conteneur de servlets associe à
des URLs virtuels une servlet
Browser HTTP
Conteneur de Servlets
/admin/*
/vignette/*.html
/examples/*.html
servlet 1
servlet 2
Requête
Réponse
Répertoire de TomcatOrganisation des répertoires de Tomcat
/bin/common/lib/conf/logs/server/lib/shared/lib/webapps
scripts startup & shutdown
jar utilisés par Tomcat (Ant, Servlet, etc.)
configuration: server.xml, web.xml, users.xml
fichiers de logs
fichiers jar propres à tomcat
fichiers jar communs à toutes les servlets
zone de déploiement
Configuration TomcatLe fichier server.xml
• Server Racine, spécifie le port de shutdown.
• ServiceAssocie des connecteurs à un engine.
• ConnectorIls correspondent à un point d’accès à un service,soit via un serveur soit en connexion directe.
• Engine correspond au conteneur de servlet en lui-même.
• Logger Ils effectuent la journalisation.
• HostDéclare où sont stockées les servlets pour un nom de machine.
• ContextChaque Context représente la configuration associée à un chemindans la hiérarchie
Un Connector point d’accès utilisable par un client :• port="8080"• minProcessors="5" • maxProcessors="75"• enableLookups="true" • acceptCount="100" • connectionTimeout="20000"
Le conteneur Engine• name="Standalone" • defaultHost="localhost"
Configuration Tomcat (2)port d’écoute
nombre de threads minimum
nombre de threads maximum
DNS inverse
nombre de connections pendantes
Nom de l’host si pas HTTP 1.1
Configuration Tomcat (3)
Le Logger effectue la journalisation des requêtes• prefix="catalina_log. "• suffix=".txt"• timestamp="true"
Le tag Host définit les paramètres pour un host virtuel• name="localhost" • appBase="webapps" • unpackWARs="true" • autoDeploy="true"
Configuration Tomcat (4)Gestion des associations entre un URI
et un chemin sur le disque
URI d’accès
Chemin d’accès des fichiers(relatif ou absolu par rapport à webapps)
Détection automatique des changementset rechargement si besoin
Un Context représente l’association entre un cheminsur le serveur (URI) et un chemin sur le disque
• path= "/examples"• docBase="examples"• reloadable="true"
Architecture d’une appli WebUne application Web possède dans un
repertoire lui-même dans webapps une architecture spécifique
*.html, *.jsp/WEB-INF/web.xml/WEB-INF/classes//WEB-INF/lib/
fichiers HTML
fichier de configuration (XML)
classes des servlets
fichiers jar des servlets
L’ensemble des fichiers et répertoire peut être mis dans un war (Web Archive)grâce à la commande jar. Le war est automatiquement dé-jarré s’il est placé
dans le répertoire webapps.
Configuration d’une appli WebLe fichier web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app> <display-name>Mon application Web</display-name> <servlet> <servlet-name>maServlet</servlet-name> <servlet-class>fr.umlv.myservlet.MaServlet</servlet-class> </servlet>
<servlet-mapping> <servlet-name>maServlet</servlet-name> <url-pattern>*.test</url-pattern> </servlet-mapping>
<servlet-mapping> <servlet-name>maServlet</servlet-name> <url-pattern>/toto</url-pattern> </servlet-mapping></web-app>
nom de la servletnom de la servletnom de la servlet
URI d’accèsURI d’accès
Configuration d’une appli WebParamètres d’initialisation d’une servlet
<servlet> <servlet-name>maServlet</servlet-name> <servlet-class>fr.umlv.myservlet.MaServlet</servlet-class> <init-param> <param-name>parametre1</param-name> <param-value>valeur1</param-value> </init-param> <init-param> <param-name>parametre2</param-name> <param-value>valeur2</param-value> </init-param></servlet>
association name/value
Generic vs HTTP Servlet
Il existe deux types de servlets
• Les GenericServlet qui ne pré-suppose pas d’un protocole
• Les HttpServlet qui repondent à des clients par le protocole HTTP
GenericServlet est une classe du paquetage javax.servlet tandis queHttpServlet est une classe du paquetage javax.servlet.http
La synchronisation est gérée par l’objet Response
Cycle de vie d’une servlet
Le cycle de vie d'une servlet : 1.la méthode init() est appelée après le
chargement ; 2.une méthode service() est appelée à
chaque requête dans une nouvelle thread.
3.la méthode destroy() est appelée pour le déchargement.
HelloServletLa méthode service() est appelée avec
un objet requête et un objet réponse
import java.io.*;import javax.servlet.*;
public class HelloServlet extends GenericServlet {
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { PrintStream out = new PrintStream(response.getOutputStream()); out.println("Hello World!"); } public String getServletInfo() { return "Hello World Servlet"; } } L’objet réponse permet d’obtenir
le flux de sortie en écritureInformation textuelle sur la servlet
L’interface RequestL'interface ServletRequest permet de récupérer les paramètres de la requête :
public abstract int getContentLength() public abstract String getContentType() public abstract String getProtocol() public abstract String getScheme() public abstract String getServerName() public abstract int getServerPort() public abstract String getRemoteAddr() public abstract String getRemoteHost() public abstract ServletInputStream getInputStream() throws IOException public abstract String getParameter(String name) public abstract String[] getParameterValues(String name) public abstract Enumeration getParameterNames() public abstract Object getAttribute(String name)
Description du client
Il est possible de rajouterdes attributs (non HTTP)
Description du serveur
L’interface Response
L'interface ServletResponse permet de renvoyer une réponse :public abstract void setContentLength(int length) public abstract void setContentType(String type) public abstract ServletOutputStream getOutputStream() throws IOException
L’objet réponse permet d’obtenirle flux de sortie en écriture
Type de contenu auformat MIME
Taille de la réponse(peut être omis)
Fichier de configurationLe fichier web.xml correspondant
<?xml version="1.0" encoding="ISO-8859-1"?><!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> <display-name>Appli de Demo</display-name> <description>Ceci est une série de servlets de démo</description>
<servlet> <servlet-name>hello</servlet-name> <servlet-class>fr.umlv.servletdemo.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello.html</url-pattern> </servlet-mapping></web-app>
Le ‘/’ ici est par rapportà l’application Web
Hello World
Le conteneur de servlets fait l’association entre
l’URL et la servlet
Hello World (2)Répertoires sur le serveur
Les servlets HTTP
• La méthode service de la classe HttpServlet est déjà implantée et redirige les requêtes vers les méthodes do*
• Les méthodes sont doDelete, doGet, doHead, doOptions, doPost, doPut, doTrace
protected void do*(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException
HTTP HelloWorldHelloWorld réécrit avec une servlet HTTP
import java.io.*;import javax.servlet.*;import javax.servlet.http.*;
public class HelloHttpServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); PrintWriter out = response.getWriter(); out.println("HTTP Hello World!"); } public String getServletInfo() { return "HTTP Hello World Servlet"; } }
L’objet réponse permet d’obtenirle flux de sortie en écriture
Informations sur la requête
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); PrintWriter out= response.getWriter(); out.println("Protocol: " + request.getProtocol()); out.println("Scheme: " + request.getScheme()); out.println("ServerName: " + request.getServerName()); out.println("ServerPort: " + request.getServerPort()); out.println("RemoteAddr: " + request.getRemoteAddr()); out.println("RemoteHost: " + request.getRemoteHost()); out.println("Method: " + request.getMethod()); out.println("requestuestURI: " + request.getRequestURI()); out.println("ServletPath: " + request.getServletPath()); out.println("PathInfo: " + request.getPathInfo()); out.println("PathTranslated: " + request.getPathTranslated()); out.println("QueryString: " + request.getQueryString()); out.println("RemoteUser: " + request.getRemoteUser()); out.println("AuthType: " + request.getAuthType()); }
GET, POST, PUT etc.
Chemin virtuel complet
Chemin de laressource
Chemin sur le serveur
Chemin de la servlet
Informations sur la requête (2)Déclaration de la servlet « header »
<servlet> <servlet-name>header</servlet-name> <servlet-class>fr.umlv.servletdemo.HeaderServlet</servlet-class></servlet><servlet> …</servlet>...<servlet-mapping> <servlet-name>header</servlet-name> <url-pattern>/header/*</url-pattern></servlet-mapping>
Définition des servlets
Chemin de la servlet
Définition des associations
Informations sur la requête (3)
Informations sur la requête
URL complète
Entêtes de la requêteEn-tête = Informations envoyées par le browser
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain"); PrintWriter out= response.getWriter();
Enumeration e= request.getHeaderNames(); for (; e.hasMoreElements();) { String name= (String) e.nextElement(); out.println(name + ' ' + request.getHeader(name)); }}
Ensemble des nomsdes entêtes
Valeur d’un entête
En-têtes de la requête
Entêtes
Informations sur la requête
Réponse HTTPL’objet HttpServletResponse permet en
plus de renvoyer des codes d’erreurs
public class HttpRedirectServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if ("/index.html".equals(request.getPathInfo())) response.sendRedirect("/demo/header/index.html"); else response.sendError(HttpServletResponse.SC_NOT_FOUND); } }
Redirection HTTPSC = Status Code
Paramètres d’initialisationLes paramètres sont déclarés dans le
fichier web.xml
<servlet> <servlet-name>initParam</servlet-name> <servlet-class>fr.umlv.servletdemo.InitParamServlet</servlet-class> <init-param> <param-name>count</param-name> <param-value>5</param-value> </init-param> <init-param> <param-name>message</param-name> <param-value>hello config</param-value> </init-param></servlet>
Paramètres d’initialisation (2)L’objet ServletConfig permet de récupérer
les paramètrespublic class InitParamServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain"); PrintWriter out= response.getWriter(); for(int i=0;i<count;i++) { out.println(message); } } public void init(ServletConfig config) throws ServletException { count = Integer.parseInt(config.getInitParameter("count")); message = config.getInitParameter("message"); } private int count; private String message;}
Demande la valeur duparamètre "count"
Paramètres d’initialisation (3)Le destroy doit libérer les ressources !!
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { … }
public void init(ServletConfig config) throws ServletException { super.init(config); count = Integer.parseInt(config.getInitParameter("count")); message = config.getInitParameter("message"); }
public void destroy() { message=null; } private int count; private String message;
Stockage des paramètres
Libération des paramètres
Les formulaires
Deux méthodes de passage de paramètres :
• GET (dans l’URL)
• POST (dans la requête HTTP)
Gestion uniforme au niveau des servlets
Les formulaires GET
HTML pour la méthode GET
<form enctype="application/x-www-form-urlencoded" action="subscribe" method=GET> Titre : <select name=title> <option value="Mr">Mr <option value="Ms">Mme </select> Nom : <input type=text size=20 name=username> Prénom : <input type=text size=20 name=firstname> <hr> <input type=submit value="Envoi"> <input type=reset value="Réinitialiser"> </form>
Les formulaires GET (2)Utilisation des méthodes getParameter*()
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html"); PrintWriter out= response.getWriter(); out.println("<html><body bgcolor=\"white\">");
Enumeration e=request.getParameterNames(); for(;e.hasMoreElements();) { String name=(String)e.nextElement(); String value=request.getParameter(name);
out.println(name+'='+value+"<br>"); } out.println("</body></html>"); }
Ensemble des paramètresde la requète
Valeurs d’un paramètrede la requète
Les formulaires POSTHTML pour la méthode POST
<form enctype="application/x-www-form-urlencoded" action="subscribe" method=POST> Titre : <select name=title> <option value="Mr">Mr <option value="Ms">Mme </select> Nom : <input type=text size=20 name=username> Prénom : <input type=text size=20 name=firstname> <hr> <input type=submit value="Envoi"> <input type=reset value="Réinitialiser"> </form>
Les formulaires POST (2)Utilisation des méthodes getParameter*()protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html"); PrintWriter out= response.getWriter(); out.println("<html><body bgcolor=\"white\">");
Enumeration e=request.getParameterNames(); for(;e.hasMoreElements();) { String name=(String)e.nextElement(); String value=request.getParameter(name);
out.println(name+'='+value+"<br>"); }
out.println("</body></html>"); }
Ensemble des paramètresde la requète
Valeurs d’un paramètrede la requète
Inclusion & Redirection
• L’interface RequestDispatcher :- include(request,response)- forward(request,response)
• Obtenir un RequestDispatcher :getServletContext().getRequestDispatcher(path)
Chemin correspondant• soit à une servlet• soit à un fichier
Inclusion & Redirection (2)La redirection n’est pas visible au niveau du client
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
getServletContext().getRequestDispatcher("/index.html"). forward(request,response); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html"); getServletContext().getRequestDispatcher("/hello.html"). include(request,response); getServletContext().getRequestDispatcher("/hello.html"). include(request,response); }
L’inclusion permet d’inclure plusieurs fois des ressources
fichier
servlet
Inclusion & Redirection (3)Plusieurs problèmes :• Forward :
- ne pas faire de setContentType() avant- ne rien faire après un forward sur le flux de sortie
• Inclusion :- eviter setContentType() après,- enlever les balises <html> et <body> dans la ressource inclue
Session
Permettre de garder des informations d’une requête à l’autre
• Problème :HTTP est un protocole sans état
• Solutions :– Authentification– Session (Cookie, URL rewriting)
Session (2)L’objet HttpSession gère les sessions
Création :request.getSession()request.getSession(boolean create)
Gestion d’association clé/valeur :session.getAttributeNames()session.getAttribute(String name)session.setAttribute(String name, Object value)session.removeAttribute(String name)
Destruction :session. invalidate()session. logout()
Invalide toutes les sessionspour un client
Créé une session sinon existante
Session (3)
Ouverture et fermeture
d’une session
Session (4)Requête GET sur la servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html"); PrintStream out = new PrintStream(response.getOutputStream()); out.println("<html><body bgcolor=\"white\">");
HttpSession session=request.getSession(false); if (session!=null) { out.println("<h1>Welcome "+session.getAttribute("username")+ ' '+session.getAttribute("firstname")+"</h1><hr>"); }
getServletContext().getRequestDispatcher("/session-part.html"). include(request,response);
out.println("</body></html>"); }
Demande une sessionsans création automatique
Session (5)Requête POST sur la servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session=request.getSession();
if (request.getParameter("logout")==null) { session.setAttribute("username", request.getParameter("username")); session.setAttribute("firstname", request.getParameter("firstname")); } else session.invalidate();
doGet(request,response); } Demande une session
avec création automatique
AuthentificationTypes d’autorisation
(BASIC, DIGEST, FORM)
GET / HTTP/1.0
HTTP/1.0 401 UnauthorizedWWW-Authenticate: Basic realm="univ-mlv"
GET / HTTP/1.0Autorisation: Basic RntGDOujujO=
Browser Serveur
Login:mot de passe en base64
Authentification (2)
• À la mainvérifie la sécurité dans la servlet
• Gérée par le conteneur de servletsspécifie un domaine de sécurité dans le web.xml
Authentification à la mainDemande d’authentification : WWW-Authenticate
public class Authentication1Servlet extends HttpServlet { protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
String user; String authorization = request.getHeader("Authorization"); if (authorization == null || (user=check(authorization))==null) { response.setHeader("WWW-Authenticate", "Basic realm=\"univ-mlv\""); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return; } response.setContentType("text/plain"); response.getWriter().println("Welcome "+user); } …
Authentification à la main (2)Réponse à la demande : Authorization
private String check(String authorization) throws ServletException,IOException { if (!authorization.toLowerCase().startsWith(BASIC_SCHEME)) throw new ServletException("unrecognized authentication scheme");
String creditBase64= authorization.substring(1+BASIC_SCHEME.length()); sun.misc.BASE64Decoder decoder= new sun.misc.BASE64Decoder(); byte[] credit= decoder.decodeBuffer(creditBase64); String str= new String(credit);
int index= str.indexOf(':'); String user= str.substring(0, index); String passwd= str.substring(index + 1);
return (passwd.equals("toto"))?user:null;}
private static final String BASIC_SCHEME="basic";}
Header :Autorisation: Basic RntGDOujujO=
Credit :login:password
Authentification : les rôlesUn sous-domaine est protégé par un rôle
<servlet-mapping> <servlet-name>authentication2</servlet-name> <url-pattern>/protected2/*</url-pattern> </servlet-mapping>
<security-constraint> <web-resource-collection> <web-resource-name>protected region</web-resource-name> <url-pattern>/protected2/*</url-pattern> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <role-name>client</role-name> </auth-constraint></security-constraint>
Authentification : les rôleslogin-config: schéma d’authentification
security-role: rôles de l’appli Web
<login-config> <auth-method>BASIC</auth-method> <realm-name>univ-mlv</realm-name></login-config>
<security-role> <description> Client Rôle </description> <role-name>client</role-name></security-role>
Authentification : TomcatServices d’authentification fournis :
• Fichier XML (tomcat-user.xml)
• JDBC (base de données)
• LDAP
<?xml version='1.0' encoding='utf-8'?><tomcat-users> <role rolename="client"/> <role rolename="admin"/> <user username="toto" password="toto" roles="client"/> <user username="admin" password="admin" roles="admin,client"/></tomcat-users>
Définition des rôles
Définition des utilisateurs
Authentification : ServletL’interface java.security.Principal correspond à
l’utilisateur et ses différents rôles
public class Authentication2Servlet extends HttpServlet { protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain"); PrintWriter out=response.getWriter(); out.println("RemoteUser "+request.getRemoteUser()); out.println("UserPrincipal "+request.getUserPrincipal()); out.println("is a client ? "+request.isUserInRole("client")); }}
Nom de l’utilisateur
L’utilisateur possède-t-il le rôleRegroupe un utilisateur
et ses rôles
Authentification : Servlet (2)Authentification avant l’appel à la servlet
Les filtres
ServletFiltre Filtre
Requête
RequêteRequête
Réponse
RéponseRéponse
Hello World
Hello World Filtré
Les filtresIl est possible d’ajouter des filtres qui
seront exécutés avant les servlets<filter> <filter-name>footer</filter-name> <filter-class>fr.umlv.servletdemo.FooterFilter</filter-class> </filter>
<filter-mapping> <filter-name>footer</filter-name> <url-pattern>/filter/*</url-pattern> </filter-mapping>
<filter-mapping> <filter-name>footer</filter-name> <servlet-name>hello</servlet-name ></filter-mapping>
Filtre à partir d’un URL
Filtre à partir d’une servlet
Les filtresDes wrappers permettent d’interagir avec la servlet
public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {
response.setContentType("text/html"); PrintWriter out=response.getWriter(); out.println("<html><body bgcolor=\"white\"><h1>");
HttpServletResponseWrapper newResponse=new HttpServletResponseWrapper( (HttpServletResponse)response) { public void setContentType(String contentType) { } }; chain.doFilter(request,newResponse);
// context.getRequestDispatcher("/footer.html").include(request,response);
out.println("</h1></body></html>"); }
Appelle les autres filtresou la servlet
Exécuté avant
Exécuté après
Administration de Tomcat
Tomcat possède un outil d’administration à distance
Pour l’activer il est nécessaire de rajouter un utilisateur ayant le
rôle admin
Administration de Tomcat
Même informations que dansle fichier server.xml
Ajouter un nouveau rôle
Sur les Rôles
Créé un nouveau rôle
Rôle manager créé
Ajouter un rôle à un utilisateur
L’utilisateur admindevient un manager
de servlets
Manager de Servlet
• Permet de deployer/ démarrer/ arrêter/ recharger des servlets
• Trois modes d’exécutions :- dans une URL- dans le HTML- avec Ant
Reload démandé directementdans l’URL
Manager de Servlet