Servlet - Lebenszyklus Laden meist ein wiederverwendetes Exemplar Instanziieren static{...} static{...} new MyServlet() MyServlet() Initialisieren request response init() init() Bearbeiten service() service() Aufruf von doGet() doGet() oder doPost() doPost() Löschen Komponentenbasierte SoftwareEntwicklung für Entwicklung relevant destroy() destroy() Prof. Dr. Stephan Kleuker 166 Beispiel: Keine Threadsicherheit (1/2) public class TimerServlet extends HttpServlet { private int zv; zv; // unü unüblich @Override public void init() init() { zv = 42; } protected void processRequest(HttpServletRequest request, request, HttpServletResponse response) response) throws ServletException, ServletException, IOException { response.setContentType("text/html;charset=UTFresponse.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); response.getWriter(); out.println((new Date()) + " <br <br> br> "); int tmp=zv; tmp=zv; try { Thread.sleep(10000); } catch (InterruptedException (InterruptedException ex) {} zv = tmp+1; out.println("Wert: out.println("Wert: " + zv); zv); out.close(); out.close(); }... Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 167 Beispiel: Keine Threadsicherheit (2/2) Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 168 Berechnen und Weiterleiten (1/2) public class MachA extends HttpServlet { protected void processRequest(HttpServletRequest request, request, HttpServletResponse response) response) throws ServletException, ServletException, IOException { request.setAttribute("Start", request.setAttribute("Start", new Date());//String,Object // keine responseresponse-Nutzung! Nutzung! try { Thread.sleep(10000); } catch (InterruptedException (InterruptedException ex) { } RequestDispatcher view = request. request. getRequestDispatcher("MachB"); getRequestDispatcher("MachB"); view.forward(request, view.forward(request, response); response); // nichts weiter! } Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 169 Berechnen und Weiterleiten (2/2) public class MachB extends HttpServlet { protected void processRequest(HttpServletRequest request, request, HttpServletResponse response) response) throws ServletException, ServletException, IOException { response.setContentType("text/html;charset=UTFresponse.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); response.getWriter(); try { out.println("Gestartet: out.println("Gestartet: "+request.getAttribute("Start "+request.getAttribute("Start")); request.getAttribute("Start")); out.println("<br>Beendet: out.println("<br>Beendet: "+new "+new Date()); } finally { out.close(); out.close(); } }... Klassenname in web.xml auch als Servlet-Name gesetzt Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 170 HHTP ist zustandslos/gedächtnislos (1/4) <!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"> Transitional//EN"> <html> html> <head> head> <title></title> title></title> <meta httphttp-equiv="Contentequiv="Content-Type" Type" content="text/html; content="text/html; charset=UTFcharset=UTF-8"> </head </head> head> <body> body> <form name="amnesie" name="amnesie" action="Amnesie" action="Amnesie" method="POST"> method="POST"> Programmiersprache Nr.1? <input type="text" type="text" name="prog1" value="" value="" size="12" /> <input type="submit" type="submit" value="Abschicken" value="Abschicken" name="send1" /> </form> </body </body> body> </html </html> html> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 171 HHTP ist zustandslos/gedächtnislos (2/4) public class Amnesie extends HttpServlet { protected void processRequest(HttpServletRequest request, request, HttpServletResponse response) response) throws ServletException, ServletException, IOException { response.setContentType("text/html;charset=UTFresponse.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); response.getWriter(); String prog1 = request.getParameter("prog1"); try { if (prog1 == null) { out.println("Sprache 1: " +request.getAttribute("prog1")); out.println("<br> out.println("<br> Sprache 2: " + request.getParameter("prog2")); } else {...//nä {...//nächste Folie Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 172 HHTP ist zustandslos/gedächtnislos (3/4) else { request.setAttribute("prog1", prog1); // nur Versuch out.println("<html><head></head>"); out.println("<html><head></head>"); out.println("<body>"); out.println("<body>"); out.println("<form name=\ name=\"a2\ "a2\" action=\ action=\"Amnesie\ "Amnesie\" " + "method= "method=\ method=\"POST\ "POST\">Programmiersprache Nr.2?"); out.println("<input type=\ type=\"text\ "text\" name=\ name=\"prog2\ "prog2\" " + "value "value= value=\"\" size=\ size=\"12\ "12\" />"); out.println("<input type=\ type=\"submit\ "submit\" " + "value= "value=\ value=\"Abschicken\ "Abschicken\" name=\ name=\"send1\ "send1\" />"); out.println("</form></body></html>"); out.println("</form></body></html>"); } } finally { out.close(); out.close(); } }... Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 173 HHTP ist zustandslos/gedächtnislos (4/4) Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 174 Session (1/2) ...String String prog1 = request.getParameter("prog1"); HttpSession session = request.getSession(true); request.getSession(true); try { if (prog1 == null) { out.println("Sprache 1: "+session.getAttribute("prog1")); out.println("<br> out.println("<br> Sprache 2: " + request.getParameter("prog2")); } else { session.setAttribute("prog1", prog1); out.println("<html><head></head>"); out.println("<html><head></head>"); ... • in web.xml wichtig: (Minuten, -1 für unbeschränkt) <sessionsession-config> config> <sessionsession-timeout> timeout> 30 </session </sessionsession-timeout> timeout> </session </sessionsession-config> config> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 175 Session (2/2) Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 176 HTTPSession • ein Objekt, dass dem Servlet zugeordnet wird • Objekt lebt von erster Servlet-Nutzung bis Nutzer Verbindung terminiert, Server terminiert, Servlet neu deployt wird oder Time-out • mit HttpSession session = request.getSession(true); request.getSession(true); erhält man Session-Objekt (mit „true“ wird neue Session erzeugt, falls keine existiert, mit „false“ erhält man null falls keine Session existiert) • Anmerkung: true kann weggelassen werden; ist default unsere Ziele: • Nutzer muss sich erst einloggen, wenn notwendig • HTTPS nur nutzen, wenn nichts anderes möglich Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 177 Cookie zur Nutzeridentifikation • Nutzer bekommt beim ersten Kontakt individuelle Session ID HTTP WebWeb-Server GET … Client GET … Web Server Steuerung ... HTTP … <HTML> <HTML> [Cookie] [Cookie] … Komponentenbasierte SoftwareEntwicklung Web Server Steuerung erster Kontakt: berechne ID, erstelle Cookie … Prof. Dr. Stephan Kleuker ... 178 Containerunterstützung für Cookies • wir teilen mit, ob neue Session gewünscht ist, oder Session genutzt wird • Container erzeugt Session ID • Container erzeugt Cookie mit Session ID als Inhalt • Container macht Cookie zum Teil von response • Achtung zwei Wirkungen einer Methode HttpSession session = request.getSession(true): request.getSession(true): if (request enthä enthält Cookie mit Session ID) finde Session mit der genannten ID else if (request enthä enthält keinen Cookie mit Session ID oder es gibt keine aktuelle Session mit der ID) erzeuge neue Session • Methode isNew() isNew() erlaubt Prüfung, ob Session gerade erzeugt Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 179 Browser ohne Cookie-Unterstützung • Cookies können im Browser ausgeschaltet werden • Container ermöglicht auch hier (unsicherere) Session IDNutzung • bei ausgeschalteten Cookies liefert isNew() immer true (was ursprünglichen Ansatz verhindert) • Lösung: URL Rewriting, Parameter jsessionid in URL • Ansatz: immer wenn URL (Pfad) ausgegeben werden soll, dann encode nutzen out.println("<form name=\ name=\"a2\ "a2\" action= action=\"" +response.encodeURL("/ServletSpielerei4/Amnesie2") +"\ +"\" method=\ method=\"POST\ "POST\">Programmiersprache Nr.2?"); Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 180 Garantieren von URL-Rewriting • In spezieller Datei des Web-Servers; Glassfish: sun-web.xml <session<session-config> config> <session<session-properties> <property name="enableCookies name="enableCookies" enableCookies" value="false" /> <property name="enableURLRewriting name="enableURLRewriting" enableURLRewriting" value="true" /> </session</session-properties> </session</session-config> config> • URL-Rewriting bei Weiterleitung: response.encodeRedirectURL( response.encodeRedirectURL("/Mach2" /Mach2"); Generell bei der Entwicklung • Browser nach Nutzung schließen! • Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 181 Irritationsversuch mit Session Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 182 Phishing (geht so auch ohne Cookie und Servlet) :NaiverNutzer :ITBoesewicht Email: Gratis auf www.bankk.de Geht auf Seite www.bankk.de Session-Cookie+ Login? ID+Passwort+ Session-Cookie Peinliche Daten+ Session-Cookie :Servlet Verbindung zu www.bank.de Session-Cookie ID+Passwort+ Session-Cookie Peinliche Daten+ Session-Cookie Bösewicht kann sich nach Passworterhalt ausklinken Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 183 Phishing mit Session ID :NormalerNutzer :ITBoesewicht :UnerfahrenesServlet Verbindung zu www.bank.de Email: Gratis auf Session ID www.bank.de/jsession mit Session ID Geht auf Seite www.bank.de mit Session ID Session ID+Login? ID+Passwort+Session ID nutzt Session ID für eigene Entdeckungen Gegenmaßnahmen: - Timeout für Sessions setzen - session.invalidate() session.invalidate() um Session bei Login zu beenden - nach Login neue Session ID vergeben Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 184 Weitere interessante Möglichkeiten • Event-Listener (welchen Zustandswechsel führt ein Servlet aus, welches Attribut ändert sich, ..) z. B. Zählen aktiver Sessions • Servlet kann Parameter im Deployment Descriptor haben, die gelesen werden können • HTTPSession-Objekte können serialisiert werden und von einer zur anderen virtuellen Maschine wandern • Applikation (Summe der zusammengehörigen Servlets) kann (Context-) Parameter im Deployment Descriptor haben, die gelesen werden können Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 185 5. JavaServer Pages • • • • Prinzip: Java in HTML Typisches Tags JSP-Lebenszyklus MVC2 Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 186 Vorgehensweise • Bekannt: Servlets erlauben Erstellung von WebApplikationen, leider viel HTML in Java • JSP-Ansatz: Java in HTML einbetten • Hier zunächst: JSP-Grundlagen getrennt betrachten • Späteres Ziel: Vereinigung von Servlets, JSP, JavaBeans, JPA zur strukturierten mehrschichtigen Software Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 187 Einführendes Beispiel <%@page <%@page contentType="text/html" contentType="text/html" pageEncoding="UTFpageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN" Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> html> <head> head> <meta httphttp-equiv="Contentequiv="Content-Type" Type" content="text/html; content="text/html; charset=UTFcharset=UTF-8"> <title>Zahlen</title> title>Zahlen</title> </head </head> head> <%@page <%@page import="java.util.List, import="java.util.List, java.util.ArrayList" java.util.ArrayList" %> <%! List<Integer> List<Integer> zahlen = new ArrayList<Integer>();%> ArrayList<Integer>();%> <% for (int i = 1; i < 10; i = i + 3) zahlen.add(i); zahlen.add(i); %> <body> body> <h3>Zahlen!</h3> <ul> ul> <% for (Integer i : zahlen) { %> <li> li> <%=i%> </li </li> li> <% }%> </ul </ul> ul> </body </body> body> </html </html> html> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 188 Typische Sprachelemente • <%@ page [eigenschaften] eigenschaften] %> Direktiven, hier Seiteneigenschaften, Info für Container • <%! [Deklaration] %> Deklaration von in der Seite nutzbaren Methoden, Variablen • <% [Programmstü [Programmstück] %> Ausführbare Code-Fragmente (Scriptlets) • <%= [Ausdruck] %> Auswertbarer Ausdruck, nutzt toString() toString() • Anmerkung: Gibt auch reine XML-Syntax (wesentlich sauberer, aber später eingeführt und längere Tipperei, daher seltener genutzt) <jsp:directive.page [eigenschaften] eigenschaften] /> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 189 JSPs sind Servlets C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\JSPSpielerei1\org\apache\jsp public final class index_jsp extends // aus index.jsp org.apache.jasper.runtime.HttpJspBase...{ org.apache.jasper.runtime.HttpJspBase...{ List<Integer> List<Integer> zahlen = new ArrayList<Integer>(); ArrayList<Integer>(); ... public void _jspService(HttpServletRequest request, request, HttpServletResponse response) response) throws java.io.IOException, java.io.IOException, ServletException {... try { response.setContentType("text/html;charset=UTFresponse.setContentType("text/html;charset=UTF-8"); response.setHeader("Xresponse.setHeader("X-PoweredPowered-By", By", "JSP/2.1"); ... for (int i = 1; i < 10; i = i + 3) zahlen.add(i); zahlen.add(i); ... for (Integer i : zahlen) { out.write("\ out.write("\n"); out.write(" <li out.write(" <li>"); li>"); out.print(i); out.print(i); out.write("</li>\ out.write("</li>\n"); out.write(" out.write(" "); }... Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 190 Implizite Objekte - Ausschnitt (1/2) <%@page <%@page contentType="text/html" contentType="text/html" pageEncoding="UTFpageEncoding="UTF-8"%> <html> html> <head> head> <title>Implizite <title>Implizite Objekte</title> Objekte</title> </head </head> head> <% response.setContentType("text/html;charset=UTFresponse.setContentType("text/html;charset=UTF-8"); %> <% if (session.isNew()) session.isNew()) { session.setAttribute("Zaehler", session.setAttribute("Zaehler", 1); } %> <body><form name="f1" action="index.jsp" action="index.jsp" method="POST"> method="POST"> <% if (request.getParameter("n") request.getParameter("n") != null){%> letzte Nachricht: <%=request.getParameter("n <%=request.getParameter("n")%> request.getParameter("n")%> <br <br> br> <% ;}%> Nachricht:<input type="text" type="text" name="n" name="n" value="" value="" size="12" /> <% int anzahl = (Integer) session.getAttribute("Zaehler"); session.getAttribute("Zaehler"); out.println("<br> out.println("<br> Ihre Aufrufe: " + (anzahl++)+"<br (anzahl++)+"<br>"); anzahl++)+"<br>"); session.setAttribute("Zaehler", session.setAttribute("Zaehler", anzahl); anzahl); %> <input type="submit" type="submit" value="Weiter" value="Weiter" name="w1" /> </form></body </form></body> form></body> </html </html> html> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 191 Implizite Objekte - Ausschnitt (2/2) Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 192 JSP - Lebenszyklus JSP-Seite in Servlet übersetzen [ja] JSP-Seite kompilieren Erster Aufruf? Klasse laden [nein] Instanziieren Initialisieren jspInit() jspInit() request Bearbeiten _jSPservice() service() response Löschen Komponentenbasierte SoftwareEntwicklung für Entwicklung relevant jspDestroy() jspDestroy() Prof. Dr. Stephan Kleuker 193 Nutzung von Beans (1/2) • Generell können in Servlets und JSPs selbst entwickelte JavaKlassen (POJO, Plain Old Java Objects) direkt genutzt werden • Um möglichst wenig Java in JSPs zu haben existieren sogenannte Aktionselemente (Action Elements) • Idee: XML-artige Erzeugung und Nutzung von Beans • Beanerzeugung <jsp:useBean id="kunde" id="kunde" class="entities.Kunde" class="entities.Kunde" /> entspricht kunde = new entities.Kunde(); entities.Kunde(); id: (Variablen-)Name, auch kunde.getAdresse() kunde.getAdresse() möglich class: voll qualifizierter Klassenname scope: Gültigkeitsbereich (page, request, session, application) type: Typ der Variablen kunde Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 194 Nutzung von Beans (2/2) • Set-Methode (auch für Attribute und Properties aus request) <jsp:setProperty name=" name="kunde" kunde" property=" property="adresse" adresse" value=“ value=“Xstr. Xstr. 42" /> entspricht kunde.setAdresse( kunde.setAdresse("XStr. XStr. 42" 42"); name: vergebene id property: name der zu ändernden Eigenschaft value: Wert (wird konvertiert, wenn möglich) param: Alternativ Parameter aus request nutzbar • Get-Methode (auch für Attribute und Properties aus request) <jsp:getProperty name="kunde name="kunde" kunde" property="adresse property="adresse" adresse" /> entspricht kunde.getAdresse(); kunde.getAdresse(); name s.o; property: zu lesende Eigenschaft Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 195 Basis-Design-Pattern für Web-Applikationen • Ansatz heißt Model-View-Controller 2 (MVC2) Servlet request liest als Controller schreibt übergibt Kontrolle (und request) request) JSP response JavaBean als Model liest als View Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 196 Kombination von HTML, Servlets und JSP (1/6) package entities; entities; public class Kunde { private String name; name; private int alter; private String Adresse; public Kunde(){} public Kunde(String name, name, int alter, String Adresse) { this.name = name; name; this.alter = alter; this.Adresse = Adresse; } // getget- und setset-Methoden für die Attribute Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 197 Kombination von HTML, Servlets und JSP (2/6) <!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"> Transitional//EN"> <html> html> <!-<!-- index.html --> --> <head> head> <title>Detailanfrage</title> title>Detailanfrage</title> <meta httphttp-equiv="Contentequiv="Content-Type" Type" content="text/html; content="text/html; charset=UTFcharset=UTF-8"> </head </head> head> <body> body> <form name="suche" name="suche" action="Suche"> action="Suche"> Name: <input type="text" type="text" name="name" name="name" value="" value="" size="15" /> <input type="submit" type="submit" value="Abschicken" value="Abschicken" name="send" name="send" /> </form> </body </body> body> </html </html> html> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 198 Kombination von HTML, Servlets und JSP (3/6) public class Suche extends HttpServlet { private Set<Kunde> Set<Kunde> kunden = new HashSet<Kunde>(); HashSet<Kunde>(); @Override public void init(){ init(){ kunden.add(new Kunde("Ute",42,"XStr. 3")); kunden.add(new Kunde("Urs",43,"YStr. 9")); kunden.add(new Kunde("Ulf",44,"YStr. 3")); } protected void processRequest(HttpServletRequest request, request, HttpServletResponse response) response) throws ServletException, ServletException, IOException { String name= name= request.getParameter("name"); request.getParameter("name"); Kunde ergebnis= ergebnis= new Kunde(name,Kunde(name,-1,"fehlt"); for(Kunde k:kunden) k:kunden) if(k.getName().equals(name)) if(k.getName().equals(name)) ergebnis=k; ergebnis=k; request.setAttribute("erg", request.setAttribute("erg", ergebnis); ergebnis); RequestDispatcher view = request.getRequestDispatcher("ergebnis.jsp"); request.getRequestDispatcher("ergebnis.jsp"); view.forward(request, view.forward(request, response); response); }... Komponentenbasierte SoftwareProf. Dr. Entwicklung Stephan Kleuker 199 Kombination von HTML, Servlets und JSP (4/6) <%@page <%@page contentType="text/html" contentType="text/html" pageEncoding="UTFpageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN" Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> html> <head> head> <meta httphttp-equiv="Contentequiv="Content-Type" Type" content="text/html; content="text/html; charset=UTFcharset=UTF-8"> <title>Suchergebnis</title> title>Suchergebnis</title> </head </head> head> <body> body> Name: <jsp:getProperty <jsp:getProperty name="erg" name="erg" property="name"/> property="name"/> <br <br> br> Alter: <jsp:getProperty <jsp:getProperty name="erg" name="erg" property="alter"/> property="alter"/> <br <br> br> Adresse: <jsp:getProperty <jsp:getProperty name="erg" name="erg" property="adresse"/> property="adresse"/> </body </body> body> </html </html> html> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 200 Kombination von HTML, Servlets und JSP (5/6) <?xml <?xml version="1.0" encoding="UTFencoding="UTF-8"?> <webweb-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchemaxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webhttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> servlet> <servletservlet-name>Suche</servletname>Suche</servlet-name> name> <servletservlet-class>servlets.Suche</servletclass>servlets.Suche</servlet-class> class> </servlet </servlet> servlet> <servletservlet-mapping> mapping> <servletservlet-name>Suche</servletname>Suche</servlet-name> name> <urlurl-pattern>/Suche</urlpattern>/Suche</url-pattern> pattern> </servlet </servletservlet-mapping> mapping> <welcomewelcome-filefile-list> list> <welcomewelcome-file>index.html</welcomefile>index.html</welcome-file> file> </welcome </welcomewelcome-filefile-list> list> </web </webweb-app> app> Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 201 Kombination von HTML, Servlets und JSP (6/6) Komponentenbasierte SoftwareEntwicklung Prof. Dr. Stephan Kleuker 202