1. Einführung in Servlet
Servlet ist eine Technologie von Sun Company zur Entwicklung dynamischer Webressourcen.
Sun bietet eine Servlet -Schnittstelle in seiner API. Wenn Benutzer eine dynamische Webressource senden möchten (dh ein Java -Programm, um Daten an den Browser auszugeben), müssen sie die folgenden zwei Schritte ausführen:
1. Schreiben Sie eine Java -Klasse, um die Servlet -Schnittstelle zu implementieren.
2. Bereiten Sie die entwickelten Java -Klassen auf dem Webserver ein.
Nach einer herkömmlichen Namensgewohnheit nennen wir normalerweise Java -Programme, die das Servlet Interface Servlet implementieren.
2. Der Betriebsprozess von Servlet
Das Servlet -Programm wird vom Webserver aufgerufen. Nachdem der Webserver die Servlet -Zugriffsanforderung des Clients empfängt hat:
①Der Webserver prüft zunächst, ob er geladen wurde, und ein Instanzobjekt des Servlets erstellt. Wenn ja, dann führen Sie Schritt 4 direkt aus; Andernfalls führen Sie Schritt 2 aus.
② Laden und erstellen Sie ein Instanzobjekt des Servlets.
③Call die Init () -Methode des Servlet -Instanzobjekts.
④ Erstellen Sie ein httpServletRequest -Objekt zum Einkapseln von HTTP -Anforderungsnachrichten und ein httpServletResponse -Objekt, das HTTP -Antwortnachrichten darstellt, und rufen Sie dann die Methode des Servlets auf und geben Sie die Anforderungs- und Antwortobjekte als Parameter weiter.
⑤ Bevor die Webanwendung gestoppt oder neu gestartet wird, deinstalliert die Servlet -Engine das Servlet und ruft die Methode des Servlets Center () vor dem Deinstallieren auf.
3. Servlet Call Diagramm
V.
Erstellen Sie ein neues Webprojekt in Eclipse, und Eclipse erstellt automatisch die in der folgende Abbildung gezeigte Verzeichnisstruktur:
4.1. Implementierungsklasse der Servlet -Schnittstelle
Die Servlet Interface Sun Company definiert zwei Standard -Implementierungsklassen, nämlich: GenericServlet und httpServlet.
HTTPServlet bezieht sich auf ein Servlet, das HTTP -Anfragen verarbeiten kann. Es fügt der ursprünglichen Servlet -Schnittstelle einige HTTP -Protokollverarbeitungsmethoden hinzu, die leistungsfähiger ist als die Servlet -Schnittstelle. Daher sollten Entwickler beim Schreiben von Servlets diese Klasse normalerweise erben und vermeiden, die Servlet -Schnittstelle direkt zu implementieren.
Wenn HttpServlet die Servlet -Schnittstelle implementiert, überschreibt sie die Servicemethode. Der Code in der Methodegremium ermittelt automatisch die Anforderungsmethode des Benutzers. Wenn es sich um eine GET -Anforderung handelt, wird die DoGet -Methode von httpServlet aufgerufen. Wenn es sich um eine Postanforderung handelt, wird die Dopost -Methode aufgerufen. Daher müssen Entwickler beim Schreiben von Servlets normalerweise nur die DoGet- oder Dopost -Methode überschreiben, anstatt die Servicemethode zu überschreiben.
4.2. Erstellen und schreiben Sie Servlets durch Sonnenfinsternis
Wählen Sie das Paket gacl.servlet.study, klicken Sie mit der rechten Maustaste auf → Neu → Servlet, wie in der folgenden Abbildung gezeigt:
Auf diese Weise werden wir Eclipse verwenden, um uns dabei zu helfen, einen Servlet mit dem Namen ServletDemo1 zu erstellen. Der erstellte ServletDemo01 wird der folgende Code geben:
Paket gacl.servlet.study; import java.io.ioxception; import java.io.printwriter; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; importieren javax.servlet.http.httpletrequest; javax.servlet.http.httpServletResponse; public class servletDemo1 erweitert HttpServlet { /*** Die DOGT -Methode des Servlets. <br> * * Diese Methode wird aufgerufen, wenn ein Formular seine Tag -Wert -Methode entspricht. * * @Param Anfrage Die vom Client vom Server gesendete Anforderung * @param Antwort Die vom Server vom Client gesendete Antwort an den Client * @throw servletException, wenn ein Fehler aufgetreten ist * @throws ioException, wenn ein Fehler aufgetreten ist Printwriter out = response.getWriter (); out.println ("<! docType html public/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<kopf> <titels> a servlet </title> </head>"); out.println ("<body>"); out.print ("this is"); out.print (this.getClass ()); out.println ("mit der GET -Methode"); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); } /*** Die Dopost -Methode des Servlets. <br> * * Diese Methode wird aufgerufen, wenn ein Formular seine Tag -Wert -Methode entspricht. * * @Param Anfrage Die vom Client vom Client an den Server gesendete Anforderung * @param Antwort Die vom Server vom Server an den Client gesendete * @throws servletException Wenn ein Fehler aufgetreten ist * @throws ioException, wenn ein Fehler aufgetreten ist response.setContentType ("text/html"); Printwriter out = response.getWriter (); out.println ("<! docType html public/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<html>"); out.println ("<kopf> <titels> a servlet </title> </head>"); out.println ("<body>"); out.println ("<body>"); out.println ("this is"); out.print (this.getClass ()); out.println (", mit der Post -Methode"); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); }}Diese Codes werden automatisch durch Eclipse generiert, und es gibt zwei Tags von Tags in der Web.xml-Datei, <servlet> </Servlet> und <Servlet-Mapping> </Servlet-Mapping>. Diese beiden Tagspaare sind mit ServletDemo1 konfiguriert, wie in der folgenden Abbildung gezeigt:
Dann können wir über den Browser auf das ServletDemo1 -Servlet zugreifen, wie in der folgenden Abbildung gezeigt:
5. Achten Sie auf Details in der Servletentwicklung
5.1. Servlet Access URL -Zuordnungskonfiguration
Da der Client über eine URL -Adresse auf Ressourcen auf Ressourcen zugreift, muss das Servlet -Programm einer URL -Adresse zugeordnet werden. Diese Arbeit erfolgt in der Datei web.xml mit dem Element <Servlet> und <servlet-Mapping>.
Mit dem Element <Servlet> wird ein Servlet registriert. Es enthält zwei Hauptelemente für Kinder: <Servlet-Name> und <Servlet-Klasse>, mit denen der Registrierungsname des Servlets bzw. den vollständigen Klassennamen des Servlets festgelegt wird.
Ein <Servlet-Mapping> Element wird verwendet, um einen externen Zugriffspfad einem registrierten Servlet zuzuordnen. Es enthält zwei untergeordnete Elemente: <Servlet-Name> und <URL-Muster>, mit denen der Registrierungsname des Servlets und den externen Zugangspfad des Servlets angegeben wird. Zum Beispiel:
<servlet> <servlet-name>ServletDemo1</servlet-name> <servlet-class>gacl.servlet.study.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </Servlet-Mapping> Das gleiche Servlet kann auf mehrere URLs abgebildet werden, dh der Einstellungswert des <servlet-namens> untergeordneten Elements mehrerer <Servlet-Mapping> kann der Registrierungsname desselben Servlets sein. Zum Beispiel: <Servlet> <Servlet-Name> ServletDemo1 </Servlet-Name> <Servlet-Class> gaCl.servlet.study.servletDemo1 </Servlet-Class> </Servlet> <servlet-Mapping> <Servlet-Mapping <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/1.htm</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/2.jsp</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/3.php</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-mapping> <Servlet-name> servletDemo1 </Servlet-name> <URL-Muster> /4.aspx </url-pattern> </Servlet-Mapping>
Wenn wir über die obige Konfiguration mit dem Namen ServletDemo1 auf ein Servlet zugreifen möchten, können wir die folgenden Adressen verwenden, um zugreifen zu können:
http: // localhost: 8080/javaweb_servlet_study_20140531/servlet/servletDemo1
http: // localhost: 8080/javaweb_servlet_study_20140531/1.htm
http: // localhost: 8080/javaweb_servlet_study_20140531/2.jsp
http: // localhost: 8080/javaweb_servlet_study_20140531/3.php
http: // localhost: 8080/javaweb_servlet_study_20140531/4.aspx
ServletDemo1 wird mehreren URLs zugeordnet.
5.2. Verwenden Sie * Wildcard -Mapping für Servlet Access -URLs
Das*Wildcard -Zeichen kann auch in den URLs verwendet werden, zu denen der Servlet kartiert, aber es kann nur zwei feste Formate geben: Eine ist die "*. Erweiterung", und der andere ist der Start mit einem Vorwärtsstrahl (/) und endet mit einem "/*". Zum Beispiel:
<servlet> <Servlet-Name> ServletDemo1 </Servlet-Name> <Servlet-Class> gaCl.servlet.study.servletDemo1 </Servlet-Class> </Servlet> <Servlet-Mapping> <Servlet-Name> ServletDemo1 </Servlet-Name> <url-pattern>/*</*</*</*</*</*</*</*</*</*</*</*</*</*</*</*</*</*</*
*Es kann zu jedem Zeichen übereinstimmen, sodass Sie jede URL verwenden können, um auf das ServletDemo1 -Servlet zuzugreifen, wie in der folgenden Abbildung gezeigt:
Für einige Mapping -Beziehungen unten:
Servlet1 Karten zu /abc /*
Servlet2 Karten zu /*
Servlet3 Karten nach /ABC
Servlet4 Karten zu *.do
Frage:
Wenn die Anfrage -URL "/abc/a.html" ist ","/abc/*"und"/*"beide übereinstimmen, wobei Servlet auf den Servlet -Engine reagiert, wird Servlet1 anrufen.
Wenn die Anfrage -URL "/ABC" ist, wird sowohl "/ABC/*" als auch "/ABC" übereinstimmen, die Servlet auf die Servlet -Engine reagiert, nennt Servlet3.
Wenn die Anfrage -URL "/abc/a.do" ist, wird sowohl "/ABC/*" und "*.do" Match angegeben, welches Servlet auf den Servlet -Engine wird Servlet1 anruft.
Wenn die Anfrage -URL "/a.do" ist, wird sowohl "/*" als auch "*.do" übereinstimmen, welcher Servlet auf den Servlet -Engine reagiert, wird Servlet2 anrufen.
Wenn die Anfrage -URL "/xxx/yyy/a.do" ist, wird sowohl "/*" als auch "*.do" Match, welches Servlet auf Servlet Engine antwortet, wird Servlet2 anrufen.
Das Prinzip der Übereinstimmung lautet: "Wer eher so aussieht, wie es mehr aussieht, wer immer mehr aussieht."
5.3. Der Unterschied zwischen Servlet und gewöhnlichen Java -Klassen
Servlet ist eine Java -Klasse für Anruf anderer Java -Programme (Servlet -Motoren). Es kann nicht unabhängig ausgeführt werden und der Betrieb wird vom Servlet -Motor vollständig kontrolliert und geplant.
Für mehrere Servlet -Anfragen vom Client erstellt der Server normalerweise nur ein Servlet -Instanzobjekt. Das heißt, sobald das Servlet -Instanzobjekt erstellt wurde, befindet es sich im Speicher und dient anderen nachfolgenden Anforderungen. Das Servlet -Instanzobjekt wird erst zerstört, wenn der Webcontainer beendet ist.
Während des gesamten Lebens eines Servlets wird die Init -Methode des Servlets nur einmal aufgerufen. Jede Zugangsanforderung an einen Servlet führt dazu, dass die Servlet -Engine die Servlet -Service -Methode einmal anruft. Für jede Zugriffsanforderung erstellt die Servlet -Engine ein neues HTTPServletRequest -Anforderungsobjekt und ein neues HTTPServletResponse -Antwortobjekt und übergeben diese beiden Objekte dann als Parameter an die Dienstleistung () des IT -Aufrufs. Die Dienstmethode ruft dann die Doxxx -Methode gemäß der Anforderungsmethode auf.
Wenn im <DERNLET> -Element ein <Lad-on-Startup> -Element konfiguriert ist, wird das Servlet-Instanzobjekt geladen, wenn die Webanwendung gestartet wird, und ruft die Methode init () des Servlet-Instanzobjekts auf.
Zum Beispiel:
<servlet> <servlet-name> invoker </servlet-name> <Servlet-Klasse> org.apache.catalina.servlets.invokerServlet </Servlet-Class> <Load-on-Startups> 1 </load-on-Startup> </servlet>
Zweck: Schreiben Sie einen InitServlet für die Webanwendung. Dieses Servlet ist so konfiguriert, dass das Start geladen wird, um die erforderlichen Datenbanktabellen und Daten für die gesamte Webanwendung zu erstellen.
5.4. Standard -Servlet
Wenn der Zuordnungspfad eines Servlets nur ein Vorwärtsschräger (/) ist, wird dieses Servlet zum Standard -Servlet der aktuellen Webanwendung.
Jede URL des passenden <Servlet-Mapping> -Elements, das in der Datei web.xml nicht gefunden werden kann, werden ihre Zugriffsanforderungen an das Standard-Servlet zur Bearbeitung übergeben. Das Standard-Servlet wird verwendet, um Zugriffsanforderungen zu verarbeiten, die nicht von anderen Servlets verarbeitet werden. Zum Beispiel:
<servlet> <Servlet-name> servletDemo2 </Servlet-name> <Servlet-Class> gacl.servlet.study.servletDemo2 </Servlet-Class> <Load-on-Startups> 1 </load-on-Startup> </servlet> <!-Konfigurieren Sie ServletDemo2 als Default-Servlet-> <servlet-> <Servlet> <servlet> <Servlet> <! <Servlet-name> servletDemo2 </servlet-name> <URL-Muster>/</url-pattern> </Servlet-Mapping>
Beim Zugriff auf ein nicht existierendes Servlet wird das konfigurierte Standard-Servlet zur Verarbeitung verwendet, wie in der folgenden Abbildung gezeigt:
In der Datei <Tomcat -Installationsverzeichnis> /conf/web.xml ist ein Servlet namens org.apache.catalina.servlets.DefaultServlet registriert, und dieses Servlet wird als Standardservlet festgelegt.
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value> false </param-value> </init-param> <Load-on-startup> 1 </load-on-startup> </servlet> <!-Das Mapping für das Standard-Servlet-> <Servlet-Mapping> <Servlet-Name> Standard </servlet-name> <Rl-PATTERN>/</url-patter> </</</</</</</</</</</</</</</</</</</</Servlet-Name>
Wenn Sie auf dem Tomcat -Server auf eine statische HTML -Datei und -bild zugreifen, greifen Sie tatsächlich auf dieses Standard -Servlet zu.
5.5. Sicherheitsprobleme des Servlet -Threads
Wenn mehrere Clients gleichzeitig auf das gleiche Servlet zugreifen, erstellt der Webserver einen Thread für die Zugriffsanforderung jedes Kunden und ruft die Servicemethode des Servlet in diesem Thread auf. Wenn daher bei der Servicemethode auf dieselbe Ressource zugegriffen wird, kann dies zu Sicherheitsproblemen führen. Zum Beispiel der folgende Code:
Code, der keine Thread -Sicherheitsprobleme aufweist:
Paket gacl.servlet.study; import Java.io.ioxception; import Javax.servlet.servletException; import Javax.servlet.http.httpServlet; importieren javax.servlet.http.httpletrequest; javax.servlet.http.httpServletResponse; public class servletDemo3 erweitert HttpServlet (public void dodget (httpServletRequest), httpServletRetReplet -Reaktion). Auf die I -Variable wird gleichzeitig durch mehrere Threads zugegriffen, aber es gibt kein Problem mit der Gewindesicherheit, da ich eine lokale Variable in der DoGet -Methode ist. * Wenn mehrere Threads gleichzeitig auf die DoGet-Methode zugreifen, hat jeder Thread eine eigene I-Variable. i ++; Antwort.getWriter (). Schreiben (i); } public void dopost (httpServletRequest Request, httpServletResponse -Antwort) löst ServletException aus, ioException {dodget (request, response); }} Code mit Thread -Sicherheitsproblemen:
Paket gacl.servlet.study; import java.io.ioxception; import javax.servlet.servletException; import javax.servlet.http.httpServlet; importieren javax.servlet.http.httpletRequest; HttpServlet {int i = 1; public void dodget (httpServletRequest Request, httpServletResponse -Antwort) löst ServletException aus, ioException {i ++; try {thread.sleep (1000*4); } catch (interruptedException e) {e.printstacktrace (); } response.getWriter (). Schreiben (i+""); } public void dopost (httpServletRequest Request, httpServletResponse -Antwort) löst ServletException aus, ioException {dodget (request, response); }}Definieren Sie I als globale Variable. Wenn mehrere Threads zu Zugangsvariablen i gleichzeitig zugreifen, gibt es die Sicherheitsprobleme von Threads, wie in der folgenden Abbildung gezeigt: Schalten Sie zwei Browser gleichzeitig ein, um den gleichzeitigen Zugriff auf dasselbe Servlet zu simulieren. Normalerweise sollte der erste Browser 2 sehen, und der zweite Browser sollte 3 sehen, aber beide Browser sehen 3, was nicht normal ist.
Die Sicherheitsprobleme von Threads existieren nur, wenn mehrere Threads gleichzeitig dieselbe Ressource betreiben. Beim Schreiben eines Servlets, wenn gleichzeitig auf eine bestimmte Ressource (Variable, Sammlung usw.) zugegriffen wird, gibt es Probleme mit Thread -Sicherheit. Wie kann man dieses Problem lösen?
Schauen wir uns den folgenden Code an:
Paket gacl.servlet.study; import java.io.ioxception; import javax.servlet.servletException; import javax.servlet.http.httpServlet; importieren javax.servlet.http.httpletRequest; HttpServlet {int i = 1; public void dodget (httpServletRequest Request, httpServletResponse -Antwort) löst ServletException aus, IOException { /*** Nach der Synchronisierung gibt es kein Problem mit der Sicherheit von Thread -Sicherheit, wenn der gleichzeitige Zugriff auf i. * Warum gibt es kein Problem mit Thread -Sicherheit, nachdem die Synchronisierung hinzugefügt wurde? * Wenn jetzt ein Thread auf das Servlet -Objekt zugreift, wird zuerst das Schloss des Servlet -Objekts erhalten* Nach seiner Ausführung wird das Schloss an das Servlet -Objekt zurückgegeben. Da es zum ersten Mal die Schloss des Servlet -Objekts erhält, *, wenn ein anderer Thread auf das Servlet -Objekt zugreift, kann der nachfolgende Thread nur in der Zeile warten. try {thread.sleep (1000*4); } catch (interruptedException e) {e.printstacktrace (); } response.getWriter (). Schreiben (i+""); }} public void dopost (httpServletRequest -Anforderung, httpServletResponse -Antwort) löst ServletException aus, IOException {dodget (request, response); }}Dieser Ansatz besteht nun darin, dem Servlet -Objekt eine Sperre hinzuzufügen, um sicherzustellen, dass nur ein Thread jederzeit auf die Ressourcen im Servlet -Objekt zugreift. Daher gibt es keine Fadensicherheitsprobleme, wie in der folgenden Abbildung gezeigt:
Obwohl dieser Ansatz die Sicherheitsprobleme von Threads löst, dürfen das Schreiben von Servlets auf diese Weise keine Sicherheitsprobleme mit Thread behandeln. Wenn 9999 Personen gleichzeitig auf das Servlet zugreifen, müssen diese 9999 Personen nacheinander anstellen, um nacheinander zugreifen zu können.
Als Reaktion auf das Problem der Fadensicherheit von Servlets bietet Sun eine Lösung: Lassen Sie das Servlet eine SingleTheadModel -Schnittstelle implementieren. Wenn ein Servlet die SingleTheadModel-Schnittstelle implementiert, ruft die Servlet-Engine seine Servicemethode im Einzel-Thread-Modus auf.
Wenn Sie sich die Sevlet -API ansehen, können Sie feststellen, dass die SingletheadModel -Schnittstelle keine Methoden oder Konstanten definiert. In Java wird eine Schnittstelle, die keine Methoden oder Konstanten definiert, als Tag -Schnittstelle bezeichnet. Eine der typischsten Tag -Schnittstellen, die Sie häufig sehen, ist "serialisierbar". Diese Schnittstelle definiert auch keine Methoden oder Konstanten. Wie nutzen die Tag -Schnittstellen in Java? Die Hauptfunktion besteht darin, ein Objekt zu markieren und dem JVM zu sagen, was dieses Objekt tun kann. Beispielsweise kann das Objekt der Klasse, das die "serialisierbare" Schnittstelle implementiert, serialisiert werden, und es gibt auch eine "klonbare" Schnittstelle, die auch eine Tag -Schnittstelle ist. Standardmäßig dürfen Objekte in Java nicht kloniert werden, genau wie Menschen im wirklichen Leben ist das Klonen nicht erlaubt, aber solange die "klonbare" Schnittstelle implementiert ist, kann das Objekt kloniert werden.
Lassen Sie das Servlet die SingleTheadModel -Schnittstelle implementieren. Fügen Sie einfach die Erklärung hinzu, um die SingleTheadModel -Schnittstelle zur Definition der Servlet -Klasse zu implementieren.
Für Servlets, die die SingleTheadModel-Schnittstelle implementieren, unterstützt die Servlet-Engine immer noch einen gleichzeitigen Zugriff auf den Servlet. Die Methode besteht darin, mehrere Servlet -Instanzobjekte zu generieren, und jeder gleichzeitige Thread ruft ein unabhängiges Servlet -Instanzobjekt separat auf.
Durch die Implementierung der Interface der SingleTheadModel kann das Problem der Thread-Sicherheit von Servlets nicht wirklich lösen, da die Servlet-Engine mehrere Servlet-Instanzobjekte erstellt, und das Problem mit Multi-Thread-Sicherheit wirklich zu dem Problem zu lösen, dass ein Servlet-Instanzobjekt gleichzeitig von mehreren Threads aufgerufen wird. In der Servlet API 2.4 wurde Singletheadmodel als veraltet (veraltet) gekennzeichnet.
Das Obige dreht sich alles um diesen Artikel, ich hoffe, es wird für das Lernen aller hilfreich sein.