1。サーブレットの紹介
サーブレットは、動的なWebリソースを開発するためにSun Companyが提供するテクノロジーです。
Sunは、APIにサーブレットインターフェイスを提供します。ユーザーが動的なWebリソースを送信したい場合(つまり、データをブラウザに出力するJavaプログラムを開発する)、次の2つの手順を完了する必要があります。
1. Javaクラスを作成して、サーブレットインターフェイスを実装します。
2。開発されたJavaクラスをWebサーバーに展開します。
従来の名前の習慣によると、通常、サーブレットインターフェイスサーブレットを実装するJavaプログラムを呼び出します。
2。サーブレットの動作プロセス
サーブレットプログラムは、Webサーバーによって呼び出されます。 Webサーバーがクライアントのサーブレットアクセスリクエストを受信した後:
web Webサーバーは、最初にロードされたかどうかを確認し、サーブレットのインスタンスオブジェクトを作成しました。その場合、ステップ4を直接実行します。それ以外の場合は、ステップ2を実行します。
servletのインスタンスオブジェクトをロードして作成します。
servletインスタンスオブジェクトのinit()メソッドをコールします。
httpリクエストメッセージとHTTPRETRESPONSEオブジェクトをカプセル化するためのHTTPSERVLETREQUESTオブジェクトを作成し、HTTP応答メッセージを表すHTTPSERVLETRESPONSEオブジェクトを作成し、サーブレットのサービス()メソッドを呼び出し、リクエストと応答オブジェクトをパラメーターとして渡します。
webアプリケーションが停止または再起動する前に、サーブレットエンジンはサーブレットをアンインストールし、アンインストールする前にサーブレットのDestroy()メソッドを呼び出します。
3.サーブレットコール図
4.日食にサーブレットを開発します
Eclipseで新しいWebプロジェクトを作成すると、Eclipseは以下の図に示すディレクトリ構造を自動的に作成します。
4.1。サーブレットインターフェイス実装クラス
サーブレットインターフェイスSun Companyは、2つのデフォルトの実装クラスを定義します。
httpservletは、HTTPリクエストを処理できるサーブレットを指します。いくつかのHTTPプロトコル処理方法を元のサーブレットインターフェイスに追加します。これは、サーブレットインターフェイスよりも強力です。したがって、サーブレットを書くとき、開発者は通常、このクラスを継承し、サーブレットインターフェイスの直接実装を避ける必要があります。
Httpservletがサーブレットインターフェイスを実装すると、サービス方法を上書きします。メソッド本体のコードは、ユーザーの要求方法を自動的に決定します。 GETリクエストの場合、httpservletのdogetメソッドが呼び出されます。 POSTリクエストの場合、DOPOSTメソッドが呼び出されます。したがって、サーブレットを書くとき、開発者は通常、サービス方法を上書きする代わりに、dogetまたはdopostメソッドを上書きする必要があります。
4.2。 Eclipseを通してサーブレットを作成して書き込みます
下の図に示すように、gacl.servlet.studyパッケージ、右クリック→new→サーブレットを選択します。
このようにして、Eclipseを使用して、ServletDemo1という名前のサーブレットを作成するのに役立ちます。作成されたServletDemo01には、次のコードがあります。
gacl.servlet.study; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletexception; Import javax.servlet.http.httpservlet; Import javax.servlet.http.httpservletrequest; import; javax.servlet.http.httpservletresponse; public class servletdemo1は、httpservlet { /***サーブレットのdogetメソッドを拡張します。 <br> * *このメソッドは、フォームにタグ値メソッドが得られる場合に呼び出されます。 * *クライアントがサーバーに送信するリクエストの要求printwriter out = response.getWriter(); out.println( "<!doctype html public/" - // w3c // dtd html 4.01 transitional // en/">"); out.println( "<head> <title> aサーブレット</title> </head>"); out.println( "<body>"); out.print( "this is"); out.print(this.getClass()); out.println( "、get method"); out.println( "</body>"); out.println( "</html>"); out.flush(); out.close(); } /***サーブレットのドポスト法。 <br> * *このメソッドは、フォームにタグ値メソッドが投稿に等しい場合に呼び出されます。 * * @paramリクエストクライアントがサーバーに送信するリクエスト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( "<head> <title> aサーブレット</title> </head>"); out.println( "<body>"); out.println( "<body>"); out.println( "this is"); out.print(this.getClass()); out.println( "、postメソッドを使用して"); out.println( "</body>"); out.println( "</html>"); out.flush(); out.close(); }}これらのコードはEclipseによって自動的に生成され、web.xmlファイル、<servlet> </servlet>および<servlet-mapping> </servlet-mapping>に2つのタグがあります。これらの2つのペアのタグは、下の図に示すように、servletdemo1で構成されています。
次の図に示すように、ブラウザを介してservletdemo1サーブレットにアクセスできます。
5.サーブレット開発の詳細に注意してください
5.1。サーブレットアクセスURLマッピング構成
クライアントはURLアドレスを介してWebサーバーのリソースにアクセスするため、サーブレットプログラムに外部からアクセスしたい場合は、サーブレットプログラムをURLアドレスにマッピングする必要があります。この作業は、<Servlet>要素と<サーブレットマッピング>要素を使用してWeb.xmlファイルで行われます。
<サーブレット>要素は、サーブレットの登録に使用されます。 2つの主要な子要素が含まれています。<Servlet-Name>と<Servlet-Class>。これは、サーブレットの登録名とサーブレットの完全なクラス名を設定するために使用されます。
<サーブレットマッピング>要素は、登録されたサーブレットへの外部アクセスパスをマッピングするために使用されます。これには、サーブレットの登録名とサーブレットの外部アクセスパスを指定するために使用される2つの子要素の2つの子要素が含まれています。例えば:
<Servlet> <Servlet-Name> Servletdemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet mapping> <servlet-name> servletdemo1 </servlet-name> <url-mo> </servletememo1同じサーブレットを複数のURLにマッピングできます。つまり、複数の<サーブレットマッピング>要素の<Servlet-Name>子要素の設定値は、同じサーブレットの登録名になります。例:<Servlet> <Servlet-Name> ServletDemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet> <servlet-mapping <url-pattern>/servlet/servletdemo1 </url-pattern> </servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern> /1.htm </url-pattern> </servlet-mapping> <servlet-name> <servlet-name> </servlet-name> <url-pattern> /2.jsp </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-pattern> /php </url-pattern> </servlet-mapping> <サーブレットマッピング> <サーブレットマッピング> <サーブレットマッピング> <サーブレットマッピング> <url-pattern> /4.aspx </url-pattern> </servlet-mapping>
上記の構成を通じて、ServletDemo1という名前のサーブレットにアクセスする場合、次のアドレスを使用してアクセスできます。
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は複数のURLにマッピングされます。
5.2。サーブレットアクセスURLにワイルドカードマッピングを使用します
*ワイルドカード文字は、サーブレットマップのURLでも使用できますが、2つの固定形式しかありません。1つは「*。拡張機能」で、もう1つはフォワードスラッシュ(/)で始まり、「/*」で終わることです。例えば:
<Servlet> <Servlet-Name> servletdemo1 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo1 </servlet-class> </servlet-mapping> <servlet-name> servletdemo1 </servlet-name> <url-perthn>/*</url-pittern>
*任意の文字に一致する可能性があるため、下の図に示すように、任意のURLを使用してサーブレットデモ1サーブレットにアクセスできます。
以下のいくつかのマッピング関係については:
servlet1マップto /abc /*
servlet2マップに /*
Servlet3は /ABCにマップします
servlet4は *.doにマップします
質問:
リクエストURLが「/abc/a.html」、「/abc/*」、および「/*」の場合、サーブレットエンジンにサーブレットが応答する場合、Servlet1を呼び出します。
リクエストURLが「/ABC」の場合、「/ABC/*」と「/ABC」の両方の一致の両方で、サーブレットエンジンに応答するサーブレットはサーブレット3を呼び出します。
リクエストURLが「/abc/a.do」の場合、「/abc/*」と「*.do」の両方の一致の両方で、サーブレットエンジンに応答するサーブレットがサーブレット1を呼び出します。
リクエストURLが「/*」と「*」と「*.Do」の両方の一致の場合、サーブレットエンジンに応答するサーブレットの両方がServlet2を呼び出します。
リクエストURLが「/xxx/yyy/a.do」の場合、「/*」と「*.do」の両方の一致の両方で、サーブレットエンジンに応答するサーブレットの両方がServlet2を呼び出します。
マッチングの原則は、「見える人がもっと見える人を見つける人」です。
5.3。サーブレットと通常のJavaクラスの違い
サーブレットは、他のJavaプログラム(サーブレットエンジン)が呼び出すためのJavaクラスです。独立して実行できず、その動作は完全に制御され、サーブレットエンジンによってスケジュールされます。
クライアントからの複数のサーブレット要求の場合、通常、サーバーはサーブレットインスタンスオブジェクトのみを作成します。つまり、サーブレットインスタンスオブジェクトが作成されると、メモリに存在し、他のその後のリクエストを提供します。 Webコンテナが出るまで、サーブレットインスタンスオブジェクトは破壊されません。
サーブレットの生涯の間、サーブレットのinitメソッドは1回だけ呼ばれます。サーブレットへの各アクセス要求により、サーブレットエンジンはサーブレットサービスメソッドを1回呼び出します。各アクセス要求に対して、サーブレットエンジンは新しいhttpservletrequestリクエストオブジェクトと新しいhttpservletResponse応答オブジェクトを作成し、これら2つのオブジェクトを呼び出すサーブレットのサービス()メソッドにパラメーターとして渡します。サービス方法は、要求方法に従ってDOXXXメソッドを呼び出します。
<Load-on-startup>要素が<servlet>要素で構成されている場合、Webアプリケーションが起動すると、サーブレットインスタンスオブジェクトをロードして作成し、サーブレットインスタンスオブジェクトのinit()メソッドを呼び出します。
例えば:
<Servlet> <Servlet-Name> Invoker </servlet-name> <servlet-class> org.catalina.servlets.invokerservlet </servlet-class> <load-on-startup> 1 </load-on-startup> </servet>
目的:Webアプリケーション用のInitServletを作成します。このサーブレットは、スタートアップにロードするように構成されており、Webアプリケーション全体に必要なデータベーステーブルとデータを作成します。
5.4。デフォルトサーブレット
サーブレットのマッピングパスがフォワードスラッシュ(/)のみである場合、このサーブレットは現在のWebアプリケーションのデフォルトサーブレットになります。
web.xmlファイルにはない<servlet-mapping>要素の任意のURLは、アクセスリクエストが処理のためにデフォルトのサーブレットに引き渡されます。つまり、デフォルトのサーブレットは、他のサーブレットによって処理されないアクセス要求を処理するために使用されます。例えば:
<サーブレット> servlet-name> servletdemo2 </servlet-name> <servlet-class> gacl.servlet.study.servletdemo2 </servlet-class> <load-on-startup> 1 </load-on-startup> </servet> <! - servletemo2を設定します - デフォルトサーブレット - > <Servlet-Name> ServletDemo2 </servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
存在しないサーブレットにアクセスするとき、下の図に示すように、構成されたデフォルトサーブレットは処理に使用されます。
<tomcatインストールディレクトリ> /conf/web.xmlファイルでは、org.apache.catalina.servlets.defaultServletという名前のサーブレットが登録されており、このサーブレットはデフォルトのサーブレットとして設定されています。
<Servlet> <Servlet-Name>デフォルト</servlet-name> <servlet-class> org.apache.catalina.servlets.defaultservlet </servet-class> <init-param> <param-name> debug </param-name> <param-value> 0 </param-value> </init-param> <init-param> <init-param> <init-param> <param> <param-value> false </param-value> </init-param> <load-on-startup> 1 </load-on-startup> </servlet> <! - デフォルトのサーブレットのマッピング - > <サーブレットマッピング> <サーブレット - >
Tomcatサーバーで静的HTMLファイルと画像にアクセスすると、実際にこのデフォルトサーブレットにアクセスしています。
5.5。サーブレットスレッドの安全性の問題
複数のクライアントが同じサーブレットに同時にアクセスすると、Webサーバーは各クライアントのアクセス要求のスレッドを作成し、このスレッドのサーブレットのサービスメソッドを呼び出します。したがって、サービス方法で同じリソースにアクセスされる場合、スレッドの安全性の問題を引き起こす可能性があります。たとえば、次のコード:
スレッドの安全性の問題がないコード:
gacl.servlet.study; import java.io.ioexception; Import javax.servlet.servletexception; Import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; Import javax.http.httpretlet; javax.servlet.http.httpservletResponse; public class servletdemo3はhttpservlet {public void doget(httpservletrequestリクエスト、httpservletresponse応答)Servletexception、ioexception、ioexception { /***この方法で複数のスレッドにアクセスするとき、 i変数は複数のスレッドで同時にアクセスされますが、私はdogetメソッドのローカル変数であるため、スレッドの安全性の問題はありません。 *複数のスレッドがDogetメソッドに同時にアクセスすると、各スレッドには独自のi変数があり、各スレッドは独自のI変数を動作させるため、マルチスレッドが特定のメソッドに同時にアクセスする場合、いくつかのリソース(変数、コレクションなど)がメソッド内に定義されている場合 *、すべてのスレッドにはこれらのものがあります。 i ++; Response.getWriter()。write(i); } public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}スレッドの安全性の問題を伴うコード:
gacl.servlet.study; import java.io.ioexception; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; intervlet.http.http.httptpretspesspesspesspespessepspersepsperspespesper httpservlet {int i = 1; public void doget(httpservletrequest request、httpservletresponse応答)servletexception、ioexception {i ++; {thread.sleep(1000*4); } catch(arturnedexception e){e.printstacktrace(); } Response.getWriter()。書き込み(i+""); } public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}Iをグローバル変数として定義します。複数のスレッドにアクセス変数が同時にアクセスすると、下の図に示すように、スレッドの安全性の問題があります。同じサーブレットへの同時アクセスをシミュレートすると同時に2つのブラウザをオンにします。通常、最初のブラウザには2が表示され、2番目のブラウザは3を表示する必要がありますが、両方のブラウザは3を表示しますが、これは正常ではありません。
スレッドの安全性の問題は、複数のスレッドが同じリソースを同時に動作させる場合にのみ存在します。したがって、サーブレットを書くとき、特定のリソース(変数、コレクションなど)に同時にアクセスされる場合、スレッドの安全性の問題が発生します。では、この問題を解決する方法は?
次のコードを見てみましょう。
gacl.servlet.study; import java.io.ioexception; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; intervlet.http.http.httptpretspesspesspesspespessepspersepsperspespesper httpservlet {int i = 1; public void doget(httpservletrequest request、httpservletResponse応答)Servletexception、ioException { /***同期が追加された後、iへの同時アクセスの場合、スレッド安全性の問題はありません。 *同期が追加された後、なぜスレッドの安全性の問題がないのですか? *今すぐサーブレットオブジェクトにアクセスするスレッドがある場合、最初にサーブレットオブジェクトのロックを取得します*実行後、ロックをサーブレットオブジェクトに返します。最初にサーブレットオブジェクトのロックを取得するため *したがって、別のスレッドがサーブレットオブジェクトにアクセスすると、ロックが前のスレッドによって削除されたため、後続のスレッドはラインでのみ待機できます */同期(this){// javaではロックがあり、ここではサーブレットオブジェクトi ++を指します。 {thread.sleep(1000*4); } catch(arturnedexception e){e.printstacktrace(); } Response.getWriter()。書き込み(i+""); }} public void dopost(httpservletrequest request、httpservletResponse応答)servletexception、ioexception {doget(request、response); }}このアプローチは、サーブレットオブジェクトにロックを追加し、下の図に示すように、スレッドの安全性の問題はいつでも1つのスレッドのみがサーブレットオブジェクトにアクセスしていることを確認することです。
このアプローチはスレッドの安全性の問題を解決しますが、書くサーブレットはこのように糸の安全性の問題を処理してはなりません。 9999人が同時にサーブレットにアクセスする場合、これらの9999人は順番にアクセスするためにキューアップする必要があります。
サーブレットの糸の安全性の問題に応じて、Sunは解決策を提供します。サーブレットにSinglethreadModelインターフェイスを実装させます。サーブレットがSinglethreadModelインターフェイスを実装する場合、サーブレットエンジンはシングルスレッドモードでそのサービス方法を呼び出します。
Sevlet APIを見ると、SinglethreadModelインターフェイスがメソッドや定数を定義していないことがわかります。 Javaでは、メソッドや定数を定義しないインターフェイスがタグインターフェイスと呼ばれます。よく見られる最も典型的なタグインターフェイスの1つは、「シリアル化可能」です。このインターフェイスは、メソッドや定数も定義しません。 Javaでのタグインターフェイスの使用は何ですか?主な機能は、オブジェクトをマークし、このオブジェクトができることをJVMに伝えることです。たとえば、「シリアル化可能な」インターフェイスを実装するクラスのオブジェクトは、シリアル化できます。また、「クローン可能な」インターフェイスもあります。これもタグインターフェイスです。デフォルトでは、Javaのオブジェクトは、実際の生活の人々と同じように、クローン化は許可されていませんが、「クローン可能」インターフェイスが実装されている限り、オブジェクトをクローン化できます。
サーブレットにSingLethReadModelインターフェイスを実装して、SingLethReadModelインターフェイスをサーブレットクラスの定義に実装するために宣言を追加するだけです。
SinglethreadModelインターフェイスを実装するサーブレットの場合、サーブレットエンジンは、サーブレットへのマルチスレッドの同時アクセスをサポートしています。この方法は、複数のサーブレットインスタンスオブジェクトを生成することであり、各並行スレッドは独立したサーブレットインスタンスオブジェクトを個別に呼び出します。
SinglethreadModelインターフェイスを実装すると、サーブレットエンジンが複数のサーブレットインスタンスオブジェクトを作成するため、サーブレットのスレッド安全性の問題を実際に解決することはできません。マルチスレッド安全性の問題を真に解決することは、サーブレットインスタンスオブジェクトが複数のスレッドで同時に呼び出される問題を指します。実際、サーブレットAPI 2.4では、SinglethreadModelは非推奨(時代遅れ)としてマークされています。
上記はこの記事に関するものです。すべての人の学習に役立つことを願っています。