Tomcat でのサーブレットの作成と実装に関する深い理解

Tomcat でのサーブレットの作成と実装に関する深い理解

1. サーブレットとは何か

1.1. 正式な言葉で説明する:

サーブレットは、動的な Web リソースを開発するために Oracle が提供するテクノロジであり、 JavaEEシステムのコア仕様です。
簡単に言うと、開発者が作成したクラスは、JavaEE のコア仕様を直接的または間接的に実装する必要があります。つまり、Servlet インターフェースを実装する必要があります。このクラスによって生成されたオブジェクトはブラウザからアクセスできるため、Servlet と呼ばれます。JavaEEでは、Servlet 実装クラスによって生成されたオブジェクトのみがブラウザからアクセス可能、つまり Servlet であると規定されています。(つまり、このクラスは Servlet インターフェースを直接的または間接的に実装する必要があります)

2. サーブレットの作成を開始する

2.1. これまでの紹介で、ブラウザからアクセスできるオブジェクトを作成するクラスの種類がわかりました。まずは、コードを直接見てみましょう。

パッケージ com.briup.web;
java.io.IOException をインポートします。
javax.servlet.Servlet をインポートします。
javax.servlet.ServletConfig をインポートします。
javax.servlet.ServletException をインポートします。
javax.servlet.ServletRequest をインポートします。
javax.servlet.ServletResponse をインポートします。

パブリッククラスFirstWayはServletを実装します{
	パブリックFirstWay() {
		System.out.println("オブジェクトが作成されました");
	}
	@オーバーライド
	パブリック void init(ServletConfig config) は ServletException をスローします {
		// TODO 自動生成されたメソッドスタブ
		System.out.println("私はinitです: 呼び出されました");
	}
	@オーバーライド
	パブリック ServletConfig getServletConfig() {
		// TODO 自動生成されたメソッドスタブ
		null を返します。
	}
	@オーバーライド
	パブリック void service(ServletRequest req, ServletResponse res) は ServletException、IOException をスローします {
		// TODO 自動生成されたメソッドスタブ
		System.out.println("私はサービスです、呼ばれました");	
	}
	@オーバーライド
	パブリック文字列 getServletInfo() {
		// TODO 自動生成されたメソッドスタブ
		null を返します。
	}
	@オーバーライド
	パブリックvoidの破棄(){
		// TODO 自動生成されたメソッドスタブ
		System.out.println("私は破壊されました: 私は呼ばれました");
	}

}

サーブレットを満たすクラスが作成されました。次の質問は

誰がサーブレットオブジェクトを作成しますか?

そこに実装されているどのインターフェース メソッドが呼び出され、いつ呼び出され、何回呼び出されるのでしょうか。
最初の質問は、サーブレット クラスであるため、開発者が手動でオブジェクトを作成するのは明らかに不合理であるため、このオブジェクトの作成は Tomcat に引き渡されるということです。開発者は、Tomcat にオブジェクトを作成するように指示するだけで、いつでも作成できます。
どうやって見分ける?

1. 方法 1: webxml を構成する。 (あまりお勧めしません)

動的Webプロジェクト全体において、web.xmlは最初に読み込まれる構成ファイルなので、web.xmlで構成します。

<?xml バージョン="1.0" エンコーディング="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" バージョン="3.1">
 <display-name>firstWay</display-name>
 <サーブレット>
 		<サーブレット名>FirstWay</サーブレット名>
 		<サーブレットクラス>com.briup.web.FirstWay</サーブレットクラス>
 		<!-- <load-on-startup>1</load-on-startup> -->
 </サーブレット>
 <サーブレットマッピング>
 	<サーブレット名>FirstWay</サーブレット名>
 	<url-pattern>/FirstWay</url-pattern>
 </サーブレットマッピング>
</ウェブアプリ>

説明する:
1. servlet-name: サーブレットの名前。以下のマッピングで設定した名前と一致する必要があります。
2. serlvet-class: serlvetの完全修飾名
3. load-on-startup: Tomcat の起動時にサーブレット オブジェクトを作成するかどうかを指定します。0 より大きい整数を渡します (デフォルトでは、ブラウザーが初めて要求したときにサーブレット オブジェクトが作成されます)
4. サーブレットマッピング: 名前の通り、ブラウザアクセスマッピングを設定します。
5. servlet-name: 上記に対応
6. url-pattern: ブラウザ アクセス マッピング (デフォルトがローカル マシンで、Tomcat のポート番号が 8080 であると仮定すると、ブラウザがこのサーブレットにアクセスするためのパスは次のようになります: localhost:8080/プロジェクト名/FirstWay )
これらの基礎が整ったところで、見てみましょう。

ステップ1: Tomcatを起動する

ここに画像の説明を挿入

tomcatが正常に起動します

ステップ 2:ブラウザからアクセスします (ここでは手動で 3 回アクセスします)

ここに画像の説明を挿入

ブラウザアクセスは正常です

ステップ3:コンソールを観察する

ここに画像の説明を挿入

結果分析を実行すると、次のようになります。

サーバーを初めて起動すると、オブジェクトは作成されません

ブラウザは 3 回リクエストしますが、オブジェクトは 1 回だけ作成され、init() メソッドは 1 回だけ呼び出されます。

オブジェクトにアクセスするたびに、service()メソッドが呼び出されます。

他のメソッドは呼び出されない

呼び出されない理由を説明します: getServletConfig(): ServletConfig オブジェクトを取得します: getServletInfo(): 作成者などのサーブレットの信頼性を取得します: destroy(): このメソッドは、サーブレットが破棄されるときに呼び出されます (例: tomcati は正常に閉じられます。ここではテストしません。テストする場合は、サービスを右クリックして停止をクリックできます)。その後、コンソールを観察して確認してください。

2. 方法2: Tomcatにアノテーションで伝える(前者と比較して推奨)

@WebServlet(値 = "マッピングパス")
パブリックファーストサーブレットはServeltを実装します{
}

このアノテーションは、サーバーの起動時にオブジェクトを作成するかどうかを設定する場合にも使用できます。ここでは説明しません。
注意: (アノテーションを使用して Tomcat にオブジェクトを作成するように指示すると、web.xml でサーブレットにアクセスして設定することはできなくなります)

3. 話題に戻り、サーブレットを作成する2番目の方法

前回の説明を踏まえて、コードを直接分析してみましょう。

パッケージ com.briup.web;

java.io.IOException をインポートします。

javax.servlet.GenericServlet をインポートします。
javax.servlet.ServletException をインポートします。
javax.servlet.ServletRequest をインポートします。
javax.servlet.ServletResponse をインポートします。
javax.servlet.annotation.WebServlet をインポートします。
@WebServlet(値 = "/secondWay")
パブリッククラスSecondWayCreateはGenericServletを拡張します{

	@オーバーライド
	パブリック void service(ServletRequest req, ServletResponse res) は ServletException、IOException をスローします {
		// TODO 自動生成されたメソッドスタブ
		System.out.println("サービスメソッドが呼び出されました");
	}

}

1. 最初の方法よりもシンプルで、GenericServletクラスを実装します

2. GenericServlet のソースコードを見て分析してみましょう。

パブリック抽象クラスGenericServletはServlet、ServletConfigを実装します。

これはドロワー クラスであり、サーブレット インターフェイスの実装クラスであることがわかります。そのため、GenericServlet は間接的にサーブレット インターフェイスを実装します。
最初の方法と比較すると、開発者は一部のインターフェースに不要なメソッドを実装する必要がなく、選択的になり、コードの量を削減できます。しかし、それは上記ほど有用ではなく、単にBのふりをしているだけです

3. 3番目の方法に焦点を当てる(最初の2つと比較して、3番目の方法をお勧めします)

コードに直接

パッケージ com.briup.web;

java.io.IOException をインポートします。

javax.servlet.ServletException をインポートします。
javax.servlet.annotation.WebServlet をインポートします。
javax.servlet.http.HttpServlet をインポートします。
javax.servlet.http.HttpServletRequest をインポートします。
javax.servlet.http.HttpServletResponse をインポートします。
@WebServlet(値 = "/ThreeWayCreate")
パブリッククラスThreeWayCreateはHttpServletを拡張します{
	@オーバーライド
	保護された void doGet(HttpServletRequest req, HttpServletResponse resp) は ServletException、IOException をスローします {
		// TODO 自動生成されたメソッドスタブ
		super.doGet(要求、応答);
	}
	@オーバーライド
	保護された void doPost(HttpServletRequest req, HttpServletResponse resp) は ServletException、IOException をスローします {
		// TODO 自動生成されたメソッドスタブ
		super.doPost(req, resp);
	}
}

上記のコードを見て、サーブレットはサーブレット インターフェイスを直接的または間接的に実装する必要があるのではないのか、ブラウザーはリクエストごとにサービス メソッドを 1 回呼び出す必要があるのではないのか、と疑問に思う人もいるかもしれません。方法はどこにありますか?これは以前の理論と矛盾しませんか?
引き続きソースコードを見てみましょう。ソースコードは真実です。 以下にソースコードの核となる部分をリストします。より深く理解する必要がある友人は、ソースコードに直接アクセスできます。Tomcatはオープンソースです

パッケージ com.briup.web;

java.io.IOException をインポートします。

javax.servlet.ServletException をインポートします。
javax.servlet.annotation.WebServlet をインポートします。
javax.servlet.http.HttpServlet をインポートします。
javax.servlet.http.HttpServletRequest をインポートします。
javax.servlet.http.HttpServletResponse をインポートします。
@WebServlet(値 = "/ThreeWayCreate")
パブリッククラスThreeWayCreateはHttpServletを拡張します{
	@オーバーライド
	保護された void doGet(HttpServletRequest req, HttpServletResponse resp) は ServletException、IOException をスローします {
		// TODO 自動生成されたメソッドスタブ
		super.doGet(要求、応答);
	}
	@オーバーライド
	保護された void doPost(HttpServletRequest req, HttpServletResponse resp) は ServletException、IOException をスローします {
		// TODO 自動生成されたメソッドスタブ
		super.doPost(req, resp);
	}
}

分析:

最初のステップの分析

ここに画像の説明を挿入

この抽象クラスは抽象クラス GennericeServlet を継承していることがわかります。つまり、レイヤーごとにプッシュダウンされ、Servle インターフェイスを実装します。次に、この抽出クラスも serice メソッドを継承する必要があります。

第二段階の分析

ここに画像の説明を挿入

これはサーブレットインターフェースを継承したサービスメソッドです。このメソッドはブラウザがリクエストするたびに呼び出されます。図に示すように、このメソッドは HttpServlet によって実装されています。実装クラスからは、リクエストオブジェクト req とレスポンスオブジェクト res が HttpServletRequest と HttpServletResponse に強制的に変換され (下方変換)、その後、強制的に変換されたオブジェクトが HttpServlet のオーバーロードされたサービスメソッドに渡されて呼び出されると結論付けることができます。3 番目のステップは、オーバーロードされたサービス (HttpRequest req、HttpResponse res) を分析することです。

ステップ3 分析

保護された void サービス (HttpServletRequest 要求、HttpServletResponse 応答)
    ServletException、IOException をスローします {

    文字列メソッド = req.getMethod();

    メソッドがMETHOD_GETと等しい場合
      lastModified は、req に格納されます。
      (最終変更 == -1)の場合{
        // サーブレットは理由もなく if-modified-since をサポートしていません
        // さらに高価なロジックを実行する
        要求、応答を取得します。
      } それ以外 {
        長い ifModifiedSince;
        試す {
          変更された日付が返されるかどうか。
        } キャッチ (IllegalArgumentException iae) {
          // 日付ヘッダーが無効です - 何も設定されていないものとして続行します
          変更された場合 = -1;
        }
        if (ifModifiedSince < (lastModified / 1000 * 1000)) {
          // サーブレットの変更時刻が遅い場合は、doGet() を呼び出します
          // 適切な比較のために最も近い秒に切り捨てます
          // ifModifiedSinceが-1の場合は常に
          おそらく、LastModified を設定します(resp、lastModified);
          要求、応答を取得します。
        } それ以外 {
          resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        }
      }

    } そうでない場合 (method.equals(METHOD_HEAD)) {
      lastModified は、req に格納されます。
      おそらく、LastModified を設定します(resp、lastModified);
      要求されたレスポンスを返す。

    } それ以外の場合 (method.equals(METHOD_POST)) {
      要求をポストします。

    } それ以外の場合 (method.equals(METHOD_PUT)) {
      要求、応答を返す。

    } そうでない場合 (method.equals(METHOD_DELETE)) {
      要求、応答を削除します。

    } そうでない場合 (method.equals(METHOD_OPTIONS)) {
      オプションを(req,resp)実行します。

    } そうでない場合 (method.equals(METHOD_TRACE)) {
      トレースを実行します(req,resp);

    } それ以外 {
      //
      // これは、どのサーブレットもサポートしていないことを意味することに注意してください
      // メソッドがこのサーバーのどこからでも要求されました。
      //

      文字列 errMsg = lStrings.getString("http.method_not_implemented");
      オブジェクト[] errArgs = 新しいオブジェクト[1];
      errArgs[0] = メソッド;
      errMsg = MessageFormat.format(errMsg, errArgs);

      resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED、errMsg);
    }
  }

リクエストメソッドは渡されたHttpRequestオブジェクトによって決定され、呼び出されるメソッドはリクエストメソッドによって決定されます(リクエストメソッドがpostの場合、doPost(HttpRequest req,HttpRestpone Res)メソッドが呼び出されます

4 番目のステップの分析: 上記の分析に基づいて、次のように結論付けることができます。Tomcat はオブジェクトを作成し、ブラウザーが要求すると、サーブレットの Service(ServeltRequest req, ServletRespone res) メソッドを呼び出します。次に、このメソッドは HttpServlet 内のオーバーロードされた Servlet(HttpServletReqeust req, HttpServletRespone res) メソッドを呼び出します。次に、このメソッドは要求メソッドに従って doPost() メソッドまたは doGet() メソッドを選択的に呼び出します (もちろん、ここに記載されていない他の多くの方法があります)。したがって、3 番目の方法の本質は、ブラウザーが要求を開始すると、サーブレット インターフェイス内の Service(ServeltRequest req, ServletRespone res) メソッドが呼び出され、次に実装クラスのロジックを通じて doPost() メソッドと他のメソッドが間接的に呼び出されることにあります。

アドバンテージ:

1. 対応するリクエストはリクエストメソッドを通じて処理できるため、ロジックが明確になります。

2. コードの量を減らしてプログラムを簡潔にする

3. リクエストやレスポンスをより操作しやすくする

4…

IV. 要約:

注:ブラウザはサーブレットのサービス メソッドを呼び出すリクエストを開始する必要があります。

Tomcat でのサーブレット作成の実装に関する詳細な理解に関するこの記事はこれで終わりです。Tomcat サーブレット作成に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • アイデアのMavenWebプロジェクトのソリューションではサーブレットを作成できない
  • アイデアファイルを右クリックしても「新規サーブレットの作成」が表示されない問題の解決方法の詳細説明
  • IDEA で Maven プロジェクト サーブレットを作成する方法の詳細なチュートリアル
  • IDEAはサーブレットを作成し、web.xmlの実装を構成します。
  • IntelliJ IDEA2020.2.2 はサーブレット メソッドと 404 問題を作成します
  • myeclipse が servlet_PowerNode を作成する Java アカデミー
  • エディターなしでサーブレット (Tomcat + Java) プロジェクトを作成する方法は?

<<:  JavaScript にはすでに Object があるのに、なぜ Map が必要なのでしょうか?

>>:  IntelliJ IDEA で Java を使用して MySQL データベースに接続する方法の詳細な説明

推薦する

Flexレイアウトを使用してヘッドの固定コンテンツ領域のスクロールを実現する方法

ページ ヘッダーの固定レイアウトは、以前は position:fixed を使用して実装されていまし...

CSS 透明ボーダー背景クリップマジック

この記事では、CSSの透明な境界線の背景クリップの素晴らしい使い方を主に紹介し、みんなと共有し、自分...

画像の色を変更するための純粋なCSS

画像の色を変更するための CSS テクニックは非常にシンプルです。具体的なコードは次のとおりです。ヒ...

CSS3を使用してテキストの垂直配置を実現する方法

最近のプロジェクトでは、テキストを垂直に揃えたいと考え、CSS の writing-mode プロパ...

Vue はアップロードした画像に透かしを追加できるようになりました (アップグレード版)

vueプロジェクトでは、アップロードした画像に透かしを追加して参照できるようにするアップグレード版...

Chromeブラウザの自動パスワード保存プロンプト機能を無効にする方法

注: Web 開発では、フォームに autocomplete="off" を追加...

まだ*を選択しますか?

アプリケーションが牛のように遅い理由は数多くあります。ネットワーク、システム アーキテクチャ、または...

Navicatをサーバー上のdockerデータベースに接続する方法

dokekrでmysqlコンテナを起動するコマンドを使用します: docker run -p 330...

CSS 8 目を引く HOVER 効果のサンプル コード

1. エフェクトHTMLを送信する <div id="送信ボタン">...

Webサービスのリモートデバッグとタイムアウト動作原理の分析

Webサービスのリモートデバッグ.NET では、WEBSERVICE のリモート デバッグ機能はデフ...

Vue における属性とプロパティの具体的な使用法と違い

目次Vue.jsにおける属性とプロパティ値および関連する処理として属性とプロパティの概念属性とプロパ...

MySQLの文字セットと検証ルールの詳細な説明

1いくつかの一般的な文字セットMySQL で最も一般的な文字セットには、ASCII 文字セット、ラテ...

Tomcatの再構成後に起動が遅くなる問題を迅速に解決

Jenkins+Tomcatサーバーの設定中に、Tomcat設定ファイルが変更され、サーバーのTom...

MySQL 5.7.18 MSI インストール グラフィック チュートリアル

この記事では、参考までにMySQL 5.7.18 MSIインストールチュートリアルを紹介します。具体...

WeChatアプレットのスクロールビューは、プルアップ時にデータの読み込みを重複させるソリューションを実装しています。

WeChat アプレットのスクロール ビューでは、プルアップして読み込むときにバグが多く発生します...