640 likes | 840 Views
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.
E N D
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)
Browser HTTP /admin/* Requête servlet 1 /vignette/*.html Réponse /examples/*.html servlet 2 Conteneur de Servlets Servlet & Conteneur Le conteneur de servlets associe àdes URLs virtuels une servlet
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 Répertoire de Tomcat Organisation des répertoires de Tomcat /bin /common/lib /conf /logs /server/lib /shared/lib /webapps
Configuration Tomcat Le fichier server.xml • ServerRacine, 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. • Enginecorrespond au conteneur de servlet en lui-même. • LoggerIls 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
Configuration Tomcat (2) port d’écoute • 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" 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 • Un Context représente l’association entre un cheminsur le serveur (URI) et un chemin sur le disque • path= "/examples" • docBase="examples" • reloadable="true" URI d’accès Chemin d’accès des fichiers(relatif ou absolu par rapport à webapps) Détection automatique des changementset rechargement si besoin
fichiers HTML *.html, *.jsp /WEB-INF/web.xml /WEB-INF/classes/ /WEB-INF/lib/ fichier de configuration (XML) classes des servlets fichiers jar des servlets Architecture d’une appli Web Une application Web possède dans un repertoire lui-même dans webapps une architecture spécifique 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 Web Le 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 servlet nom de la servlet nom de la servlet URI d’accès URI d’accès
Configuration d’une appli Web Paramètres d’initialisation d’une servlet association name/value <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>
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
Cycle de vie d’une servlet Le cycle de vie d'une servlet : • la méthode init() est appelée après le chargement ; • une méthode service() est appelée à chaque requête dans une nouvelle thread. • la méthode destroy() est appelée pour le déchargement. La synchronisation est gérée par l’objet Response
HelloServlet La méthode service() est appelée avec un objet requête et un objet réponse importjava.io.*; importjavax.servlet.*; publicclassHelloServletextendsGenericServlet{ publicvoidservice(ServletRequestrequest,ServletResponseresponse) throwsServletException,IOException{ PrintStreamout=newPrintStream(response.getOutputStream()); out.println("Hello World!"); } publicStringgetServletInfo(){ return"Hello World Servlet"; } } L’objet réponse permet d’obtenirle flux de sortie en écriture Information textuelle sur la servlet
L’interface Request L'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 serveur Description du client Il est possible de rajouterdes attributs (non HTTP)
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 Taille de la réponse(peut être omis) Type de contenu auformat MIME L’objet réponse permet d’obtenirle flux de sortie en écriture
Fichier de configuration Le 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, doTraceprotected void do*(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException
HTTP HelloWorld HelloWorld réécrit avec une servlet HTTP importjava.io.*; importjavax.servlet.*; importjavax.servlet.http.*; publicclassHelloHttpServletextendsHttpServlet{ protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/plain"); PrintWriterout=response.getWriter(); out.println("HTTP Hello World!"); } publicStringgetServletInfo(){ return"HTTP Hello World Servlet"; } } L’objet réponse permet d’obtenirle flux de sortie en écriture
Informations sur la requête protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/plain"); PrintWriterout=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 la servlet Chemin de laressource Chemin sur le serveur
Informations sur la requête (2) Déclaration de la servlet « header » Définition des servlets <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> Chemin de la servlet Définition des associations
Informations sur la requête (3) URL complète Informations sur la requête
Entêtes de la requête En-tête = Informations envoyées par le browser protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/plain"); PrintWriterout=response.getWriter(); Enumeratione=request.getHeaderNames(); for(;e.hasMoreElements();){ Stringname=(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 HTTP L’objet HttpServletResponse permet en plus de renvoyer des codes d’erreurs publicclassHttpRedirectServletextendsHttpServlet{ protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ if("/index.html".equals(request.getPathInfo())) response.sendRedirect("/demo/header/index.html"); else response.sendError(HttpServletResponse.SC_NOT_FOUND); } } Redirection HTTP SC = Status Code
Paramètres d’initialisation Les 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ètres publicclassInitParamServletextendsHttpServlet{ protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/plain"); PrintWriterout=response.getWriter(); for(inti=0;i<count;i++){ out.println(message); } } publicvoidinit(ServletConfigconfig)throwsServletException{ count=Integer.parseInt(config.getInitParameter("count")); message=config.getInitParameter("message"); } privateintcount; privateStringmessage; } Demande la valeur duparamètre "count"
Paramètres d’initialisation (3) Le destroy doit libérer les ressources !! protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ … } publicvoidinit(ServletConfigconfig)throwsServletException{ super.init(config); count=Integer.parseInt(config.getInitParameter("count")); message=config.getInitParameter("message"); } publicvoiddestroy(){ message=null; } privateintcount; privateStringmessage; 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*() protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/html"); PrintWriterout=response.getWriter(); out.println("<html><body bgcolor=\"white\">"); Enumeratione=request.getParameterNames(); for(;e.hasMoreElements();){ Stringname=(String)e.nextElement(); Stringvalue=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 POST HTML 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*() protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/html"); PrintWriterout=response.getWriter(); out.println("<html><body bgcolor=\"white\">"); Enumeratione=request.getParameterNames(); for(;e.hasMoreElements();){ Stringname=(String)e.nextElement(); Stringvalue=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 protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ getServletContext().getRequestDispatcher("/index.html"). forward(request,response); } fichier L’inclusion permet d’inclure plusieurs fois des ressources protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/html"); getServletContext().getRequestDispatcher("/hello.html"). include(request,response); getServletContext().getRequestDispatcher("/hello.html"). include(request,response); } 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éé une session sinon existante 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
Session (3) Ouverture et fermeture d’une session
Session (4) Requête GET sur la servlet protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/html"); PrintStreamout=newPrintStream(response.getOutputStream()); out.println("<html><body bgcolor=\"white\">"); HttpSessionsession=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 protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ HttpSessionsession=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 sessionavec création automatique
Browser Serveur GET / HTTP/1.0 HTTP/1.0 401 UnauthorizedWWW-Authenticate: Basicrealm="univ-mlv" GET / HTTP/1.0Autorisation: Basic RntGDOujujO= Authentification Types d’autorisation(BASIC, DIGEST, FORM) 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 main Demande d’authentification : WWW-Authenticate publicclassAuthentication1ServletextendsHttpServlet{ protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ Stringuser; Stringauthorization=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 privateStringcheck(Stringauthorization)throwsServletException,IOException{ if(!authorization.toLowerCase().startsWith(BASIC_SCHEME)) thrownewServletException("unrecognized authentication scheme"); StringcreditBase64=authorization.substring(1+BASIC_SCHEME.length()); sun.misc.BASE64Decoderdecoder=newsun.misc.BASE64Decoder(); byte[]credit=decoder.decodeBuffer(creditBase64); Stringstr=newString(credit); intindex=str.indexOf(':'); Stringuser=str.substring(0,index); Stringpasswd=str.substring(index+1); return (passwd.equals("toto"))?user:null; } privatestaticfinalStringBASIC_SCHEME="basic"; } Header :Autorisation: Basic RntGDOujujO= Credit :login:password