Projet ECOM – Documentation de la couche présentation J2EE (Servlets)
M2PGI & RICM 3
Année 2006-2007
Responsables : Fabienne Boyer & Didier Donsez
Editeur : D. Donsez
Références J2EE :
1
Programmation de la partie présentation d’une application J2EE à base de servlets
Les servlets correspondent à la partie présentation d’une application conçus sur le modèle J2EE. Les servlets sont des « scripts » exécutés par le serveur pour traiter la requête d’un navigateur et lui retourner un document dans un langage de présentation supporté par le navigateur. Par exemple, HTML4.x+CSS+JavaScript, CHTML, WML, XML+XSLT, PDF, GIF, JPEG, SVG, …
Petite remarque avant de commencer :
La programmation des servlets diffèrent de ceux des JSP, ASP, PHP, … car leur code est une classe Java dans laquelle le développeur écrit des lignes de code out.println(" … "); pour retourner le « texte » du document retourné. Dans l’approche SSS (Server Side Script) comme ASP, JSP et PHP, les scripts sont nichés au milieu de code HTML. Cette dernière approche à l’avantage de pouvoir utiliser les outils auteurs (authoring tools) comme Visual Studio, DreamWeaver, … Mais cette approche possède un très gros inconvénient puis qu’elle mêle deux métiers complémentaires mais diffèrents ! En effet, l’auteur du document « SSSiser » doit être à la fois Web Designer (i.e. Infographiste) et Développeur (connaissant bien les bases de données, les transactions, les EJB, la sécurité, …).
La suite de cette section 0 présente la notion d’application Web, les packages Java pour la programmation des servlets, le cycle de vie d’une servlet, l’accès aux ressources, le suivi de session et enfin le déploiement d’une application Web.
1.1
Notion d’application Web
Une application Web est un ensemble de scripts serveur (Servlet, Filter, JSP, TagLib, …) et des documents (hypertextuels, XML, XSLT, images, vectoriel animée, …) reliés par des relations d’inclusion, de référencement, …
En clair, une application se conçoit de manière modulaire et donc il est nécessaire de réfléchir à la structure globale de celle-çi avant de se mettre à programmer des bouts (les servlets !).
1.2
Les packages javax.servlet et javax.servlet.http
La programmation des servlets se fait au moyen des classes et des interfaces (listés dans le schéma ci dessous) qui se trouvent dans les 2 packages javax.servlet et javax.servlet.http.
Le package javax.servlet est conçu pour fournir des scripts serveur indépendant d’un protocole. Cependant le seul protocole supporté actuellement est HTTP et le package sert à programmer de scripts invoqués au moyen d’HTTP !
Packages javax.servlet et javax.servlet.http
1.3
Cycle de vie d’une servlet
Une servlet est un objet instancié (d’une classe dérivant de javax.servlet.http.HttpServlet) une seule fois. Cependant vous pouvez déployez plusieurs servlets à partir de la même classe Java! Attention aux méthodes et membres statiques de la classe, ils sont partagées entre les instances (quand elles appartiennent à la même application Web donc le même ClassLoader (voir %JONAS_ROOT%\doc\ClassLoader.html).
Une fois instantié, cet objet est « initialisé » lors la première requête (méthode init(…)).
Cet objet est ensuite concurremment accédé par les threads que le serveur démarre pour traiter les requêtes issues des navigateurs (méthode service(…)) ! Il peut être donc nécessaire de contrôler l’accès à des sections critiques du code qui accéder aux membres de l’objet (i.e. synchronized(this){ … })
1.3.1
Initialisation
L’initialisation se fait au moyen de la méthode void init(ServletConfig config)
Le développeur y place généralement l’initialisation des membres de l’objet (ou les statiques de la classe ) et utilise généralement les paramètres d’initialisation de la servlet et/ou ceux du contexte.
les paramètres d’initialisation de la servlet sont dans les éléments init-param (dans le fichier de déploiement de l’application WEB-INF\web.xml voir 5.5) et sont récupérés au moyen des 2 méthodes de Servlet : Enumeration getInitParameterNames(); et String getInitParameter(String paramName);
les paramètres d’initialisation du contexte de l’application sont dans les éléments context-param (dans le fichier de déploiement de l’application WEB-INF\web.xml voir 5.5) et sont récupérés au moyen des 2 méthodes de ServletContext : Enumeration getInitParameterNames(); et String getInitParameter(String paramName);
Exemple:
out.println("Servlet init parameters:");
Enumeration e =
getInitParameterNames();
while
(e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = getInitParameter(key);
out.println(" " + key + " = " + value);
}
out.println("Context init parameters:");
ServletContext context =
getServletContext();
Enumeration enum =
context.getInitParameterNames();
while
(enum.hasMoreElements()) {
String key = (String)enum.nextElement();
Object value = context.getInitParameter(key);
out.println(" " + key + " = " + value);
}
Exemple d’extrait du fichier web.xml:
<servlet>
<servlet-name>CustomerServlet</servlet-name>
<servlet-class>ecom.servlets.CustomerServlet</servlet-class>
<init-param>
<param-name>language</param-name>
<param-value>en</param-value>
</init-param>
<init-param>
<param-name>currency</param-name>
<param-value>EUR</param-value>
</init-param>
</servlet>
<context-param>
<param-name>language</param-name>
<param-value>fr</param-value>
<description>Parametre du contexte</description>
</init-param>
</context-param>
1.3.2
Traitement d’une requête
Le traitement d’une requête se fait au moyen de la méthode void service(ServletRequest req, ServletResponse res). Cependant la méthode service(…) implémentée par javax.servlet.http.HttpServlet appelle les méthode suivantes doGet(…), doPost(…), doPut(…), doDelete(…) …en fonction du type de la requête HTTP (GET, POST, PUT, DELETE, …)
Pour les deux plus courantes doGet(…) et doPost(…) (celles dont vous vous servirez), le traitement comporte généralement 3 phases :
1) récupération des paramètres de la requête
2) invocation de la logique applicative (par exemple, invoquer une ou plusieurs méthodes de Session Beans
3) formatage d’un document de retour (de préférence dans un format supporté par le navigateur à l’origine de la requête)
1.3.2.1 Récupération des paramètres de la
requête
Les paramètres d’une requête HTTP sont encodés au format x-www-form-urlencoded
et passés soit dans l’URI d’une requête de type GET soit dans le corps d’une requête de type POST.
Pour la servlet, les paramètres se récupèrent décodées au moyen des 3 méthodes de ServletRequest :
· Enumeration getParameterNames(); qui retourne une énumeration des noms (key) de paramètres récupérés
· String[] getParameterValues(String key); qui retourne un tableau des valeurs d’un paramètre (en effet en HTML, dans le cas des <input type="checkbox" name="menu" value= "dessert"><input type="checkbox" name="menu" value= "fromage"> peuvent retourner des valeurs multiples)
· String getParameterValue(String key); qui retourne la première valeur d’un paramètre
Exemple :
out.println("Parameter names in this
request:");
e = request.getParameterNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String[] values = request.getParameterValues(key);
out.print(" " + key + " = ");
for(int i = 0; i < values.length; i++) {
out.print(values[i] + " ");
}
out.println();
}
Il est possible de récupérer d’autres informations concernant la requête (dont les cookies, les champs d’entête, les attributs du contexte de l’application, …) comme le présente l’exemple suivant :
out.println("Servlet Name: " + getServletName());
out.println("Protocol: " + request.getProtocol());
out.println("Scheme:
" + request.getScheme());
out.println("Server
Name: " + request.getServerName());
out.println("Server Port: " + request.getServerPort());
out.println("Remote
Addr: " + request.getRemoteAddr());
out.println("Remote
Host: " + request.getRemoteHost());
out.println("Character Encoding: " + request.getCharacterEncoding());
out.println("Content Length: " + request.getContentLength());
out.println("Content Type: "+ request.getContentType());
out.println("Locale: "+ request.getLocale());
out.println("Request Is Secure: " + request.isSecure());
out.println("Auth Type:
" + request.getAuthType());
out.println("HTTP
Method: " + request.getMethod());
out.println("Remote
User: " + request.getRemoteUser());
out.println("Request URI: " + request.getRequestURI()); // Example:
/ecom/store
out.println("Context Path: " + request.getContextPath()); // Example:
/ecom
out.println("Servlet Path: " + request.getServletPath()); // Example:
/store
out.println("Path
Info: " + request.getPathInfo());
out.println("Path
Trans: " + request.getPathTranslated());
// Example:
G:\devtools\jakarta-tomcat-4.0.3\bin\..\webapps\ecom\servlets\CustomerServlet
out.println("Query
String: " + request.getQueryString());
out.println("Headers in this request:");
e =
request.getHeaderNames();
while
(e.hasMoreElements()) {
String key =
(String)e.nextElement();
String value
= request.getHeader(key); // example: Accept, User-Agent, ...
out.println(" " + key + ": " + value);
}
out.println("Cookies in this request:");
Cookie[] cookies =
request.getCookies();
if (cookies != null) {
for (int i =
0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
out.println(" " + cookie.getName() + " = "
+
cookie.getValue());
}
}
out.println("Context
attributes:");
enum =
context.getAttributeNames();
while
(enum.hasMoreElements()) {
String key =
(String)enum.nextElement();
Object value
= context.getAttribute(key);
out.println(" " + key + " = " + value);
}
1.3.2.2 Invocation de la logique applicative
Une fois que les paramètres récupérés dans des objets, la servlet invoque la logique applicative de l’application qui de préférence est encapsulé dans des Session Beans. La référence sur la maison de ces beans est obtenue classiquement avec le contexte (voir 3.2.6).
1.3.2.3 Formatage d’un document de retour
Une fois que le traitement est effectué, il est nécessaire de formater un document à retourner au navigateur. Il est préférable de choisir un format qui est supporté par le navigateur à l’origine de la requête et dans une langue comprise de l’usager de ce navigateur. Rappel : la liste des formats supporté est donnée dans le champs d’entête de la requête Accept et la langue par le champs d’entête Accept-Language.
Le document retourné est typé au moyen de la méthode setContentType(String mimeType), avec des types MIME comme text/html, text/xml, text/plain, text/vnd.wap.wml, … et de récupérer le flux de sortie (java.io.OutputStream ou java.io.PrintWriter)
Exemple
public class Hello extends
HttpServlet {
public void
doGet(HttpServletRequest req, HttpServletResponse res)
throws
ServletException, IOException {
res.setContentType("text/html");
PrintWriter
out = res.getWriter();
out.println("<HTML>");
out.println("<HEAD><TITLE>Hello
World</TITLE></HEAD>");
out.println("<BODY>");
out.println("<BIG>Hello World</BIG>");
out.println("</BODY></HTML>");
} }
La réponse suivante permet au navigateur et au serveur de maintenir la connexion ouverte entre eux (KeepAlive) pour d’autres requêtes afin d’améliorer les performances réseaux.
public class KeepAliveHello
extends HttpServlet {
public void
doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
// Set up a
PrintStream built around a special output stream
ByteArrayOutputStream
bytes = new ByteArrayOutputStream(1024);
PrintWriter
out = new PrintWriter(bytes, true); // true forces flushing
out.println("<HTML>");
out.println("<HEAD><TITLE>Hello
World</TITLE></HEAD>");
out.println("<BODY>");
out.println("<BIG>Hello World</BIG>");
out.println("</BODY></HTML>");
res.setContentLength(bytes.size());
// Set the content length
bytes.writeTo(res.getOutputStream()); // Send the buffer
} }
Exercice : Amusez vous à benchmarker ces 2 exemples avec Apache JMeter !
En cas d’erreur lors du traitement de la requête (mauvais paramètre, exception, …), il est souhaitable de retourner une réponse d’erreur avec le code d’état correspondant. Il est également souhaitable de journaliser cette erreur pour que l’administrateur de l’application ou du serveur soit informer du problème.
Exemple
public void
doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
try {//
...
} catch (FileNotFoundException e) {
// utilise le journal de GenericServlet
this.log("Could not find
file: " + e.getMessage());
// envoi du code 404
res.sendError(HttpServletResponse.SC_NOT_FOUND);
} catch (IOException e) {
// utilise le journal de ServletContext
this.getServletContext().log(e, "Problem sending file");
// envoi du code 500
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.toString());
}
}
Il est également possible d’ajouter des champs d’entête de la réponse au moyen de la méthode setHeader(…).
Exemple d’usage pour la redirection de document :
public class ClientPull extends
HttpServlet {
public void
doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter
out = res.getWriter();
res.setHeader("Refresh",
"10");
out.println(new Date().toString());
}
}
public class ClientPullMove
extends HttpServlet {
static final String
NEW_HOST = "http://www.ecom.com";
public void
doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter
out = res.getWriter();
String
newLocation = NEW_HOST + req.getRequestURI();
res.setHeader("Refresh",
"10; URL=" + newLocation);
out.println("The requested URI has been moved to a different
host.<BR>");
out.println("Its new location is " + newLocation +
"<BR>");
out.println("Your browser will take you there in 10 seconds.");
}
}
Il est également possible d’ajouter un cookie à l’entête de la réponse afin que le navigateur le stocke et le retourne lors d’une prochaine requête (méthode void HttpServletResponse.addCookie(Cookie cookie))
Remarque : quand les URL insérées dans le document comporte des caractères spéciaux (+, &, <space>, é, à, …), il est nécessaire d’encoder celles ci avec la méthode static String java.net.URLEncoder.encode(String str).
1.3.3
Accès aux ressources
La servlet peut récupérer via le contexte JNDI les variables d’environnements globales à l’application. Ces variables sont initialisées au moyen d’éléments env-entry du fichier web.xml
Exemple
<env-entry>
<env-entry-name>defaultCurrency</env-entry-name>
<env-entry-value>EUR</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
<env-entry>
<env-entry-name>defaultLanguage</env-entry-name>
<env-entry-value>33</env-entry-value>
<env-entry-type>java.lang.Integer</env-entry-type>
</env-entry>
Exemple
Context ctx = new
InitialContext();
Object value =
ctx.lookup("java:/comp/env/defaultCurrency");
out.println("Default
currency value : " + value);
Context envCtx = (Context) ctx.lookup("java:/comp/env/");
NamingEnumeration enum = ctx.list("java:/comp/env/");
while (enum.hasMoreElements()) {
out.print("Binding : "+ (enum.nextElement().toString());
}
NamingEnumeration enumbinding = envCtx.listBindings("java:/comp/env/");
while
(enumbinding.hasMoreElements()) {
out.print("Binding : "+( enumbinding.nextElement().toString());
}
La servlet peut récupérer via le contexte JNDI les références vers les Home (local ou remote) des Enterprise JavaBeans de l’application. Ces références sont décrites au moyen d’éléments ejb-local-ref ou ejb-remote-ref du fichier web.xml
Exemple :
<!--
Remote EJB Reference -->
<ejb-ref>
<ejb-ref-name>ejb/Cart</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>ecom.beans.CartHome</home>
<remote>ecom.beans.Cart</remote>
<ejb-link>ecom.jar#Cart</ejb-link>
</ejb-ref>
<!--
Local EJB Reference -->
<ejb-local-ref>
<ejb-ref-name>ejb/CartLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>ecom.beans.CartLocalHome</local-home>
<local>ecom.beans.CartLocal</local>
<ejb-link>ecom.jar#Cart</ejb-link>
</ejb-local-ref>
Exemple
Context ctx = new
InitialContext
// We want to start transactions from client: get UserTransaction
UserTransaction utx
= (UserTransaction) initialContext.lookup("java:comp/UserTransaction");
//
Connecting to CartLocalHome thru JNDI
CartLocalHome cartLocalHome = ctx.lookup("java:comp/env/ejb/CartLocal");
CartLocal cartLocal = cartLocalHome.create("Cart123456789");
La servlet peut récupérer via le contexte JNDI les références d’autres ressources de l’application (EIS, Mail, …). Ces références sont décrites au moyen d’éléments resource-ref du fichier web.xml.
Exemple
<resource-ref>
<res-ref-name>mail/MailSession</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Exemple
Context ctx = new InitialContext();
javax.mail.Session session = (javax.mail.Session) ictx.lookup("java:comp/env/mail/MailSession");
javax.mail.Message message = new javax.mail.MimeMessage(session);
1.4
Suivi de Session
HTTP est un protocole sans session (sessionless), ne maintenant pas un état particulier associé à un usager particulier !
Or beaucoup d’applications sur le Web requièrent un suivi de session avec l’usager notamment les applications de commerce électronique (comme ECOM) qui par exemple ont besoin de se rappeler des produits achetés au cours de la navigation.
Pour cela, il vous faut utiliser une classe javax.servlet.http.HttpSession qui permet le suivi de session. On récupère la session courante de l’usager ou on ouvre une nouvelle session au moyen de la méthode getSession(boolean create)
javax.servlet.http.HttpSession session = req.getSession(false);
// la session est récupérée ou null si elle n ’existait pas déjà
javax.servlet.http.HttpSession session = req.getSession(true);
// la session est récupérée ou ouverte si elle n ’existait pas déjà
Les informations disponibles sur la session sont :
· L ’identifiant
String sessionid=
session.getId(); // par exemple: To1010mC8601021835741167At
· La date de création
long datecreation= session.getCreationTime(); // nb de ms depuis 1/1/1970:00:00
· La date du dernier accès
long datelastaccess= session.getLastAccessedTime();
· Le nombre de seconde maximum d’inactivité de la session avant abandon
long nbsec= session.getMaxInactiveInterval();
Généralement la servlet lie à la session un certain nombre d’attributs (objet) qui sont récupérés lors d’une prochaine requête du navigateur (de cette servlet ou d’une autre). Chaque attribut est identifié au moyen d’une clé.
Les méthodes suivantes sont utilisées pour
L’ajout ou le remplacement d’un objet
· void HttpSession.setAttribute(String key, Object attribute)
La suppression d ’un attribut
·
void
HttpSession.removeAttribute(String name)
La récupération de noms d’attributs
· Enumeration HttpSession.getAttributeNames()
La récupération d’un attribut
· Object HttpSession.getAttribute(String key)
Exemple :
HttpSession session = request.getSession();
out.println("Session values: ");
Enumeration names = session.getAttributeNames();
while
(names.hasMoreElements()) {
String name = (String) names.nextElement();
out.println(" " + name + " = " + session.getAttribute(name));
}
Exemple de liaison d ’objets
import ecom.beans.cart.* ;
...
public void doGet(HttpServletRequest req, HttpServletResponse res) … {
Cart cart;
HttpSession session = req.getSession(true);
if((cart=(Cart)session.getAttribute("MYCART"))!=null) {
cart=cartHome.create();
session.setAttribute("MYCART",cart);
}
...
cart.add(product,2);
}
...
A tout moment, la session peut être invalidée au moyen de la méthode invalidate()
javax.servlet.http.HttpSession session = req.getSession(true);
// invalide la session si la requête précédente est vieille de plus de 5 minutes
if(session.getLastAccessedTime()
- session.getCreationTime() > 5*60*1000 ) {
session.invalidate(); // la session est invalidée (i.e. fermée)
}
L’invalidation de la session est provoqué le plus souvent par le serveur car il ne peut maintenir une quantité infinie d’objets liés à une session. La durée maximum entre 2 requêtes avant invalidation de la session est fixée avec l’élément session-config du fichier web.xml.
Pour cela, il est nécessaire de déclarer des observateurs de liaison qui sont notifiés des ajouts ou retraits d’attributs d’une session. Un observateur est généralement utilisé pour libérer des ressources critiques (fermer des fichiers, des connexions, valider des transactions, ...). L’observateur est l’objet lié qui doit implémenter l’interface HttpSessionBindingListener
interface
HttpSessionBindingListener {
public void valueBound(HttpSessionBindingEvent event) ;
// invoqué quand l ’objet est lié (putValue())
public void valueUnbound(HttpSessionBindingEvent event) ;
// est invoqué quand la session est invalidée ou expire
// ou quand l ’objet
est délié (putValue()/removeValue()).
}
class HttpSessionBindingEvent extends EventObject
public Session getSession() { ... } // la session concernée
public String getName(){ ... } // le nom de la liaison
}
Exemple d’observateur de liaison
class CartBindingListener implements HttpSessionBindingListener {
Cart
cart=null;
public
CartBindingListener(CartHome cartHome) { this.cart = cartHome.create(); }
public void
valueBound(HttpSessionBindingEvent event) {}
public void
valueUnbound(HttpSessionBindingEvent event) { cart.discard();}
}
...
public void
doGet(HttpServletRequest req, HttpServletResponse res) {
CartBindingListener cbl;
HttpSession session =
req.getSession(true);
CartBindingListener cbl
=( CartBindingListener)session.getValue("MYCART");
if(cbl ==null) {
cbl=new CartBindingListener ( ... );
session.setValue("MYCART",cbl); // valueBound est invoqué sur l ’objet lié
} …
session.removeValue("MYCART"); // valueUnbound est invoqué sur l ’objet lié
Techniquement, le serveur maintient une session soit au moyen de cookie (le Cookie de nom SESSIONID pour TomCat (cependant les cookies peuvent être déactivés sur le navigateur) soit au moyen des la réécriture des URLs en y glissant l’identifiant de session (cependant la suivi de session est perdu si on traverse une page statique !)
La méthode de suivi de session est connue au moyen des 2 méthodes suivantes
· boolean HttpServletRequest.isRequestedSessionIdFromCookie() teste si le suivi de session utilise un cookie
· boolean HttpServletRequest.isRequestedSessionIdFromURL() teste si le suivi de session utilise la réécriture d ’URL
Dans le cas de la réécriture des URL, les URL générées dans le document de réponse doivent être encodées pour intégrer le suivi de session avec les 2 méthodes :
·
String
HttpServletResponse.encodeRedirectURL(String url)
· String HttpServletResponse.encodeURL(String url)
Exemple
res.sendRedirect(res.encodeRedirectURL("/servlet/login");
1.5
Déploiement
Pour être déployée, une application Web doit être emballée dans un fichier WAR/Web Application Archive (par exemple, ecom.war). L’application est installée en plaçant ce fichier dans le répertoire webapps du serveur web J2EE sous %JONAS_BASE%/webapps (ou %JONAS_ROOT%/webapps).
Ce fichier WAR est une archive Java (fichier Jar) ayant la structure suivante :
- *.html, *.jsp, … : des documents statiques ou dynamiques
- WEB-INF/web.xml : des fichiers de déploiement décrivant le paramétrage des servlets, types MIME additionnels, etc.
- WEB-INF/classes : les classes des servlets
Le fichier de déploiement web.xml comporte les informations nécessaires au nommage des servlets, leur initialisations, la désignation des ressources, …
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
<servlet>
<servlet-name> CustomerServlet </servlet-name>
<servlet-class>ecom.servlets.CustomerServlet</servlet-class>
<init-param>
...
</init-param>
...
</servlet>
<servlet-mapping>
<servlet-name>CustomerServlet</servlet-name>
<url-pattern>/store</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CustomerServlet</servlet-name>
<url-pattern>/product</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CustomerServlet</servlet-name>
<url-pattern>/cart</url-pattern>
</servlet-mapping>
...
<session-config>
<session-timeout>54</session-timeout>
</session-config>
<resource-ref>
<res-ref-name>jdbc/EcomDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<mime-mapping>
<extension>wbmp</extension>
<mime-type>image/vnd.wap.wbmp</mime-type>
</mime-mapping>
<mime-mapping>
<extension>wml</extension>
<mime-type>text/vnd.wap.wml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>wmls</extension>
<mime-type>text/vnd.wap.wmlscript</mime-type>
</mime-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.wml</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
1.6
Filter
Les Filter peuvent être chaînés pour effectuer des pré-traitements sur le contenu d’une requête avant d’invoquer la servlet ou la JSP, ou bien faire des post-traitements sur la réponse qui est retournée par la servlet (ou un autre filtre de la chaîne). Les utilisations possibles sont l’authentification, la conversion/transformation (XSLT, FOP), le chiffrage/compression, l’audit/journalisation, …
Exemple de Filter :
public class TraceFilter implements javax.servlet.Filter {
private FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest req,ServletResponse res, FilterChain chain)
throws
IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest)req;
trace(hreq.getServletPath()); // trace only the path
chain.doFilter(req,
res);
}
private void
trace(String msg){ System.err.println(msg); }
}
Exemple de déploiement de filtre dans le fichier web.xml
<filter>
<filter-name>TraceFilter</filter-name>
<display-name>TraceFilter</display-name>
<description>trace calls</description>
<filter-class>ecom.servlets.TraceFilter</filter-class>
<init-param>
<param-name>traceContent</param-name>
<param-value>date,session,uri</param-value>
</init-param>
<init-param>
<param-name>fieldSeparator</param-name>
<param-value>:</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TraceFilter</filter-name>
<!-- trace all requests for (.html, .jsp, Servlets, … -->
<url-pattern>/*</url-pattern>
</filter-mapping>
Vous pouvez voir d’autres filtres dans les exemples de Jakarta Tomcat.
1.7
JSP
Les JSP (Java Server Page) sont des SSS (Server Side Script) comme les ASP (Active Server Pages) ou bien les PHP (Personal Home Pages). Ce sont des « scripts » qui sont nichés au milieu du document HTML. Ces scripts forment des parties du document qui sont générées lors de l’invocation.
En réalité, les documents *.jsp sont tous traités par une servlet org.apache.jasper.servlet.JspServlet qui lors de la première invocation d’une JSP transforme son document en une classe Java (héritant de la classe org.apache.jasper.runtime.HttpJspBase) puis invoque sa méthode _jspService(HttpServletRequest request, HttpServletResponse response). Plus de détail, explorez le répertoire work de TomCat !
Exemple de JSP ( http://localhost:8080/ecom/hello.jsp)
<HTML>
<HEAD><TITLE>Hello</TITLE></HEAD>
<H1> Hello
<%
String pname; // déclaration de
variable
pname =
request.getParameter("name"); // request : objet implicite
if (pname== null) {
out.println("World !");
} else {
%>
Mister <%=pname%>
!
<% } %>
</H1>
</BODY>
</HTML>
Vous pouvez voir un certain nombre de JSP dans les exemples de Jakarta Tomcat.
2
Déploiement d'une application EJB avec accès Web
Pour être déployée, une application composée d'une partie Web et d'une partie EJB doit être emballée dans un fichier EAR/Enterprise Application Archive, par exemple ecom.ear. L’application est installée en plaçant ce fichier dans le répertoire apps du serveur web J2EE sous %JONAS_BASE%/apps (ou %JONAS_ROOT%/apps).
Ce fichier EAR est une archive Java (fichier Jar) contenant à la fois :
- La partie ejbjar, correspondant à la mise en œuvre de la partie EJB
- La partie war, correspondant à la mise en œuvre de la partie servlets
- Un fichier application.xml, qui décrit la composition des deux parties précédentes.
Pour charger effectivement votre application dans un serveur JOnAS, vous pouvez utiliser la commande jonas admin –a ecom.ear, ou bien utiliser l'outil d'administration fourni par JOnAS. En placeant votre fichier ear dans le sous-répertoire autoload, alors votre application sera automatiquement chargée par JOnAS lors du lancement du serveur.
Les commandes ant ear, et ant install, permettent respectivement de générer votre fichier ear, et d' installer votre application dans les répertoires de JOnAS.