Protokoll Stunde 11

Werbung
Praktikum aus Softwareentwicklung 2, Stunde 11
Lehrziele/Inhalt
1. Java Servlet
Java Servlet
Java Servlets sind auf Java basierende Web-Komponenten. Sie werden von einem Container
verwaltet und können dynamisch Inhalt erzeugen. Ein Container (Servlet-Engine) ist ein Teil eines
Web-Servers, leitet Anfragen an die Servlets und liefert Antworten zurück. Der Container verwaltet
die Servlets über ihren Lebenszyklus hinweg. Abbildung 12 zeigt die grobe Architektur von
Webanwendungen die auf Java Servlets aufbauen.
Die Spezifikation der Java Servlets kann in JSR 145 für die Version 2.5 und in JSR 315 für die Version
3.0 nachgelesen werden. Die Version 3.0 bringt einige interessante Neuerungen, die wir besprechen
werden. Es ist aber interessant sich auch mit Version 2.5 zu beschäftigen, um die Grundlagen zu
verstehen und weil einige Web-Hoster nur Version 2.5 verstehen, zB Google App Engine.
Client
Request
Web-Server & Servlet-Engine
Firefox, Opera, Chrome,
Internet Explorer, …
Response
GlassFish, Tomcat, jetty://, …
Servlet 1
Servlet 2
Servlet 3
Ressourcen
Dateien,
Datenbanken, …
Abbildung 12) Grobe Architektur von Webanwendungen mit Servlets
Servlets vs. Common Gateway Interface
Java Servlets sind vergleichbar mit dem Common Gateway Interface (CGI) und proprietären ServerErweiterungen. Servlets haben folgende Vorteile:



Schneller als CGI-Skripte, weil der Code im Speicher bleibt und der Prozess nach einer
Anfrage weiterläuft. Bei CGI wird pro Aufruf ein Prozess gestartet
Unterstützung für Sitzungen, CGI ist von sich aus zustandslos
In Java entwickelt:
o Nur von der JavaVM abhängig, aber sonst Systemunabhängig
o Große Klassenbibliothek
© Markus Löberbauer 2010
Seite 41
Entwickeln eines Servlets
Will man ein Servlet entwickeln, muss man eine Klasse schreiben die das Interface Servlet im Packet
javax.servlet implementiert. Servlets sind generisch gehalten, die Methode service(ServletRequest,
ServletResponse) bekommt eine Anfrage (ServletReqest) und beantwortet diese im ServletResponse.
Dabei wird keine Aussage getroffen woher die Anfragen kommen. Meistens schreibt man aber
Servlets für das Web, die Http-Anfragen beantworten. Dazu leitet man von HttpServlet ab, das ist
eine abstrakte Basisklasse die von GenericServlet ableitet und Servlet implementiert.
HttpServlet hat eine Methode für jede Http-Methode (GET, HEAD, POST, PUT, DELETE, TRACE,
CONNECT und OPTIONS), zB doGet für Get-Anfragen und doPost für Post-Anfragen. Je nachdem
welche Http-Methoden man unterstützen will muss man die zugehörige Servlet-Methode
überschreiben. Das Servlet in Abbildung 13 beantwortet Get-Anfragen mit dem Text „Hello!“.
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
try {
out.println("Hello!");
} finally {
out.close();
}
}
}
Abbildung 13) Beispiel Hello World Servlet
Installieren von Web-Anwendungen
Um Web-Anwendungen in einem Servlet-Container wie zB Tomcat zu installieren muss man einen
Deployment Descriptor (web.xml) schreiben. Für das Beispiel in Abbildung 13 ist die web.xml in
Abbildung 14 gegeben. Abbildung 15 zeigt die Verzeichnisstruktur von Tomcat 6 mit installiertem
Hello-Beispiel. Im Verzeichnis webapps sind die Installierten Web-Anwendungen, in unserem Fall
hello5. Im Verzeichnis der Web-Anwendung kann beliebiger Inhalt liegen zB: Bilder oder HTMLDateien, dieser Inhalt kann über Web-Zugriffe abgefragt werden. Die Einzige Ausnahme ist das
Verzeichnis WEB-INF, das ist vor Zugriffen von außen geschützt. In diesem liegen die Servlets im
Verzeichnis classes und falls nötig jar-Dateien im Verzeichnis lib.
© Markus Löberbauer 2010
Seite 42
Abbildung 15Abbildung
15
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>
at.jku.ssw.psw2.servlet.hello.HelloServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello.do</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>hello.do</welcome-file>
</welcome-file-list>
</web-app>
Abbildung 14) web.xml für Beispiel Hello World Servlet
Abbildung 15) Verzeichnisstruktur von Tomcat 6
© Markus Löberbauer 2010
Seite 43
Lebenszyklus von Servlets
Der Servlet-Container lädt die Klasse des Servlets, erzeugt ein (!) Objekt, d.h. die Felder werden
einmal initialisiert und leben so lange das Servlet-Objekt lebt. Clients (Web-Browser) stellen Anfragen
an den Web-Server, dieser ruft die Servlet-Engine auf und diese leitet die Anfrage an das Servlet
weiter. Pro Anfrage erzeugt die Servlet-Engine einen Thread, d.h. mehrere Threads können
gleichzeitig Methoden auf einem Servlet-Objekt ausführen. Die Servlet-Engine bestimmt wann ein
Servlet weggeworfen wird, dabei muss das Servlet Ressourcen frei geben und eventuell seinen
Zustand speichern. Der Lebenszyklus aus der Sicht eines Servlets ist in Abbildung 16 zu sehen.
init(ServletConfig)
Variablen initialisieren, Ressourcen anfordern
service(HttpRequest, HttpResponse)
doGet(HttpRequest, HttpResponse)
doPost(HttpRequest, HttpResponse)
doPut(HttpRequest, HttpResponse)
...
destroy()
Ressourcen freigeben
Eventuell Zustand speichern
Abbildung 16) Lebenszyklus eines Servlets
Sitzungen (Sessions)
Http ist ein nicht sitzungsorientiertes Protokoll. Sinnvolle Web-Anwendungen benötigen aber
Sitzungen, zB: Warenkorb einer Shop-Anwendung oder Anmeldung einer E-Mail-Anwendung. Intern
verwenden Servlets Cookies, URL-Parameter und versteckte Formular-Felder zur SitzungsVerwaltung. Für den Programmierer wird die Sitzungsverwaltung über die Klasse HttpSession
abstrahiert.
Servlet 3.0
Am 10 Dezember 2009 hat Sun die Spezifikation für Servlet 3.0 veröffentlicht. Mit Version 3.0 werden
Annotationen eingeführt mit denen man Informationen aus dem Deployment Descriptor direkt zu
den Servlet-Klassen schreiben kann. Das Beispiel Hello World Servlet aus Abbildung 13 kann mit der
Annotation @WebServlet angereichert werden, dadurch kann man die Information aus web.xml
entfernen. Der neue Code und die neue web.xml ist in Abbildung 17 bzw. Abbildung 18 gegeben.
© Markus Löberbauer 2010
Seite 44
@WebServlet(name = "HelloServlet", urlPatterns = {"/hello.do"})
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
try {
out.println("Hello from JavaEE 6!");
} finally {
out.close();
}
}
}
Abbildung 17) Beispiel Hello World Servlet mit @WebServlet Annotation
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>hello.do</welcome-file>
</welcome-file-list>
</web-app>
Abbildung 18) web.xml für Beispiel Hello World Servlet mit @WebServlet Annotation
Um dieses Servlet ausführen zu können braucht man einen Web-Container der Servlets in der
Version 3.0 unterstützt, zB: GlassFish Server 3, jetty:// (Experimental) oder Tomcat 7 (in
Entwicklung).
JavaServer Pages (Erstellen von HTML-Seiten)
Servlets sind die Basis der Java Web-Technologie. Will man aber HTML-Seiten aus Servlets erstellen
ist das sehr aufwendig. Man müsste programmatisch, über den PrintWriter, den ganzen Text in den
HttpServletResponse schreiben. Um den Standard-Anwendungsfall HTML-Seiten zu erstellen wurden
JavaServer Pages eingeführt.
JavaServer Pages (JSP) werden vom Web-Container in Servlets übersetzt und dann wie alle anderen
Servlets behandelt. Der Web-Container übersetzt JSPs bei Veränderungen automatisch neu.
Schreiben von JSPs ist Servlet-Programmierung auf einer abstrakten Ebene.
Man kann mit JSPs alles machen was man auch mit Servlets machen kann. Aber man soll Servlets und
JSPs als Team verwenden: wobei Servlets den Ablauf steuern, die Daten aufbereiten und die
Geschäftslogik ansprechen; und JSPs die Darstellung übernehmen. Die Trennung entspricht dem
Model-View-Controller-Muster, diese Architektur heißt in der Java Servlet Welt „Model 2
Architecture“. Die selten Verwendete „Model 1 Architecture“ benutzt JSPs zur Ablaufsteuerung und
Darstellung; die Datenaufbereitung und Verbindung zur Geschäftslogik erfolgt in Java Beans. Heute
© Markus Löberbauer 2010
Seite 45
wird fast nur mehr die „Model 2 Architecture“ eingesetzt, weil sie klarer und einfacher ist.
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<html>
<head>
<title>Hello Page</title>
</head>
<body>
Hello!
</body>
</html>
Abbildung 19) Beispiel Hello World JSP
public final class hello_jsp extends
org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
// ...
public void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write("
<title>Hello Page</title>\r\n");
out.write(" </head>\r\n");
out.write(" <body>\r\n");
out.write("
Hello!\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");
out.write("\r\n");
} catch (Throwable t) {
// ...
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
Abbildung 20) Generiertes Servlet für Hello World JSP
© Markus Löberbauer 2010
Seite 46
Abbildung 19 zeigt eine einfache Hello World JSP. Abbildung 20 zeigt dazu Ausschnitte aus dem
generierten Java Servlet. Man kann sehen wie die Zeilen aus der JSP-Datei in einzelne writeAnweisungen im Code verwandelt werden. Will man für eine JSP das generierte Servlet sehen, kann
das in Tomcat unter work/Catalina/localhost/<Web-Anwendung>/org/apache/jsp/<JSPName>_jsp.java.
© Markus Löberbauer 2010
Seite 47
Herunterladen