Advanced Java Services | Java Server Pages |
Während in einem Servlet HTML in Java eingebettet werden muß, schreibt man in einer Java Server Page Javacode in HTML. In der ersten Version der Java Server Pages gab es nur Scripting Elemente. Mit Scriptlets schreibt man Javacode in eine Html-Seite. Ein Parser liest dann diese Datei und erzeugt daraus ein Servlet. Beim ersten Aufruf einer JSP wird die textdatei geparst , das zugehörige Servlet erzeugt und gestartet. Daher dauert der erste Aufruf einer JSp immer etwas länger als die darauffolgenden Aufrufe, denn da steht das Servlet schon im Speicher. Eine Java Server Page wird direkt ins zugehörige Verzeichnis der Webapplikation gelegt.
Webanwendungen werden unterhalb des Verzeichnisses webapps angelegt. Das Bild zeigt den Standardaufbau einer JSP-Webapplikation an Hand des Verzeichnisses mit dem Namen HelloWorldapp. Im Einfachsten Fall gibt es keine class-Dateien und damit auch kein Verzeichnis mit dem Namen classes. JSP können jedoch mit Javaobjekten zusammenarbeiten, den sog. JSP-Beans. Diese Klassen liegen dann wieder in einem classes-Verzeichnis und müssen in einem Unterverzeichnis liegen, das ein Packageverzeichnis ist. Im Gegensatz zu Servlets ist hier das Deafultpackage nicht zulässig. Es kann auch mehrere Packages geben. Das Verzeichnis lib dient demselben Zweck wie bei Servlets. Wenn man mit JSTL arbeitet, was meistens der Fall ist, muß man das entsprechende Archiv in das lib-Verzeichnis legen. Hier sieht man zusätzlich die Datei log4j-x.x.xx.jar mit der man zum Debuggen Meldungen in eine log-Datei schreiben kann. Dieses Tool wird von der Apache Software Foundation zur Verfügung gestellt. Im Verzeichnis WEB-INF liegt die Konfigurierungsdatei web.xml und hier die zu log4j gehörende properties-Datei, mit der man log4j konfiguriert.
Wie oben erwähnt erzeugt ein Parser im ServletContainer aus der Java Server Page ein Servlet Nehmen wir an, unsere JSp heiße HelloWorld.jsp und liege in der Webappliaktion HelloWorldApp. Dann wird in Tomcat die JSP wie folgt angesprochen:
http://<servername>:<portnumber>/HelloWorldApp/HelloWorld.jsp
Das zu dieser JSP gehörende Servlet legt Tomcat dann tief ins work-Verzeichnis
<TomcatHome>\work\Catalina\localhost\HelloWorldApp\org\apache\jsp\HelloWorld_jsp.java <TomcatHome>\work\Catalina\localhost\HelloWorldApp\org\apache\jsp\HelloWorld_jsp.class
Da zu einer JSP ein Servlet erzeugt wird gibt es zwei web.xml Dateien. Eine web.xml liegt im Verzeichnis der Webapplikation, in der die JSP liegt. Die zweite web.xml-Datei liegt im Vezeichnis
<TomcatHome>\conf
Diese Datei enthält mehrere Servlet-Einträge. Der für Java Server Pages zuständige Eintrag lautet:
<servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>xpoweredBy</param-name> <param-value>false</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet>
Es gibt also in Tomcat noch eine weitere Servletdatei. Die Datei org.apache.jasper.servlet.JspServlet arbeitet im Hintergrund und tritt immer dann in Aktion, wenn eine JSP mit der Endung *.jsp gestartet wird.
Von Scriptlets wird mittlerweile aus guten Gründen abgeraten, siehe weiter unten. Trotzdem soll hier aus historischen Gründen mit einer Übersicht über die verschiedenen Scripting-Elemente begonnen werden.
Die Scripting-Elemente werden hier an Hand von Beispielen vorgestellt.
Code-Element | Scripting in HTML |
---|---|
Importanweisung (Spezialfall einer Direktive) |
<%@ page import = "java.util.*" %> <%@ page import = "java.util.*, java.io.*" %> |
Deklaration/Definition |
<%! StringBuilder sb = new StringBuilder("Hallo");%> <%! int i = 17;%> |
Statement |
<% i = (int)(49*(Math.random()+1)); %> |
Ausdruck |
<%= (int)(49*(Math.random()+1)) %> (kein Leerzeichen zwischen % und =) |
if/else |
<% if (user.name().equals("Max")) { %> <p>Welcome, Max!</p> <% } else { %> <p>Welcome, guest!</p> <% } %> |
for |
<% for ( int i = 0; i < n; i++ ) { %> Number: <%= i+1 %><br/> <% } %> |
Kombination mehrerer Scriptlets |
<%! class Authors { String[] authors = {"Anatole France", "Guy de Maupassant"}; public String[] getAuthors() { return authors; } } %> <% Authors aut = new Authors(); %> <% String[] authors = aut.getAuthors(); if (authors != null) { %> <br/> <b>You selected the following authors:</b> <ul> <% for (String author : authors) { %> <li><%= author %></li> <% } } %> </ul> |
Es gibt in JSP acht implizite Objekte, auch vordefinierte Variablen genannt, die aufgrund ihrer Namen den direkten Bezug zu Servlets zeigen: application, config, out, page, pageContext, request, response, session.
Implizite Objekte und ihre Superklassen | ||||
---|---|---|---|---|
Implizites Objekt |
Klasse | Superklasse | Supersuperklasse | Implementiertes Interface (Es gibt höchstens eines) |
application | org.apache.catalina.core.ApplicationContextFacade | java.lang.Object | no superclass | javax.servlet.ServletContext |
config | org.apache.catalina.core.StandardWrapperFacade | java.lang.Object | no superclass | javax.servlet.ServletConfig |
out | org.apache.jasper.runtime.JspWriterImpl | javax.servlet.jsp.JspWriter | java.io.Writer | no interface |
page | org.apache.jsp.predefined_jsp | org.apache.jasper.runtime.HttpJspBase | javax.servlet.http.HttpServlet | org.apache.jasper.runtime.JspSourceDependent |
pageContext | org.apache.jasper.runtime.PageContextImpl | javax.servlet.jsp.PageContext | no superclass | no interface |
request | org.apache.catalina.connector.RequestFacade | java.lang.Object | no superclass | javax.servlet.http.HttpServletRequest |
response | org.apache.catalina.connector.ResponseFacade | java.lang.Object | no superclass | javax.servlet.http.HttpServletResponse |
session | org.apache.catalina.session.StandardSessionFacade | java.lang.Object | no superclass | javax.servlet.http.HttpSession |
JSP Direktiven geben Anweisungen und Informationen an den Servlet/JSP Container.
Die page-Direktive und ihre Verwendung wurde bereits erwähnt. Direktiven können auch Attribute haben. Die allgemein Form einer Direktive ist wie folgt.
Form einer Direktive | |
---|---|
Scriptlet-Stil | XML-konformer Stil |
<%@ directiveName attribute1="value1" attribute2="value2"%> | <jsp:directive.directiveName attribut1="value1" attribut2="value2" /> |
Die Attribute sind key-value Paare die durch ein Leerzeichen oder einen Zeilenumbruch nicht aber durch ein Komma getrennt werden. Es kann auch mehr als zwei Attribute geben. Das Leerzeichen nach @ ist optional, ebenso das Leerzeichen nach dem letzten Attribut.
Es gibt nur drei verschiedene Direktiven. In der XML-Form steht der Name der Direktive nach dem Punkt nach "directive".
Direktive (Script-Form) | Direktive (XML-Form) | Beschreibung |
---|---|---|
<%@ include ... %> | <jsp:directive.include ... /> | Fügt beim Parsen der JSP die angegebene Datei ein. |
<%@ page ... %> | <jsp:directive.page ... /> | Vereinbart seitenspezifische Attribute, etwa welche Skriptsprache, welches Encoding, welche Fehlerseite verwendet werden soll. |
<%@ taglib ... %> | <jsp:directive.taglib ... /> | Deklariert eine tag library |
Mit der include-Direktive kann man externe Dateien einbinden. Diese Direktive kann überall stehen und die angegebene Datei wird dann an dieser Stelle während des Übersetzungsvorgangs eingefügt. Es gibt nur das Attribut file.
include Direktive (Script-Form) | include Direktive (XML-Form) |
---|---|
<%@ include file="relative-url"> | <jsp:directive.include file="relative url" /> |
Die page-Direktive verfügt über dreizehn verschiedene Attribute.
autoFlush, buffer, contentType, errorPage, isErrorPage, extends, import, info, isELIgnored, isScriptingEnabled,
isThreadSafe, language, session.
page Direktive (Script-Form) | page Direktive (XML-Form) | Werte | Beschreibung |
---|---|---|---|
<%@ page autoFlush="true"%> | <jsp:directive.page autoFlush="false" /> | true (default) false |
true = Ausgabepuffer wird automatisch geleert, wenn notwendig. false = Falls der Ausgabepuffer voll ist wird eine Exception geworfen. |
<%@ page buffer="none"%> | <jsp:directive.page buffer="16kb" /> | none XXkb |
Angabe von "none" bedeutet, daß Daten sofort zum response-Objekt geschickt werden. Andernfalls werden Sie in einem Ausgabepuffer der angegebenen Größe zwischengespeichert. Wird meist zusammen mit dem autoFlush-Attribut verwendet. |
<%@ page contentType="text/html"%> | <jsp:directive.page contentType="text/html:charset=ISO-8859-1" /> | text/html (default) bel. mimetype |
Setzt den Texttyp und das Encoding. |
<%@ page errorPage="myerrorpage.html"%> | <jsp:directive.page errorPage="myerrorpage.html" /> | relative URL | Setzt die Seite, die angezeigt wird, wenn auf der aktuellen Seite eine Exception geworfen wird, die nicht auf der Seite abgefangen wird. |
<%@ page isErrorPage="myerrorpage.html"%> | <jsp:directive.page isErrorPage="myerrorpage.html" /> | false (default) true |
Zeigt an, daß diese Seite aufgrund eines errorPage-Atrributs einer anderen Seite aufgerufen wird. |
<%@ page extends="aPackage.aClass"%> | <jsp:directive.page extends="aPackage.aClass" /> | false (default) true |
Gibt eine Superklasse an, von der das generierte Servlet erben muß. |
<%@ page import="java.util.*"%> | <jsp:directive.page import="java.util.*" /> | Importattribut (siehe erste Tabelle). | |
<%@ page info="InfoText"%> | <jsp:directive.page info="InfoText" /> | String | Definiert einen String den die Methode getServletInfo() liefert. |
<%@ page isELIgnored="true"%> | <jsp:directive.page isELIgnored="false" /> | false true |
Gibt an, ob EL (expression language) ignoriert wird oder nicht. EL wurde mit JSP 2.0
eingeführt und wird im nächsten Kapitel besprochen. true bedeutet, daß die EL Ausdrücke wie Text behandelt werden.
The default value varies depending on the version of the web application deployment descriptor. The default mode for JSP pages delivered using a Servlet 2.3 or earlier descriptor is to ignore EL expressions; this provides backward compatibility. The default mode for JSP pages delivered with a Servlet 2.4 descriptor is to evaluate EL expressions; this automatically provides the default that most applications want. (siehe) |
<%@ page isScriptingEnabled="true"%> | <jsp:directive.page isScriptingEnabled="false" /> | true (default) false |
Bestimmt ob Scriptelemente zulässig sind. Steht der Schalter auf false, so werden Scriptelemente vom JSP-Parser nicht mehr akzeptiert, EL-Ausdrücke (expression language) dürfen jedoch verwendet werden. |
<%@ page isThreadSafe="true"%> | <jsp:directive.page isThreadSafe="false" /> | true (default) false |
Gibt an, ob eine Seite thread-safe ist. Wird diese Option auf false gesetzt, so stellt die JSP-Engine sicher, daß diese Seite nur von einem einzigen Thread ausgeführt wird. |
<%@ page language="java"%> | <jsp:directive.page language="java" /> | java (default) | Gibt die Programmiersprache an, die auf der JSP-Seite verwendet wird. |
<%@ page session="true"%> | <jsp:directive.page session="false" /> | true (default) false |
Gibt an, ob die JSP-Seite eine HTTPSession verwendet. true bedeutet, daß die JSP-Seite auf das implizite Objekt session zugreifen kann. |
Die JSP-Spezifikation stellt mittlerweile die Existenz einer Library von Standard Tags sicher (JSTL). es können aber auch eigene Tags eingeführt werden. Diese werden mit einer taglib Direktive dem Parser bekanntgemacht. Die JSTL wird im übernachsten Kapitel besprochen.
taglib Direktive (Script-Form) | taglib Direktive (XML-Form) |
---|---|
<%@ taglib uri="uri" prefix="prefixOfTag" > | <jsp:directive.taglib uri="uri" prefix="prefixOfTag" /> |
Scriptelemente wurden 2001 mit der ersten Version von JSP eingeführt. Bei der Vorstellung der Scriptelemente zeigt besonders das letzte Beispiel Kombination mehrerer Scriptlets die Mängel dieses Konzepts. Ständig wird zwischen HTML und Java hin- und hergesprungen. Der Javacode enthält oft nur Schnipsel und nicht einmal vollständige Statements. Daraus resultiert sofort ein ganzes Bündel von Problemen.
Mit den nächsten JSP Versionen wurden deshalb zwei Neuerungen eingeführt, die Scriptelemente ablösen können.