Cours J2EE les Servlets
Java EE
-
Cours 2
Cours de 2e année ingénieur
Spécialisation « Génie Informatique »
Servlets
• Une servlet est une application Java qui permet de créer dynamiquement des données au sein d'un serveur HTTP. Ces données sont le plus généralement présentées au format HTML, mais elles peuvent également l'être au format XML ou tout autre format destiné aux navigateurs web.
• Une servlet s'exécute dynamiquement sur le serveur web et permet l'extension des fonctions de ce dernier. Typiquement : accès à des bases de données, transactions d'e-commerce, etc. Une servlet peut être chargée automatiquement lors du démarrage du serveur web ou lors de la première requête du client. Une fois chargées, les servlets restent actives dans l'attente d'autres requêtes du client.
Servlets
• Un servlet est un objet qui peut être manipulé par le conteneur via l’interface suivante:
«interface» Servlet |
void destroy() ServletConfig getServletConfig() String getServletInfo() void init(ServletConfig) void service(ServletRequest, ServletResponse) |
• Lorsque le conteneur reçoit une requête, il la transmet au servlet qui correspondàl’URL pour que la requête soit traitée effectivement
Cycle de vie d’un servlet
1. Chargement de la classe
2. Instanciation du servlet
• constructeur par défaut
3. Appel de init()
4. Appel(s) de service()
• 1 thread par requête
5. Appel de destroy()
La méthode service()
• Lors de la réception d’une requête, le conteneur crée:
– un objet ServletRequest (la requête), et
– un objet ServletResponse (la réponse) • Le conteneur appelle ensuite la méthode service() avec ces deux objets en paramètres pour permettre au servlet de répondre à la requête du client.
Requêtes HTTP (rappel)
• Deux méthodes principales: GET et POST
GET
Utilisateur Client Serveur
GET ou POST
Utilisateur Client Serveur GenericServlet
Servlets HTTP void destroy()
String getInitParameter(String)
Enumeration getInitParameterNames()
ServletConfig getServletConfig()
«interface» ServletContext getServletContext()
Servlet String getServletInfo()
String getServletName()
void destroy() void init()
ServletConfig getServletConfig() void init(ServletConfig)
String getServletInfo() void log(String) void init(ServletConfig) void log(String, Throwable)
void service(ServletRequest, voidservice(ServletRequest, ServletResponse) ServletResponse)
HttpServletMyServlet # void doDelete(HttpServletRequest, HttpServletResponse)
# void doGet(HttpServletRequest, HttpServletResponse)
void doGet (HttpServletRequest, # void doHead(HttpServletRequest, HttpServletResponse)
HttpServletResponse) # void doOptions(HttpServletRequest, HttpServletResponse)
void doPost(HttpServletRequest, # void doPost(HttpServletRequest, HttpServletResponse)
HttpServletResponse) # void doPut(HttpServletRequest, HttpServletResponse)
void doWhatYouWant() # void doTrace(HttpServletRequest, HttpServletResponse)
# long getLastModified(HttpServletRequest)
# void service(HttpServletRequest, HttpServletResponse) void service(ServletRequest, ServletResponse)
Requêtes et Réponses HTTP
«interface»
ServletRequest
Object getAttribute(String) int getContentLength()
ServletInputStream getInputStream()
int getLocalPort()
String getParameter(String)
Enumeration getParameterNames()
String[] getParameterValues(String)
// Other methods not listed here…
HttpServletResponse | |
void addCookie(Cookie cookie) void addHeader(String, String) String encodeRedirectURL(String) void sendError(int, String) void setStatus(int) // Other methods not listed here… | 8 |
HttpServletRequest
String getContextPath()
Cookie[] getCookies()
String getHeader(String)
String getMethod()
String getQueryString()
HttpSession getSession()
// Other methods not listed here…
(1/8)
Lors de la création d’un projet JEE, on a deux grandes phases :
• La phase de développement qui s’effectue la plupart du temps en local, dans un dossier permettant de compiler et tester les sources Java, les fichiers HTML, les CSS, …
• La phase de déploiement qui exporte le site local sur un serveur JEE afin de le tester.
Ø Ainsi, lors de la création d’une servlet, on commencera par créer un dossier de projet, avec un dossier src contenant les sources des servlets que l’on compilera dans un dossier build/classes (comme nous faisions dans les cours de Java ING1).
Ø C’est dans un second temps, que nous déploierons notre projet sur le serveur Tomcat.
Ø L’utilisation d’un outil de contruction de projets Java, tels que Ant ou Maven, est classique durant ces phases.
(2/8)
• Ecrire un servlet et le mettre dans src (ici ) |
import .*; import javax.servlet.*; import .*; public class Clock extends HttpServlet{ public void doGet (HttpServletRequest request, Servlet classique:
HttpServletResponse response) redéfinit doGet()
throws IOException{ de HttpServlet
PrintWriter out= response.getWriter(); today=new ();
String docType= "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 "+
"Transitional//EN\">\n";
out.println(docType); out.println("<html>");
out.println("<head>\n<title>Clock</title>\n</head>");
Code HTML out.println("<body>\n"+
incorporé"<h1>Time on server</h1>\n"+ dans Java "<p>"+ today+ "</p>\n"+
"</body>");
out.println("</html>"); }
}
(3/8)
• Créer un dossier WEB-INF et y placer le fichier de configuration
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="2.4" xmlns="; xmlns:xsi="; xsi:schemaLocation=" ">
<servlet>
<servlet-name>The Clock</servlet-name>
<servlet-class> Clock</servlet-class> <servlet-name> permet de lier
</servlet> classe Java <servlet> et <servlet-mapping>
<servlet-mapping>
<servlet-name>The Clock</servlet-name> <url-pattern> /Serv1</url-pattern>
</servlet-mapping> nom utilisé par le client
</web-app>dans sa requête
(4/8)
• A partir du répertoire de projet, compiler le servlet et placez-le dans le répertoire build/classes
% cd AREL
% javac –classpath
–d classes
(5/8)
(6/8)
• Démarrer Tomcat
% cd tomcat %
ou bien lancer le Monitor si vous êtes sous Windows
en 8 (7/8)
• Lancer un navigateur et entrer l’URL suivante – http://localhost:8080/MonProjet/Serv1 • Le navigateur affiche: |
en 8 (8/8)
• Redémarrer Tomcat à chaque modification de la classe serlvet ou du descripteur de déploiement
% cd tomcat
%
Entêtes d’une requête GET
public class ShowRequestHeaders extends HttpServlet{ public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException{ //...
out.println(doctype+
"<html>\n<head><title>"+ title+ "</title></head>\n"+
"<body>\n<h1>"+ title+ "</h1>\n"+
"<b>Request Method: </b>"+ request.getMethod()+ "<br />\n"+
"<b>Request URI: </b>"+ request.getRequestURI()+ "<br />\n"+
"<b>Request Protocol: </b>"+ request.getProtocol()+ "<br />\n"+
"<table>\n"+
"<tr><th>Header Name</th><th>Header Value</th></tr>"); Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
String headerName = headerNames.nextElement(); out.println("<tr><td>"+ headerName+ "</td>"); out.println("<td>"+ request.getHeader(headerName)+
"</td></tr>");
} out.println("</table>\n</body></html>"); }
}
Entêtes d’une requête GET (2)
Entêtes d’une requête POST
public class ShowRequestHeaders extends HttpServlet{ public void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException{
doGet(request,response);
}
}
Formulaire GET
<form action="http://localhost:8080/AREL/LogServlet">
Login: <input type="text" name="param1"/><br/>
Mot de passe: <input type="password" name="param2"/><br/>
<input type="submit" value="Valider"/>
</form>
Traitement formulaire GET
|
public class LogServlet extends HttpServlet{ public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException{
String login= request.getParameter("param1");
String password= request.getParameter("param2"); if (checkUserAndPassword(login, password)){ grantAccessTo(login);
} else{ sendAuthentificationFailure(login); }
}
}
Formulaire POST
<form method="post" action="http://localhost:8080/AREL/LogServlet">
Login: <input type="text" name="param1"/><br/>
Mot de passe: <input type="password" name="param2"/><br/>
<input type="submit" value="Valider"/>
</form>
Traitement formulaire POST
|
public class LogServlet extends HttpServlet{ public void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException{
doGet(request,response);
}
}
Paramètres de formulaires
public class ShowParameters extends HttpServlet{ public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException{
//...
out.println("<b>Query String: </b>"+
request.getQueryString()+"<br />");
out.println("<table>");
Enumeration<?> parameterNames= request.getParameterNames();
while(parameterNames.hasMoreElements()){
String parameterName=(String)parameterNames.nextElement();
out.println("<tr><td>"+ parameterName+"</td>");
String paramValue=request.getParameter(parameterName); out.println("<td>"+ paramValue+"</td>");
} out.println("</table>");
}
}
Vérification de formulaires
• Données manquantes
– Champ manquant dans le formulaire
• getParameter retourne null – Champ renvoyé vide
• getParameter retourne une chaine vide (ou une chaine avec des espacements)
String param= request.getParameter("someName");
if((param == null) || (().equals(""))){ doSomethingForMissingValues(...);
} else{ doSomethingWithParameter(param);
}
• Données malformées
– Chaine non vide mais dans le mauvais format
(ex: code HTML si le résultat doit être affiché)
Upload de fichiers
• Formulaire HTML
– <input type="file" name="nameFile" />
– <form method="post"
enctype="multipart/form-data"
action="/servlet">
– Le choix du enctype impacte les autres champs du formulaire
• request.getParameter("name") ne fonctionne plus
• Côté Servlet – Bas-niveau : parser l’inputStream
request.getInputStream()
– Haut-niveau : utiliser une librairie ex: Commons FileUpload du projet Jakarta
()
Commons FileUpload
• Développement
– import org.apache.commons.fileupload.*
– import org.apache.commons.fileupload.servlet.*
• Déploiement
– Dans le module Web de l’application…
• ie. même chose pour chaque application!
– …dans le répertoire WEB-INF/lib
•
•
Upload simple (1)
public void doPost (HttpServletRequest request,
HttpServletResponse response) throws IOException{
//...
// check file upload request if(ServletFileUpload.isMultipartContent(request)){
// create a factory for disk-based (large) file items
FileItemFactory fileItemFactory = new DiskFileItemFactory(); fileItemFactory.setSizeThreshold(40960); /* the unit is bytes */
// create a new file upload handler
ServletFileUpload servletFileUpload =
new ServletFileUpload(fileItemFactory);
servletFileUpload.setSizeMax(81920); /* the unit is bytes */
// parse the request
// ... --->
}
}
Upload simple (2)
// parse the request
try{
List<?> fileItemsList= servletFileUpload.parseRequest(request);
// Process file items
Iterator<?> it = fileItemsList.iterator(); while (it.hasNext()){
DiskFileItem fileItem=(DiskFileItem)();
if(fileItem.isFormField()){ // classic form field (name = value) out.println("<b>Form field:</b><br />\n"+ fileItem.getString()+ "<br/>");
} else{ // uploaded file out.println("<b>File:</b><br />\n<pre>"+
fileItem.getString()+ "</pre><br/>");
// ex: save on disk
File dest= new File(directoryPath,fileName);
FileOutputStream fos = new FileOutputStream(dest); fos.write( () );
fos.close();
}
}
} catch (FileUploadException e) {e.printStackTrace();}
Réponse HTTP (rappel)
• Une réponse HTTP peut contenir du HTML
• HTTP rajoute des (meta)informations en entête du contenu de la réponse
Entête réponse HTTP
• Ex: Ligne de statut
HTTP/1.1 200 OK
Date: Wed,8 Oct 2008 16:19:13 GMT
Server: Apache-Coyote/1.1
Content-Type: text/html Entête
Content-Lenght: 1234 Connection: close
<html>
... Corps
</html>
• Quelques codes réponses
– 200 OK
– 301 MOVED
– 403 FORBIDDEN
– 404 NOT FOUND
– 503 SERVICE UNAVAILABLE
Status Codes
• response.setStatus(int statusCode)
– Utiliser les constantes, pas d’entiers directement
– Noms dérivés du message standard • Ex: SC_OK, SC_NOT_FOUND, etc…
• response.sendError(int code, String msg)
– Englobe le message dans un petit document HTML
• response.sendRedirect(String url)
– Le code de status est alors 302
– L’attribut «Location» est également généré dans l’entête de la réponse
Exemple sendError
public class LogServlet extends HttpServlet{ public void doGet (HttpServletRequest request,
HttpServletResponse response) throws IOException{
String login= request.getParameter("param1");
String password= request.getParameter("param2"); if ((param1 == null) || (().equals(""))){ response.sendError(HttpServletResponse.SC_NOT_FOUND,
"Empty login");
return;
}
if (checkUserAndPassword(login, password)){ grantAccessTo(login);
} else{ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied to"+ login);
}
}
}
Exemple sendRedirect
public class WrongDestination extends HttpServlet{ public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
String userAgent= request.getHeader("User-Agent"); if ((userAgent != null) &&
(userAgent.contains("MSIE")){ response.sendRedirect("");
} else{ response.sendRedirect("");
}
}
}
Exemple sendRedirect (2)
• Même URL de départ pour les deux
setContentType
Type | Meaning |
application/msword | Microsoft Word document |
application/octet-stream | Unrecognized or binary data |
application/pdf | Acrobat (.pdf) file |
application/postscript | PostScript file |
-excel | Excel spreadsheet |
-powerpoint | Powerpoint presentation |
application/x-gzip | Gzip archive |
application/x-java-archive | JAR file |
application/x-java-vm | Java bytecode (.class) file |
application/zip | Zip archive |
audio/basic | Sound file in .au or .snd format |
audio/x-aiff | AIFF sound file |
audio/x-wav | Microsoft Windows sound file |
audio/midi | MIDI sound file |
text/css | HTML cascading style sheet |
text/html | HTML document |
text/plain | Plain text |
text/xml | XML document |
image/gif | GIF image |
image/jpeg | JPEG image |
image/png | PNG image |
image/tiff | TIFF image |
video/mpeg | MPEG video clip |
video/quicktime QuickTime video clip
public class ApplesAndOranges extendsHttpServlet{ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ response.setContentType ("-excel"); PrintWriter out= response.getWriter(); out.println("\tQ1\tQ2\tQ3\tQ4\tTotal"); out.println("Apples\t78\t87\t92\t29\t=SUM(B2:E2)"); out.println("Oranges\t77\t86\t93\t30\t=SUM(B3:E3)"); } } |