HttpURLConnection | Java Server Pages JSP |
Bei der Client-Server-Programmierung kann man sich auf die Socket-Ebene zurückziehen und alles selbst programmieren und auch das Protokoll selbst festzulegen. Die Alternative ist ein Application-Server wie Glassfish oder Tomcat, der als Protokoll HTTP verwendet und den „technischen Kram“ übernimmt.
Um die Clientanfragen inhaltlich zu bearbeiten, ruft der Application Server ein Servlet auf. Ein Servlet ist ein Java-Programm-Modul, das die Anfrage des Clients liest und eine Antwort zusammensetzt.
Ein Client für HTTP kann mit einer HttpURLConnection erstellt werden.
Servlets sind die Basiskomponenten bei der Programmierung von Jakarta/Java Enterprise Edition. Die anderen Technologien wie Java Server Pages (JSP), Java Server Faces (JSF), SOAP oder REST setzen darauf auf.
Für die Erstellung von Servlets benötigt man eine Entwicklungsumgebung, die einen Application-Server in die IDE einbindet.
Die Klassen Servlet und HttpServlet
In der Regel arbeiten Servlets auf der Basis des Protokolls HTTP. Darum erweitert ein Servlet die Klasse HttpServlet, welche ihrerseits die Klasse Servlet erweitert.Vom Interface Servlet erbt ein Servlet die Methoden init und destroy, die es polymorph überschreiben kann. Die Methode init wird beim ersten Start des Servlets aufgerufen und die Methode destroy, wenn das Servlet entfernt wird.
Die Methode getServletConfig kann die Konfiguration auslesen. Die Methode init erhält als Parameter das Objekt der Klasse ServletConfig, das vom Application Server für das Servlet angefertigt wurde. Es enthält Informationen aus der Konfigurationsdatei web.xml, die Eclipse freundlicherweise automatisch erstellt hat.
Die Methode getServletInfo ermittelt den Info-String.
Bei Anfragen von einem Client wird die Methode service aufgerufen. Sie liefert in ihren Parametern alle Informationen zur Anfrage (request)und den Ausgabekanal (response).
void service(ServletRequest request, ServletResponse response) throws ServletException, IOException;In der Regel verwendet ein Servlet HTTP und darum erweitert es die Klasse HttpServlet, die ihrerseits das Interface Servlet implementiert.
Die Klasse HttpServlet stellt statt der Methode service Methoden zur Auswertung von HTTP-Kommandos zur Verfügung. Am häufigsten werden doPost zur Reaktion auf POST-Anfragen, doGet für GET-Anfragen überschrieben, seltener auch doPut für PUT und doDelete für DELETE. Alle diese Methoden haben die gleichen Parameter wie service.
Erstellen eines Servlets mit Eclipse
Unter Eclipse können Sie den Rahmen eines Servlets automatisch erstellen. Zunächst benötigen Sie ein Projekt für den Application-Server, ein Dynamic Web Project:- Aus dem Menue: File|New|Project
- In dem Dialog Web|Dynamic Web Project
- Den Button Next ein neuer Dialog erscheint.
- Project name: Hier wird ein neuer Projektname eingegeben
- Wenn bei Target runtime nur None steht, muss zunächst die Einbindung des Application Servers erfolgen.
- Der Klick auf Finish erzeugt das Projekt.
- Rechtsklick auf das Projekt. Dann New|Servlet anklicken.
- Package leer lassen
- Class name: GetForm Dieser Name wird Bestandteil der URL.
- Zwei Mal Next klicken.
- Nur schauen: Hier gibt es die Methoden doGet, doPost, doPut, doDelete, init, destroy
- Finish erzeugt das Servlet.
@WebServlet("/GetForm") public class GetForm extends HttpServlet { public GetForm() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("Served at: ") .append(request.getContextPath()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
- @WebServlet bestimmt den Pfad hinter der URL. Damit meldet sich das Servlet beim Application-Server als zuständig für diesen URL-Pfad an. Alle Anfragen auf diesen Pfad gehen an das Servlet.
- Der Konstruktor ruft den Konstruktor der Basisklasse.
- doPost ruft einfach doGet
- doGet verwendet den Parameter für die Antwort (response), um einen Writer zu holen und an diesen einen String zu senden. Jeder Aufruf von append hängt einen weiteren String an.
- getContextPath wird über den Anfrage-Parameter request aufgerufen.
Ein HTML-Formular erstellen
Bei der Erstellung einer HTML-Datei kann Eclipse helfen.- Das Projekt mit der rechten Maustaste anklicken.
- New|HTML File wählen
- Als Dateiname index.html eingeben.
- Finish anklicken
<form action=GetForm method=get> <input type=submit value="Start"> </form>
- Rechtsklick auf die Datei index.html im Projektordner WebContent.
- Run As|Run on Server
- Es erscheint ein Kleinst-Browser im Editorbereich mit einem Start-Button.
- Auf den Button Start klicken.
Served at: /TestServlet
Datenverkehr und Parameter
Wir erweitern nun die HTML-Seite und fügen zwei Eingabefelder hinzu. Diese sollen nun per POST an das Servlet gelangen, das diese auslesen soll und eine Tabelle als Ergebnis vorweisen soll.<form action="GetForm" method="post"> <table> <tr> <td>Name</td> <td><input type=text name=user value="" size=30 /></td> </tr> <tr> <td>E-Mail</td> <td><input type=text name=email value="" size=30 /></td> </tr> <tr> <td><input type=submit value="Einfügen" /></td> <td></td> </tr> </table> </form>Jetzt können wir das Servlet aufbohren, so dass doPost das Formular ausliest und den Inhalt an den Client zurücksendet.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("<!DOCTYPE html>\n<html><body>" + "Benutzer: " + request.getParameter("user") + " E-Mail: " + request.getParameter("email") + "<p/><a href=\"TestServlet.html\">zurück</a>" + "</body></html>"); }In den HTML-Code wurde noch ein kleiner Link geschummelt, der zum wiederholten Ausprobieren auf die Eingabeseite zurückführt.
Ein Blick auf die Parameter HttpServletRequest und HttpServletResponse
HttpServletRequest request
Über den Parameter request kann die Umgebung des Aufrufs ausgelesen werden.- getParameter liest ein input über den übergegeben Namen aus.
String str = request.getParameter("user");
- getParameterValues ist für Eingabeelemente, die mehrere
Komponenten haben, beispielsweise Radio- oder Check-Buttons.
Dort werden alle Elemente in ein String-Array gelesen.
String[] str = request.getParameterValues("radiobutton");
- getParameterNames liefert alle Namen der Eingabeelemente eines
FORMs.
Diese landen in einem String-Array, das dann wieder verwendet werden
kann, um über getParameter die Inhalte zu lesen.
String[] names = request.getParameterNames();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("<table>"); // Hole alle Parameterbezeichner Enumeration<String> controls = request.getParameterNames(); while (controls.hasMoreElements()) { String controlName = controls.nextElement(); // Zeige den Parameterbezeichner response.getWriter().println("<tr><td>" + controlName); // Zeige den eingegeben Wert response.getWriter().println("</td><td>" + request.getParameter(controlName) + "</td></tr>"); } response.getWriter().println("</table>"); }
HttpServletResponse response
Über den Parameter response wird der Zugriff auf die Antwort an den Client eröffnet.- getWriter eröffnet einen Writer auf den Ausgabekanal,
dem mit add immer weitere Strings angefügt werden können.
Alternativ kann auch die Methode print verwendet werden.
PrintWriter out = response.getWriter(); out.add(“\n... out.print(“\n...
Diese Methode wird von ServletResponse geerbt, bezieht sich also nicht auf HTTP, funktioniert, aber beißt sich ggf mit den HTTP-Aufrufen. - getOutputStream: Hier gilt Gleiches wie bei getWriter. Der ServletOutputStream bietet die Methode write an und wird hauptsächlich für Binärdaten verwendet.
- sendRedirect sendet eine Nachricht an den Client, dass er
die übergebene URL aufrufen soll.
response.sendRedirect(“index.html“)
- setStatus und setError übergeben die HTTP-Fehlermeldungen
im HTTP-Header an den Client. Die HTTP-Fehler liegen als Konstanten vor.
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.sendError(HttpServletResponse.SC_NOT_FOUND);
- setHeader ermöglicht das Setzen von Header-Werten.
response.setHeader("Location", "alternativ.html");
Internes Dispatchen
Der Aufruf von response.sendRedirect gibt die Meldung über die Antwort (response) an den Client weiter, sich an eine andere URL zu wenden. Das Servlet kann den Auftrag aber auch intern an ein anderes Servlet weiterleiten, indem es über die Anfrage-Variable (request) einen Request-Dispatcher auslöst.RequestDispatcher dispatch = request.getRequestDispatcher("anzeige.jsp"); dispatch.forward(request, response);In diesem Zusammenhang kann es von Interesse sein, Attribute der request mit setAttribute zu hinterlegen. Diese können am Ziel mit getAttribute ausgelesen werden.
request.setAttribute("name", strName); // ... String str = request.getAttribute("name");
Projektstruktur
Die Struktur eines dynamischen Webprojekt hat in Eclipse folgendes Aussehen:+ TestServlet + Java Ressources | Hier stecken die Java-Quelltexte, also die Servlets ... + WebContent + META-INF + WEB-INF | + web.xml | + lib (für Libraries) index.html TestServlet.html
HttpSession
HTTP-Kommunikation kennt eigentlich keine Sessions, die aber gebraucht werden, um beispielsweise einen Einkauf über mehrere Seiten zu verfolgen.Allerdings stellt das Servlet eine einfache Lösung zur Verfügung. Aus dem Request-Parameter kann mit der Methode getSession die aktuelle Session ermittelt werden. Gibt es noch keine, wird eine angelegt.
HttpSession session = request.getSession();
Sessions können mit Cookies realisiert werden, durch Erweitern der URL um eine Session-ID (insbesondere bei GET) oder durch verborgene Eingabeelemente. Standardmäßig werden Cookies verwendet.
Mit den folgenden Methoden kann der Session Werte zugeordnet werden:
- setAttribute("attributname", wert)
- wert = getAttribute("attributname")
- removeAttribute("attributname");
Weitere Methoden des Request-Parameters
String str = request.getHeader("User-Agent"); Cookie[] cookies = request.getCookies(); InputStream in = request.getInputStream();