Tomcat が応答データグラムを書き戻すタイミングの詳細な分析

Tomcat が応答データグラムを書き戻すタイミングの詳細な分析

疑問が生じる

この質問は、ファイルのダウンロードを記述しているときに発生しました。HttpServletResponse を使用して Outputstream を取得し、OutputStream を使用してデータを直接書き込みました。その時、この OutputStream が対応する Socket 接続の OutputStream であるかどうか疑問に思いました。つまり、プログラムがストリームを使用して書き込んでいるときに、データも送信されているということですか?

レスポンスの OutputStream はデータをどこに書き込みますか?

そこで、HttpServletResponse の getOutputStream メソッドを見て、そのコメントが何と言っているかを確認しました。

/**
  * バイナリの書き込みに適した{@link ServletOutputStream}を返します 
  * レスポンス内のデータ。サーブレットコンテナは、
  * バイナリデータ。 
  *
  * <p> ServletOutputStream で flush() を呼び出すと、応答がコミットされます。
  *
  * このメソッドまたは{@link #getWriter}のいずれかが 
  * {@link #reset} の場合を除き、本体を書き込むために呼び出され、両方を書き込むために呼び出されることはありません。
  * が呼び出されました。
  *
  * @return バイナリデータを書き込むための {@link ServletOutputStream} 
  *
  * @exception IllegalStateException、<code>getWriter</code> メソッドの場合
  * この応答で呼び出されました
  *
  * @exception IOException 入力または出力例外が発生した場合
  *
  * @see #getWriter
  * @see #リセット
  */
 public ServletOutputStream getOutputStream() は IOException をスローします。

上記のコメントでは、OutputStream はレスポンス本文のコンテンツを書き込むために使用されると述べられており、また flush() メソッドについても言及されています。これは、バッファリングが必要であることを意味するため、データを書き込むためにソケット上で直接操作すべきではないことを意味します。一時的な保存用のバイト配列を用意し、それを均一にフラッシュする必要があると思います。しかし、まだ確信が持てなかったので、Tomcat のソース コードを調べてみました。

ServletOutputStream の実装クラス、CoyoteOuputStream を見つけます。 OutputStream の抽象メソッド write を実装し、データを OutputBuffer 型のフィールドに書き込んで保存します。この OutputBuffer オブジェクトは coyote/Response から取得されます。実際、この OutputBuffer は単なるインターフェースであり、具体的な実装は StreamOutputBuffer です。データ サイズに制限はありません。リンク リストに格納され、各リンク リスト ノードには 8196 バイトが格納されます。

応答データグラムはいつクライアントに返されますか?

実際には、OutputBuffer の flush メソッドを呼び出すときにチェックします。レイヤーごとに調べて、最終的に connector/Response の finishResponse() メソッドを見つけました。このメソッドは、最初に応答行と応答ヘッダーを送信します。次に、応答本文を送信します。 Tomcat のソース コードをあまり読んでいませんが、HTTP リクエストの処理を説明する優れたシーケンス図がここにあります。以下では、サーブレットの service メソッド呼び出しと Response の FinishResponse メソッド呼び出しに焦点を当てます。サービス メソッドが返された後、finishResponse 操作が実行されることが分かります。つまり、サーブレット プログラムが要求を処理すると、Tomcat は応答をクライアントに返します。

注:サーブレットプログラムは、基礎となるデータの送受信には関与せず、また制御も行いません。

図の中でサーブレットのサービス メソッドが呼び出される場所はどこですか?

ApplicationFilterChain の internalDoFilter メソッドに含まれます。

サーブレット プログラムの処理要求とはどういう意味ですか?

基本的に、サーブレット プログラムの仕事は、リクエスト情報に基づいてレスポンス情報を入力することです。

サーブレット プログラムと Spring MVC の関係は何ですか?

Spring MVC の基盤となるレイヤーは依然として Serlvet であり、DispatcherServlet と呼ばれるサーブレットを使用してすべてのリクエストを処理し、次にリクエストを対応する @RequestMapping アノテーション付きメソッドに分散して処理します。一般的に言えば、サービス メソッドの呼び出しを完了します。

では、MVC リターン ページと REST データの戻りはどうでしょうか?

ページを返すということは、ページ データをレスポンス ボディに書き込むことを意味します。@ResponseBody アノテーションは、実際には @RequestMapping でアノテーションが付けられたメソッドの戻り値を JSON 文字列に変換し、レスポンス ボディに書き込みます。ここでの応答 Body は、上記の OutputBuffer を参照します。

Tomcat と Servlet プログラムの役割

「Tomcat の仕組み」では、サーブレット コンテナ (Tomcat はサーブレット コンテナです) のタスクは次のように要約できると説明されています。

1. リクエスト オブジェクトを作成し、関連情報 (パラメーター、ヘッダー、Cookie、URI など) を入力します。

2. レスポンスオブジェクトを作成する

3. このリクエストに関連付けられたサーブレットのサービス メソッドを呼び出し、リクエストとレスポンスを渡します。

ここで、私自身の言葉で説明します。ブラウザがサーバーにリクエストを送信すると、サーバーはリクエスト データグラムの内容を解析し、リクエスト情報で満たされたリクエスト オブジェクトを作成し、「空の」レスポンス オブジェクトを作成します。次に、これらの 2 つのオブジェクトがサーブレットのサービス メソッドに渡され、レスポンス オブジェクトへの入力が完了し、レスポンス データがクライアントに送信されます。

なぜ Request オブジェクトを渡す必要があるのでしょうか?

Request オブジェクトを渡さない場合、Servlet プログラムは何を入力すればよいかわかりません。つまり、どのようなリソースが必要なのかがわかりません。

Tomcat はリクエストに関連付けられたサーブレットをどのように見つけるのでしょうか?

Tomcat を開発する場合、どのプロジェクトを Tomcat にデプロイするか、またはサーブレット プログラムが何と呼ばれるかを知ることは不可能であることはわかっています。したがって、サービス メソッドを呼び出すためのハード コーディングは不可能であり、リフレクション メカニズムが使用されます。

Spring Boot フレームワークを使用する前にプロジェクトをどのようにデプロイしたか考えてみましょう。プロジェクトをパッケージ化して、Tomcat の webapp ディレクトリに配置するだけです。実行後、プロジェクトに対応する URL は localhost:8080/projectName/xxx になりますか?また、プロジェクトでは、アノテーション スタイルか web.xml スタイルかを問わず、サーブレット プログラムのマッピングが構成されます。 URL を Servlet クラス ファイルにマップします。

リクエストが来ると、まずprojectNameに従って対応するプロジェクトを見つけ、その後のURLに従って対応するServletクラス名にマッピングします。その後、Tomcat はリフレクション メカニズムを使用して Servlet クラス ファイルをロードし、インスタンスを取得して、サービス メソッドを呼び出します。

coyote/Response、connector/Response、connector/ResponseFacade の関係は何ですか?

coyote/Response は主に基礎となるデータ転送にリンクされており、connector/Response は HttpServletResponse インターフェースを実装する coyote/Response の上位レベルのラッパーです。ただし、サービス メソッドに直接渡されると、ユーザーが HttpServletResponse を connector/Response に直接変換し、いくつかの基礎となるメソッドを直接呼び出す恐れがあります。したがって、HttpServletResponse インターフェースで定義されているものを除く、コネクタ/レスポンスのすべてのパブリック メソッドをブロックする「ファサード モード」が導入されています。つまり、サービスに渡されるのは実際にはコネクタ/ResponseFacade オブジェクトであり、強制的に実際の型に変換しても、HttpServletResponse インターフェースで定義されたメソッドしか見えません。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • 動的データと静的リソースのリクエストを分離するための Nginx + Tomcat の詳細な説明
  • Linux 上の Tomcat で MySQL にデータを挿入するときに中国語の文字化けが発生する問題を解決する
  • Tomcat データ ソースの原理、構成、使用方法の紹介
  • Android は Apache Tomcat サーバー (MySql データベース) とのデータ相互作用を実装します。
  • Tomcat 7-dbcp 構成データベース接続プールの詳細な説明
  • Post メソッドを使用して Tomcat サーバーにデータを送信する方法
  • Get メソッドを使用して Tomcat サーバーにデータを送信する方法
  • 接続プールを使用してTomcatサーバーのOracleデータベースに接続する
  • Tomcatc3p0 で jnid データ ソースを構成する 2 つの実装方法の分析

<<:  1つのSQL文でMySQLの重複排除が完了し、1つが保持されます。

>>:  Vue3の状態管理の使用方法の詳細な説明

推薦する

Nginx 仮想ホストを構成する 3 つの方法 (ポートベース) の詳細な説明

Nginx は、IP ベースの仮想ホスト構成、ポート ベースの仮想ホスト構成、ドメイン名ベースの仮想...

Vue+echart で 2 列チャートを実現

この記事では、vue+echart を使って二重列チャートを実現するための具体的なコードを参考までに...

MySQL 継続的集計の原理と使用法の分析

この記事では、例を使用して、MySQL の継続的な集計の原理と使用方法を説明します。ご参考までに、詳...

要素フォーム検証で検証プロンプトをクリアする方法

目次問題のシナリオ:解決: 1. フィールドを個別にチェックする2. フォームフィールドの下のフィー...

ウェブページの読み込み速度を上げる6つのヒント

第二に、キーワードのランキングは、Webページの表示速度にも関係しています(参照:キーワードランキン...

MySQL の結合インデックスと左端一致原則の詳細な説明

序文これまでインターネットでMySQLジョイントインデックスの最左接頭辞マッチングに関する記事をたく...

Linux でファイアウォールがオフになっているかどうかを確認する方法

1. サービス方法ファイアウォールのステータスを確認します。 [root@centos6 ~]# サ...

phpstudy から Linux への MySQL の移行に関するチュートリアル

プロジェクトの目的元のWindows環境でphpstudyを使用して構築されたMySQL 5.5.5...

XHTML 1.0 リファレンス

機能別に並べ替えNN: このタグをサポートする Netscape の以前のバージョンを示しますIE:...

Vue+ElementUI で超大規模なフォーム例を処理する方法

最近、社内の業務調整により、以前の超長文のロジックが大幅に変更されたため、リファクタリングする予定で...

Vue は Axios リクエスト フロントエンドのクロスドメイン問題をどのように解決するのか

目次序文1. クロスドメインの問題はなぜ発生するのでしょうか? 2. 解決策クロスオリジンリソース共...

MySQL 外部キー制約の例の説明

MySQL の外部キー制約は、2 つのテーブル間のリンクを確立するために使用されます。 1 つのテー...

Centos7でのMySQLインストールチュートリアル

MySQLインストールチュートリアル、参考までに具体的な内容は次のとおりです。 1. ダウンロードY...

ブラウザのURLの前に小さなアイコンを表示する方法

多くのウェブサイトを閲覧すると、ブラウザのアドレスバーの前に小さなアイコンがあり、ブラウザのタブの位...

CSSフローティングとフローティング解除について

フロートの定義要素を通常のドキュメント フローから外し、要素を左また​​は右に近づけます。親要素の端...