Vous êtes sur la page 1sur 60

BenlahmarElhabib

Partietrois
Uneservletestunprogrammequis'excute
ctserveurentantqu'extensionduserveur.
LatechniquedesCGIenJava,MAIS
Sanscrerdeprocessus+toutelapuissancede
Java(accsauxdiversdomainesdel'informatique:
BD,multimdia,rseau,objetsdistribus,
composants,etc.)
+indpendancedelaplateformeetduserveur
Servlets
ScriptsserveurcritenJava
Servlets deBase:FileServlet,CGIServlet,
HttpServlet
Excutiondansunespaceisol(WebApplication)
Spcification:Sun(souspartiedeJ2EE)
Implmentationderfrence:ApacheGroup
(JakartaTomcat)
DiffrenceaveclesCGIetlesLD(NSAPI,ISAPI)
performancesurlespassagesdesparamtres (vsCGI)
sretdefonctionnement(NSAPI,ISAPI)
Pourexcuterdesservlets,ilfautunmoteur
deservletsdansleserveurWeb.
Cesmoteurssontdespluginpourdesserveurs
Webexistants
oubiendesserveursWebauxmmes
Plugin:deuxcandidats:Jrun(www.allaire.com),
tomcat(jakarta.apache.org)
Utilisedeuxpaquetages:
javax.servlet:paquetagegnrique
javax.servlet.http:paquetagepourserveursWeb
CespaquetagesnesontpasdansJ2SE1.3
Sontdespaquetagessupplmentaires.
IlsontaussiintgrsdansJ2EEvoir
http://java.sun.com/j2ee/
L'APIservletregroupeunensembledeclasses
dansdeuxpackages:
javax.servlet:contientlesclassespourdvelopper
desserlvetsgnriquesindpendantesd'un
protocole.
javax.servlet.http:contientlesclassespour
dvelopperdesservletsquireposentsurle
protocolehttputilisparlesserveursweb.
javax.servlet
Nom Role
Les
interfaces
RequestDispatcher Dfinitiond'unobjetquipermetlerenvoid'une
requteversuneautreressourceduserveur(une
autreservlet,uneJSP...)
Servlet Dfinitiondebased'uneservlet
ServletContext Dfinitiond'unobjetpourobtenirdes
informationssurlecontexted'execution dela
servlet
ServletConfig Dfinitiond'unobjetpourconfigurerlaservlet
ServletRequest Dfinitiond'unobjetcontenantlarequtedu
client
ServletResponse Dfinitiond'unobjetquicontientlareponse
renvoyeparlaservlet
SingleThreadModel Permetdedfiniruneservlet quinerpondraqu'
uneseulerequtelafois
javax.servlet Nom Role
Lesclasses
GenericServlet Classedfinissantuneservlet indpendantede
toutprotocole
ServletInputStream Fluxpermetlalecturedesdonnesdelarequte
cliente
ServletOutPutStream Fluxpermettantl'envoiedelareponse dela
servlet
Les
exceptions
SevletException Exceptiongnraleencasdeproblmedurant
l'excutiondelaservlet
UnavailableException Exceptionlevesilaservlet n'estpasdisponible
javax.servlet.
http
Nom Role
Lesinterfaces
HttpServletRequest HritedeServletRequest :dfinitunobjet
contenantunerequteselonleprotocolehttp
HttpServletResponse HritedeServletResponse :dfinitunobjet
contenantlareponse delaservlet selonle
protocolehttp
HttpSession Dfinitunobjetquireprsenteunesession
Lesclasses
Cookie Classereprsentantuncookie(ensemblede
donnessauvegardesparlebrower surleposte
client)
HttpServlet HritedeGenericServlet :classedfinissantune
servlet utilisantleprotocolehttp
HttpUtils Classeproposantdesmthodesstatiquesutiles
pourledveloppementdeservlet http
Cetteinterfacedfinit5mthodesquipermettentau
conteneurwebdedialogueraveclaservlet:
void service(ServletRequest req,ServletResponse res)
void init(ServletConfig conf)
ServletConfig getServletConfig()
void destroy()
StringgetServletInfo()
Lesmthodesinit(),service()etdestroy()assurentle
cycledeviedelaservlet entantrespectivement
appeleslorsdelacrationdelaservlet,lorsdeson
appelpourletraitementd'unerequteetlorsdesa
destruction.
L'interfaceServletRequest dfinitplusieursmthodesqui
permettentd'obtenirdesdonnessurlarequteduclient:
ServletInputStream getInputStream()
//Permetd'obtenirunfluxpourlesdonnesdelarequte
BufferedReader getReader()
//Idem
L'interfaceServletResponse dfinitplusieursmthodesqui
permettentdefournirlarponsefaiteparlaservlet suiteces
traitements:
SetContentType
//PermetdeprciserletypeMIMEdelarponse
ServletOutputStream getOutputStream()
//Permetd'obtenirunfluxpourenvoyerlarponse
PrintWriter getWriter()
//Permetd'obtenirunfluxpourenvoyerlarponse
Lepassaged'untatunautreestautomatiquefaitparleconteneurdeservlets.
importjava.io.*;
importjavax.servlet.*;
publicclassHelloServlet extends GenericServlet {
publicvoid service(ServletRequest req,
ServletResponse res)
throws ServletException,IOException {
PrintStreamout=new
PrintStream(res.getOutputStream());
out.println("HelloWorld!");
}
publicStringgetServletInfo(){
return"HelloWorldServlet";
}
}
permetdereprertouslesparamtresdelarequteaumoyendesmthodes:
publicabstractint getContentLength()
publicabstractStringgetContentType()
publicabstractStringgetProtocol()
publicabstractStringgetScheme()
publicabstractStringgetServerName()
publicabstractint getServerPort()
publicabstractStringgetRemoteAddr()
publicabstractStringgetRemoteHost()
publicabstractStringgetRealPath(Stringpath)
publicabstractServletInputStream getInputStream()throws IOException
publicabstractStringgetParameter(Stringname)
publicabstractString[]getParameterValues(Stringname)
publicabstractEnumeration getParameterNames()
publicabstractObjectgetAttribute(Stringname)
disposedetroismthodesqu'ilfaututiliser
pourretournerunerponse.
publicabstractvoidsetContentLength(intlen)
publicabstractvoidsetContentType(Stringtype)
publicabstractServletOutputStream
getOutputStream()throwsIOException
Apartirdequelmomentlaservletestrellementcreetquelest
l'vnementquifaitqu'ellen'existeplus?
Pourlaphasedecration,c'estaudveloppeurdedcider.Pourcela,ilindique
dansledescripteurdedploiementcequ'ildsirefairegrcel'lment
<loadonstartup>.
<servlet>
<loadonstartup>5</loadonstartup>
...
</servlet>
L'lment<loadonstartup>lorsqu'ilestprsent,contientunentierpositif
quiindiquequ'ilfautchargerlaservletaudmarrageduserveur.
L'ordredechargementdesservletsestdterminparcettevaleur.
Lesservletsayantlapluspetitevaleursontchargeslespremires.Encasde
valeursgales,l'ordredechargementestarbitraire.
Sil'lment<loadonstartup>estabsentdansledescripteurde
dploiement,laservletestchargelorsdelapremirerequtesdonneparle
client.
Uneservletdoitimplmenterl'interface
javax.servlet.http
Elledoitcomporterlunedesdeuxmthodes:
doGet()pourlesrequteshttpdetypeGET
doPost()pourlesrequteshttpdetypePOST
publicvoiddoGet(HttpServletRequestreq,
HttpServletResponserep)
throwsServletException,IOException{
Enumerationliste=req.getParameterNames();
String[]valeurs=req.getParameterValues();
Stringval1=req.getParameter(''param1'');
<HTML>
<HEAD><TITLE>ANNUAIRE</TITLE></HEAD>
<BODYBGCOLOR="#FFFFFF"<CENTER>
<CENTER><H1>ANNUAIREDUDESSTIIR</H1></CENTER>
<HR><CENTER>
<H2>Recherchedecoordonnes</H2></CENTER>
<P>Tapezledbutdunomdelapersonnerecherche:
<P><FORMMETHOD=POSTACTION=annuaire >
<INPUTTYPE=TEXTNAME="nom"SIZE=20MAXLENGTH=30
VALUE="">
<P><INPUTTYPE=SUBMITNAME="go"VALUE="RECHERCHER">
<INPUTTYPE=RESETNAME="reset"VALUE="ANNULER">
</FORM>
</BODY></HTML>
importjava.io.*;
importjava.sql.*;
importjavax.servlet.*;
importjavax.servlet.http.*;
publicclassAnnuaire extendsHttpServlet{
publicvoiddoPost(HttpServletRequest req,HttpServletResponse res)
throwsServletException,IOException{
res.setContType("text/html");
PrintWriter out=res.getWriter();
out.println("<HEAD><TITLE>Rponse annuaire </TITLE></HEAD><BODY>");
out.println("<HR>");
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
Stringurl ="jdbc:odbc:mabase";
java.sql.Connection c=DriverManager.getConnection(url,"","");
java.sql.Statement st =c.createStatement();
java.sql.ResultSet rs =
st.executeQuery("Select*frommatable wherenomlike'"
+req.getParameter("nom"+"*'"));
rs.next();
out.println(rs.getString("prenom")+""+rs.getString("nom"));
}
catch(SQLException e){
out.println("Cettepersonnen'existepas");
}
out.println("<P><Ahref =annuaire.html>Retour</A>"</P>);
out.println("</BODY>");
out.close();
}
publicStringgetServletInfo(){
return"Servlet Annuaire";
}
Aulieudutrycatch
<errorpage>
<exceptiontype>java.lang.NumberFormatException
</exceptiontype>
<location>/WEBINF/NombreIncorrect.html
</location>
</errorpage>
ou/etlessouslmentssuivant:
<errorpage>
<codetype>500</exceptiontype>
<location>
/WEBINF/ErreurServeur.html
</location>
</errorpage>
Ajoutdecookieslenttedelarponse
voidHttpServletResponse.addCookie(
Cookiecookie)
Lecookiepeuttreuncookiercuprdansla
requte
Etmodifiavantdtreajoutlarponse
Garderlammoiredesinformationsd'unepagel'autre:
Utiliserlescookies(scurit!)
SyntaxeCGI:paramtresdansl'URL
Champs``HIDDEN''deformulaires
<INPUTTYPE=''HIDDEN''NAME=''PARAM1''VALUE=''VAL1''>
ObjetHttpSession
HttpSessionsession=request.getSession(true);
Classeobjet=(Classe)session.getValue(''param1'');
Mthodes:getValue(),putValue(),removeValue()
HttpSessionsession=req.getSession(true);
If(session.isNew()){
session.putValue('toto'',newint[]{0});
}
Int[]toto=(int[])session.getValue('toto'');
Leserveurmaintientunesessionde2manires:
Cookie(Name:SESSIONIDValue:To1010mC8601021835741167At)
lescookiespeuventtredsactivssurlenavigateur
RcrituredesURLs
Ouverture/rcuprationdunesession
javax.servlet.http.HttpSession session=req.getSession(false);
//lasessionestrcupreounull siellenexistaitpasdj
javax.servlet.http.HttpSession session=req.getSession(true);
//lasessionestrcupreououvertesiellenexistaitpasdj
Invalidationdunesession
javax.servlet.http.HttpSession session=req.getSession(false);
session.invalidate();lasessionestinvalide(i.e.ferme)
javax.servlet.http.HttpSessionsession=req.getSession(false);
Lidentifiant
Stringsessionid=session.getId();//parexemple:To1010mC8601021835741167At
Ladatedecration
longdatecreation=session.getCreationTime();//nbdemsdepus1/1/1970:00:00
Ladatedudernieraccs
longdatelastaccess=session.getastAccessedTime();
Exemple
HttpSessionsession=req.getSession(true);
if(session.getastAccessedTime() session.getCreationTime()>5*60*1000){
session.invalidate();
}
javax.servlet.http.HttpSession session=req.getSession(false);
Mthodedesuividesession
boolean HttpServletRequest.isRequestedSessionIdFromCookie()
//testsilesuividesessionutiliseuncookie
boolean HttpServletRequest.isRequestedSessionIdFromUR ()
//testsilesuividesessionutiliselarcrituredUR
RcrituredesURL(casisRequestedSessionIdFromURL )
lesURLgnresdoiventtreencodespourintgrerlesuividesession
StringHttpServletResponse.encodeRedirectUR (Stringurl)
StringHttpServletResponse.encodeUR (Stringurl)
Exemple
res.sendRedirect(res.encodeRedirectUR ("servlet login");
javax.servlet.http.HttpSession session=req.
getSession(true);
Ajout/remplacementdunevaleur
voidHttpSession.setAttribute(Stringname,Objectvalue)
Suppressiondunevaleur
voidHttpSession.removeAttribute(Stringname)
Rcuprationdesvaleurs/dunevaleur
String[]HttpSession.getAttributeNames()
ObjectHttpSession.getAttribute(Stringname)
Motivations
ragirfacedesvnementsintervenantsdansla/lessessions
4interfacesListeners
HttpSessionActivationListener
lasessionpeuttrepassivepuisractive
HttpSessionListener
changementsurlalistedessessionsactivesdel'applicationWeb.
HttpSessionAttributeListener
changementsurlesattributsdunedessessionsdelapplicationWeb.
HttpSessionBindingListener
unobjetpeuttrenotifidesaliaisonruptureunsession
HttpSessionActivationListener
lasessionpeuttrepassivepuisractive
voidsessionDidActivate(HttpSessionEventse)
voidsessionWillPassivate(HttpSessionEventse)
HttpSessionListener
changementsurlalistedessessionsactivesdel'applicationWeb.
voidsessionCreated(HttpSessionEventse)
VoidsessionDestroyed(HttpSessionEventse)invalidation
HttpSessionAttributeListener
attributelistsofsessionswithinthiswebapplication.
voidattributeAdded(HttpSessionBindingEventse)
voidattributeRemoved(HttpSessionBindingEventse)
voidattributeReplaced(HttpSessionBindingEventse)
HttpSessionBindingListener
unobjetpeuttrenotifidesaliaisonruptureunsession
voidvalueBound(HttpSessionBindingEventevent)
voidvalueUnbound(HttpSessionBindingEventevent)
Motivations
faireragirlesobjetslisauxliaisonsetdliaisons
fermerdesfichiers,desconnexions,validerdestransactions,...
API
interfaceHttpSessionBindingistener
publicvoidvalueBound(HttpSessionBindingEventevent)
publicvoidvalueUnbound(HttpSessionBindingEventevent)
classHttpSessionBindingEventextendsEventObject
publicSessiongetSession()lasessionconcerne
publicStringgetName()lenomdelaliaison
Principe
lobjetlidoitimplantHttpSessionBindingistener
valueBound()estinvoququandlobjetestli(putValue())
valueUnbound()estinvoququandlasessionestinvalidouexpireou
quandlobjetestdli(setAttribute()/removeAttribute()).
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class Binder extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
HttpSession session = req.getSession(true);
SessionObject o = new SessionObject(getServletContext());
session.setAttribute("Binder.object", o);
out.println("<html>");
out.println("<head>");
out.println("<title>Session Binder</title>");
out.println("</head>");
out.println("<body>");
out.println("Object bound to session " + session.getId());
out.println("</body>");
out.println("</html>");
out.flush();
}
}
class SessionObject implements HttpSessionBindingListener {
ServletContext context;
public SessionObject(ServletContext context) {
this.context = context;
}
public void valueBound(HttpSessionBindingEvent event) {
context.log("" + (new java.util.Date()) + " Binding " + event.getName() + " to ses
sion "
+ event.getSession().getId());
}
public void valueUnbound(HttpSessionBindingEvent event) {
context.log("" + (new java.util.Date()) + " Unbinding " + event.getName() + " fro
msession "
+ event.getSession().getId());
}
}
import java.util.Date;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class SessionListen implements HttpSessionListe
ner {
private int sessionCount;
public SessionListen() {
this.sessionCount = 0;
}
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
session.setMaxInactiveInterval(60);
synchronized (this) {
sesesionCount++;
}
String id = session.getId();
Date now = new Date();
String message = nw StringBuffer("New Session create
d on ").append(
now.toString()).append("\nID: ").append(id).append(
"\n")
.append("There are now ").append("" + sessionCount
).append(
" live sessions in the application.").toString();
System.out.println(message);
}
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
String id = session.getId();
synchronized (this) {
sessionCount;
}
String message = newStringBuffer("Session destroyed
"
+ "\nValue of destroyed session ID is").append("" + id)
.append( "\n").append("There are now ").append("" + sess
ionCount)
.append(" live sessions in the application.").toString()
;
System.out.println(message);
}
}
Motivation
partageruneinformationcommuneentre
servlets,...
Plusieurs
S1:utilisezlesPropertiesdejava.lang.System
S2:classecommuneavecdesmembresstatiques
S3:utilisezlecontextedelapplication
Solution1:utiliselesProperties dejava.lang.System
Stringjava.lang.System.getProperty(Stringkey)
Stringjava.lang.System.setProperty(Stringkey,
Stringvalue)
Remarque:lesProperties sontpartagespartoutesles
WebApps duserveurJ2EE
Solution2:classecommuneavecdesmembresstatiques
linitialisationdesmembresstatiquesXXXpeutsefaireau
momentdupremieraccsparunedesservlets
Remarquepourunemeilleureprogrammation
lesmembresstatiquessontprivsetsontaccdspardes
mthodesstatiquessetXXX()etgetXXX()
laclassenestaccessiblequeparlesservlets dummepackage
etchargeparlemmeClassLoader (unparWebApp)
Solution3:utiliserles<env entry>ducontexteJNDIde
lapplication
Pairestypes(name,value,classname)appartenantau
contextedelapplicationWeb
<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>defaultanguage<env entry name>
<env entry value>33<env entry value>
<env entry type>java.lang.Integer<env entry type>
<env entry>
Rcuprationdes<env entry>viaJNDI
Contextctx=newInitialContext();
Objectvalue=ctx.lookup("java:compenvdefaultCurrency");
out.println("Defaultcurrencyvalue:"+value);
ContextenvCtx=(Context)ctx.lookup("java:compenv");
NamingEnumerationenum=ctx.list("java:compenv");
while(enum.hasMoreElements()){
out.print("Binding:"+(enum.nextElement().toString());
}
NamingEnumerationenumbinding=envCtx.listBindings("java:compenv
");
while(enumbinding.hasMoreElements()){
out.print("Binding:"+(enumbinding.nextElement().toString());
Deuxtypesd'entresdufichierweb.xmlcontrlentla
scuritetl'authentification(avectoutefoisuntroisme
pourladfinitiondurle):
<securitycontraint>:quifournissentdesautorisations
basessurlesrlesutilisateurset,sivouslesouhaitez,surle
transportscurisdedonnes.
<loginconfig>:quidtermineletyped'authentification
utilisepourl'applicationWeb.
<securityrole>:quidfinitunrledescuritpour
l'applicationweb.(Aplaceravantlabalise<security
contraint>).
lemodled'URLest/,cequisignifiequetoutel'applicationWebestscurise.Nous
pourrionsscuriserqu'uneseulepartiedel'applicationWeb,parexempleunrpertoirede
l'applicationquineseraaccessiblequeparmotdepasse.
lemodled'identificationBASIC,qui
affichedanslenavigateurunesimple
botededialogue:
nom d'utilisateur/mot de passe
Avantquecelafonctionne,ilrestetoutefoisunetapefranchir:crerlerleutilisateur
"personnel",
PourquevotreapplicationWebsoitparfaitementscurise,ilfaudrait
galementprotgerlesinformationsquitransitentsurlerseau.Ilnous
fautdoncaborderunlmentsupplmentairedelacontraintede
scurit:lagarantiedetransport.
Chaquebloc<securitycontraint>peutfinirparuneentre<userdata
contraint>,quiindiquelequeldestroisniveauxdescuritdetransport
estretenupourleprotocoleutilislorsdutransfertdedonnesdeetvers
lazoneprotges
NONE :quiestquivalentunesortiedesection,sanstransport
spcial.C'estlemodestandardpourletraficweb,quiengnral
vhiculedutextepleinvialerseau.
INTEGRAL :prcisequeleprotocoledetransportutilisdoit
garantirquelesdonnesenvoyesnesontpasmodifiesdurantle
transit.Ceciimpliquel'utilisationdesignaturesdigitalesoudetout
autremthodedevalidationdesdonnesl'arrive,mais
n'imposepasquelesdonnessoientchiffresetcachesdurantle
transport.
CONFIDENTIAL :ajoutelechiffrementlamthodeINTEGRAL.
Enpratique,leseulmodedetransportscurislargementutilis
danslesnavigateurswebestSSL.Exigerunegarantiedetransport
autrequeNONEimposel'utilisationduSSLaunavigateurclient.
Lasection<loginconfig>dtermine
exactementcommentunutilisateur
s'authentifiel'entredelazoneprotge.
Labalise<authmethod>permetd'utiliser
quatretypesd'authentification:
BASIC :utiliselabotededialoguestandard
"nom/motdepasse"dunavigateurweb.
L'authentificationBASICenvoielenometlemotde
passeutilisateurentextepleinsurlerseau,moins
qu'unegarantiedetransportn'aittutilise
sparmentpourdmarrerSSLetchiffrerlestream
dedonnes.
DIGEST :estunevariantedeBASICquicachele
textedemotdepassemaisn'estpasvraiment
beaucoupplusscurise;elleestpeuutilise.
FORM:estquivalenteBASIC,maispermet
d'utiliser,aulieudelabotededialoguestandard,
sonpropreformulaireHTMLouservlet.
CLIENTCERT:estuneoptionintressante.Elle
imposequel'utilisateursoitidentifiviauncertificat
declpubliquectclient.Ceciimpliquel'utilisation
d'unprotocolecommeSSL,quipermetdes
changesscurissetl'authentificationmutuelleen
utilisantdescertificatsnumriques.
Mthodesrelativeslauthentification:
publ i c St r i ng getAuthType( ) : r envoi e BASI C_AUTH,
DI GEST_AUTH, CLI ENT_CERT_AUTH ou FORM_AUTH
publ i c St r i ng getUserName( )
publ i c Pr i nci pal getUserPrincipal( ) ut i l i ser avec
l e package j ava. secur i t y
publ i c bool ean isUserInRole( )
Exempl e:
out.println("Estunadministrateur:"+req.isUserInRole("admin"));.
Redirigelatraitementdelarequteversune
autreservlet ouJSP
UtilispourleMVC
Exemple
publicclassForwardServlet extendsHttpServlet {
publicvoid doGet (HttpServletRequest request,
HttpServletResponse response){
//Settheattributeandforwardtohello.jsp
request.setAttribute ("action","hello");
ServletContext context=getServletConfig().getServletContext().
context.getRequestDispatcher("hello.jsp").forward(request,
response);
}
}