Servlets (fin) Accès aux paramètres GET différend de POST GET : Paramètres dans l'url POST : Paramètres dans l'header Masqué par l'api Méthode getparameter(), getparametervalues() [page de forumulaire] dans le programme : public void doget(httpservletrequest req, httpservletresponse rep) throws ServletException, IOException{ rep.setcontenttype("text/html"); PrintWriter out = rep.getwriter(); String titre = "Lecture des paramètres"; out.println(servletutilities.headwithtitle(titre)."<body bgcolor=\"#fdf5e6\">\n" + "<h1 align=center>" + titre + "</h1>\n" + "<table border=1 align=center>\n" + "<tr bgcolor=\#ffad00\">\n" + "<th>parametre<th>valeur"); Enumeration paramnames = req.getparameternames(); while(paramnames.hasmoreelements()){ String nom = (String)(paramNames.Element()); out.println("<tr><td>"+nom+"\n<td>"); String[] valeurs = req.getparametervalues(nom); if(valeurs.length == 1){ else{ out.print(valeurs[0]); out.println("<ul>"); for(int i=0;i<valeurs.length;i++){ out.println("<li>"+valeurs[i]); out.println("</ul>");
out.println("</table>\n</body>\n</html>"); Ex : 10.4.106.12 : servlet de connexion à un annuaire login : etudiant/etudiant (voir /persist/tomcat-instances/annuaire.com) Gestion de la persistance 1) Les Cookies Petits objets contenant des informations textuelles Le serveur envoie le cookie au client, et peut demander à ce que le client lui renvoie le cookie. Buts : 1. Identifier le client pendant un échange multi-pages 2. Eviter les saisies multiples login/password 3. Adapter les réponses à un profil de client API : class Cookie(nom, valeur) HttpServletResponse.addCookie(Cookie) HttpServletRequest.getCookies() -> Cookie[] Cookie.getName() : String Cookie.getValue() : String 2) URL rewriting Passer les infos souhaités dans l'url de la requête Fonctionne même si les cookies sont désactivés. Sécurité très faible 3) Champs cachés (Hidden Form Fields) <input type="hidden" name="session" value="..."> Valable uniquement sur les pages dynamiques Visible du client 4) Utiliser la classe HttpSession session : ensemble de clés/valeurs (~ensemble de cookies)
ex : HttpSession session = req.getsession(true); // true = créer session si elle n'existe pas. Caddie achats = (Caddie)session.getValue("achats"); // traite achats if(achat!= null) dosomethingwith(achats); else { achats = new Caddie(); dosomethingwith(achats); Problème : Algorithme et présentation sont mélangés dans les méthodes de servlets doget() et dopost() JSP : Java Server Pages But : séparer la partie statique (html) des pages de ce qui dépend de traitements. En général, les moteurs de servlets savent interpréter les jsp. Tags : <%...%> URL : http://host/order.jsp?title=intro+jsp Page :... //html Merci d'avoir acheté <i><%=request.getparameter("title")%></i> Contenu typique : Code html Éléments de script Directives Actions Element de script : Expression introduites par <%=... %> sont évalués et placées dans le code servlet resultant Scriptlets : <%... %> contiennent du code java directement classés dans la méthode service() de la servlet générée. Déclaration <%!... %>
Request response session out... Sont prédéfinis et utilisables. Ex : <%String data = req.getquerystring(); out.println("get data = " +data); %> <%! private int accesscount=0;%> Nombre d'accès à la page = <%=++accesscount%> Directives : Page : import de classe, adaptation de la superclasse... Include : insérer un fichier juste avant la traduction en servlet. <%page attribut = "valeur" ;%> ex : import="moi.maclasse" content-type="data/octet-stream" extends="moi.uneclasse"... <%include file="url relative" %> Actions : Instructions "à la" XML qui précisent l'exécution de la servlet générée. jsp:include -> fichier (dynamique) jsp:usebean -> utiliser un javabean jsp:get/setproperty -> pour un javabean jsp:forward -> redirige vers une autre page jsp:plugin -> code dépendant du client Ex: <jsp:include page="recentnews.html"/> <jsp:usebean id="test" class="moi.beans.exemple"/>
<jsp:setproperty name="test" property="message" value="hello, World"/> <h2>message : <i><jsp:getproperty name="test" property="message"/></i></h2> <jsp:forward page="/util/errorpage.jsp"/> RMI Remote Method Invocation Idée : Deux machines (client/serveur) se partagent la définition d'une interface, et c'est la seule chose qui suffit au client pour que dans son programme, il puisse faire des appels aux services, qui tournent chez le serveur. L'échange se fait en RMI. Interface Programme client Programme serveur Stub/Skeleton Gestion des paramètres de retour RMI Références distantes Extension mécanisme d @ distant Transport Étapes typiques : 1) Interface publiant les services rendus par l'objet 2) Implémentation des services 3) Génération des stub/skeleton 4) Service de nommage (le client peut ne pas savoir quel serveur détient l'objet) 5) Fournisseur de bytecode (serveur FTP/HTTP) Ex : Publication d'un compteur Etape 1 (Serveur) : définition de l'interface // Counter.java package moi.rmi; import java.rmi.*; public interface Counter extends Remote{
public int values() throws RemoteException; public Counter incr() throw RemoteException; public Counter decr() throw RemoteException; // CounterImpl.java package moi.rmi; import java.rmi.*; public class CounterImpl extends UnicastRemoteObject implements Counter{ protected int valeur; public CounterImple() throws RemoteException{ valeur = 0; public Counter incr() throws RemoteException{ valeur++; return this; public Counter decr() throws RemoteException{... public int valeur() throws RemoteException{ return valeur; // CounterServeur.java Programme serveur package moi.rmi; import java.rmi.*; public class CounterServer{ public CounterServer(String nom){ // Nom sous lequel le serveur publiera l'objet dans l'annuaire try{ Counter c = new CounterImpl(); //Etape 1 : Instanciation Naming.rebind("rmi://localhost:1099/"+nom,c); //Etape 2 : enregistrement catch(exception e){system.err.println(e.getmessage); public static void main(string args[]){
String nom = "servicecompteur"; try{nom=args[0];catch(exception e){ new CounterServer(nom); Publication : javac Counter.java CounterImpl.java rmic moi.rmi.counterimpl javac CounterServer.java rmiregistry& java moi.rmi.counterserver compteur Côté client : 1) Doit disposer - De l'url d'accès - Du code de l'interface - Du code du stub 2) Utilisation : CounterClient.java // CounterClient.java package moi.tests; import java.rmi.*; import java.net.*; import moi.rmi.*; public class CounterClient{ public static void main(string args[]){ String host = "localhost"; String nom = "compteur"; try{ host=args[0]; nom=args[1]; catch(exception e){ System.setSecurityManager(new RMISecurityManager()); try{ Counter c = (Counter)Namming.lookup("rmi://"+host+"/"+nom);
System.out.println(c.valeur()); c.incr().incr(); System.out... catch(malformedurlexception e1){... catch(remoteexception e2){... catct(notboundexception e3){... // Erreur sur le host ou le port // rmi.registry absentes // Objet serveur non trouvé Utilisation : $javac CounterClient.java $java moi.tests.counterclient 0 2 $java moi.tests.counterclient 2 4 ~/.java.policy grant{ permission java.security.allpermission "", ""; ; alias java="java -D java.security.policy=$home/.java.policy " java -D java.rmi.server.codebase="http://myserver/mydir" moi.tests.counterclient Communication par Sockets en java Un socket est une paire de tubes : un en lecture/ecriture dans un sens, et l'autre dans l'autre Socket = canal d'entrée, canal de sortie, correspondant, port -> class Socket, java.net Socket(host, port) (String,int) getinputstream() -> InputStream getoutputstream() -> OutputStream
close(); En général, utilisés dans une approche Client/Serveur Ex : Client "echo" (défaut 7) package moi.net; import java.net.*; import java.io.*; public class ClientEcho{ public static void main(string args[]){ Socket s; String host="localhost"; int port = 7777; try{host=args[0];port=integer.parseint(args[1]); catch(exception e){... try{ s=new Socket(host,port); BufferedReader in, stdin; PrintStream out; in = new BufferedReader(new InputStreamReader(s.getInputStream())); out = new PrintStream(s.getOutputStream()); stdin = new BufferedReader(new InputStreamReader(System.in)); String ligne; while(true){ ligne = stdin.readline(); if(ligne.equals(".")) break; out.println(ligne); System.out.println(in.readLine()); s.close(); catch(unknownhostexception e1){... catch(ioexception e2){... Côté serveur : while true attendre demande de connexion client while connexion ouverte lire ligne
traiter ligne envoyer réponse fermer connexion Utilisation de la classe ServerSocket Remarques : 1) Algorithme de serveur mono-threadé. -> Déporter la gestion de la connexion dans un thread ServerSocket(port) java.net accept() -> Socket // Bloquante close() ServerSocket Thread * * TCPServer -nomconnexion : string -port : int +run() +main() Connexion +run() +handle(entrée String) +setsocket(entrée Socket) EchoConnexion AnnuaireConnexion +handle(entrée String) +handle(entrée String)