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 データベースに接続する方法の詳細な説明

推薦する

JavaScript の基礎: 即時実行関数

目次関数フォーマットを即時実行関数を即座に実行する他の方法 – 式即時実行される関数はパラメータを取...

Windows で mysql 8.0.12 をインストールするための詳細なチュートリアル

この記事では、MySQL 8.0.12のインストール方法に関する詳細なチュートリアルを参考までに紹介...

MySQL 5.7.18 winx64 のインストールと設定方法のグラフィックチュートリアル

圧縮パッケージのインストールは、mysql-5.7 以降、大幅に変更されました。この記事では、mys...

MySQLデータベースの基本構文と操作

MySQLデータベースの基本構文DDL操作データベース作成構文: create database デ...

Windows Server 2016 標準キー アクティベーション キー シリアル番号

Windows Server 2016 アクティベーション キーを皆さんと共有したいと思います。wi...

MySQLがファントムリードを解決する方法の詳細な説明

1. ファントムリーディングとは何ですか?トランザクションにおいて、複数のクエリの後に結果セットの数...

WeChatアプレットは写真アップロード機能を実現

この記事の例では、WeChatアプレットで写真をアップロードするための具体的なコードを参考までに共有...

el-select のスタイルを変更する方法の詳細な説明: popper-append-to-body と popper-class

elementUI が提供する el-select コンポーネントのスタイルを変更する方法この問題...

Linuxオペレーティングシステムは、タスクマネージャーの視覚化機能を実装するためにPythonを使用しています。

1. Pythonのインストール1. フォルダーを作成します。 mkdir python フォルダ...

Linux のスケジュールタスク Crontab コマンドの使用に関する詳細な説明と概要

crontab コマンドは、Unix および Linux で定期的な実行命令を設定するために使用され...

MySQL 検査スクリプト (必読)

以下のように表示されます。 #!/usr/bin/env python3.5 psutilをインポー...

MySQL 学習データベースバックアップの詳細な説明

目次1.DB、DBMS、SQL 2. データベースの特徴3. SQL分類4. MySQLを起動および...

CentOS 7 で NFS ファイル共有ストレージ サービスを構築するための完全な手順

序文NFS (Network File System) は、ネットワーク ファイル システムを意味し...