サーブレットの実行プロセスとファイル構成。

目次

 1. 基本紹介

 2. 実行プロセス

 3.ライフサイクル

 4.サーブレットの5つのメソッド

 5. アーキテクチャ

 6.urlPattern の設定

 7.XML 構成


1. 基本紹介

▶ はじめに

 サーブレットは JavaWeb のコアコンテンツであり、Java が提供する動的な Web リソース開発技術です。サーブレットを利用することで実現でき、ログインユーザーごとに異なるコンテンツを動的にページに表示することができます。Servlet は JavaEE 仕様の 1 つで、実際にはインターフェースです. 将来的には Servlet クラスを定義して Servlet インターフェースを実装し、Web サーバーで Servlet を実行する必要があります. 

▶ クイックスタート

 ▷ 要件分析: サーブレット クラスを作成し、IDEA の Tomcat プラグインを使用してデプロイし、最後に、作成されたサーブレット プログラムにブラウザーからアクセスします。

 ▷ 具体的な実装手順は次のとおりです。

 1. (前回に準ずる) Web プロジェクト「web-demo」を作成し、サーブレット依存座標をインポート

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <!--
      此处为什么需要添加该标签?
       provided指的是在编译和测试过程中有效,最后生成的war包时不会加入
      因为Tomcat的lib目录中已经有servlet-api这个jar包,
      如果在生成war包的时候生效就会和Tomcat中的jar包冲突,导致报错
    -->
    <scope>provided</scope>
</dependency>

  2.作成:クラスを定義し、サーブレットインターフェースを実装し、インターフェース内のすべてのメソッドを書き換え、サービスメソッドに文を入力します

package com.itheima.web;

import javax.servlet.*;
import java.io.IOException;

public class ServletDemo1 implements Servlet {

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet hello world~");
    }
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

 3. 構成: クラスで @WebServlet アノテーションを使用して、サーブレットのアクセス パスを構成します。

@WebServlet("/demo1")

 4. アクセス: Tomcat を起動し、ブラウザに URL アドレスを入力してサーブレットにアクセスします。

http://localhost:8080/web-demo/demo1

 5. ブラウザがアクセスすると、コンソールに「servlet hello world~」と出力され、サーブレット プログラムが正常に実行されたことを示します。

2. 実行プロセス

▶ プロセス

 サーブレット プログラムは既に正常に実行されていますが、次の質問について考える必要があります。ServletDemo1 クラスのオブジェクトを作成しておらず、オブジェクトでサービス メソッドを呼び出していないのに、なぜ「servlet hello world~」という文がコンソールに印刷?

  1. ブラウザは `http://localhost:8080/web-demo/demo1` リクエストを送信し、リクエストから 3 つの部分、つまり `localhost:8080`、`web-demo`、`demo1` を解析できます。
   ○ `localhost:8080` から、アクセスする Tomcat Web サーバーを確認
   ○ `web-demo` から、Tomcat サーバー上にデプロイされた web-demo プロジェクトを確認 ○
   `demo1` から、アクセスしたいプロジェクト内のサーブレットを見つけることができます. クラス, @WebServlet の後ろの値に従って一致します.
  2. ServletDemo1 クラスを見つけると、Tomcat Web サーバーは ServletDemo1 クラスのオブジェクトを作成し、サービス メソッドを呼び出します. 3. ServletDemo1 は Servlet インターフェースを実装しているため
  、クラスは必須です Tomcat Web サーバーが呼び出すようにサービス メソッドを書き換えます
  4. サービス メソッドには ServletRequest と ServletResponse の 2 つのパラメータがあります ServletRequest はリクエスト データをカプセル化します、ServletResponse は応答データをカプセル化します。

▶ Servlet を作成したのは誰ですか? Servlet メソッドを呼び出したのは誰ですか?

  サーブレットは Web サーバーによって作成され、サーブレット メソッドは Web サーバーによって呼び出されます。

▶ サーバーは、サーブレットにサービス メソッドが必要であることをどのように認識しますか?

  カスタム サーブレットはサーブレット インターフェイスを実装してそのメソッドをオーバーライドする必要があり、サーブレット インターフェイスにはサービス メソッドがあるためです。

3.ライフサイクル

▶ Tomcat がサーブレット オブジェクトを作成したのはいつですか?

 ライフ サイクル: オブジェクトのライフ サイクルは、オブジェクトの作成から破棄までのプロセス全体を指します。

▷ Servlet は Servlet コンテナー (Web サーバー) で実行され、そのライフサイクルはコンテナーによって管理され、4 つの段階に分けられます。

  1. ロードとインスタンス化: デフォルトでは、サーブレットが初めてアクセスされると、コンテナーによってサーブレット オブジェクトが作成されます。デフォルトでは、最初の訪問時にコンテナーによってサーブレットが作成されますが、サーブレットの作成に時間がかかる場合、最初の訪問者は長時間待たなければならず、ユーザー エクスペリエンスが低下します。サーブレット サーバーの作成は、サーバーの起動時に作成されます。

@WebServlet(urlPatterns = "/demo1",loadOnStartup = 1)
/*
loadOnstartup的取值有两类情况
      (1)负整数:第一次访问时创建Servlet对象
      (2)0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
*/

   2. 初期化: サーブレットがインスタンス化されると、コンテナーはサーブレットの init() メソッドを呼び出してオブジェクトを初期化し、構成ファイルのロードや接続の作成などの初期化タスクを完了します。このメソッドは 1 回だけ呼び出されます。
  3. リクエスト処理: サーブレットがリクエストされるたびに、サーブレット コンテナはサーブレットの service() メソッドを呼び出してリクエストを処理します。
  4. サービスの終了: メモリを解放する必要がある場合、またはコンテナーを閉じる必要がある場合、コンテナーはサーブレット インスタンスの destroy() メソッドを呼び出して、リソースの解放を完了します。destroy() メソッドが呼び出された後、コンテナーはサーブレット インスタンスを解放します。サーブレット インスタンスは、Java のガベージ コレクターによって再利用されます。

▶ ケース

package com.itheima.web;
  
  /**
  * Servlet生命周期方法
  */
  @WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)
  public class ServletDemo2 implements Servlet {
  
      /**
       *  初始化方法
       *  1.调用时机:默认情况下,Servlet被第一次访问时,调用
       *      loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用
       *  2.调用次数: 1次
       */
      public void init(ServletConfig config) throws ServletException {
          System.out.println("init...");
      }
  
      /**
       * 提供服务
       * 1.调用时机:每一次Servlet被访问时,调用
       * 2.调用次数: 多次
       */
      public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
          System.out.println("servlet hello world~");
      }
  
      /**
       * 销毁方法
       * 1.调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用
       * 2.调用次数: 1次
       */
      public void destroy() {
          System.out.println("destroy...");
      }

      public ServletConfig getServletConfig() {
          return null;
      }
  
      public String getServletInfo() {
          return null;
      }
  }

注: サーブレットの destroy メソッドはどのように実行できますか?

 ターミナル コマンド ラインで、最初に「mvn tomcat7:run」を使用して起動し、次に「ctrl+c」を使用して tomcat を閉じます。

▶まとめ

1. サーブレット オブジェクトはいつ作成されますか?

  デフォルトは初回アクセス時に作成ですが、 @WebServlet(urlPatterns = "/demo2", loadOnStartup = 1) の loadOnStartup を使用して、サーバーの起動時に作成するように変更できます。

 2. サーブレットのライフサイクルに関わる 3 つのメソッド、この 3 つのメソッドとは? いつ呼び出されるか? 呼び出される回数は? ○ init   メソッド
  は、サーブレット オブジェクトの作成時に 1 回だけ実行されます。   . destroy メソッドは、サーブレット オブジェクトが破棄されるときに呼び出され、1 回だけ実行されます。

4.サーブレットの5つのメソッド

▷ 初期化メソッド、サーブレット作成時に実行、一度だけ実行

void init(ServletConfig config) 

▷ サーブレットにアクセスするたびに呼び出されるサービス メソッドを提供する

void service(ServletRequest req, ServletResponse res)

▷ Destruction メソッドは、サーブレットが破棄されるときにこのメソッドが呼び出されます。メモリの割り当て解除またはサーバーのシャットダウン時にサーブレットを破棄する

void destroy() 

▷サーブレット情報を取得する

String getServletInfo() 
//该方法用来返回Servlet的相关信息,没有什么太大的用处,一般我们返回一个空字符串即可
public String getServletInfo() {
    return "";
}

▷ ServletConfig オブジェクトを取得する

ServletConfig getServletConfig()

▶ご注意

 ServletConfig オブジェクトは init メソッドのパラメーターに含まれており、Tomcat Web サーバーは Servlet オブジェクトの作成時に init メソッドを呼び出し、ServletConfig オブジェクトを渡す必要があります。サーバーから渡された ServletConfig を返すだけで済みます。

package com.itheima.web;

@WebServlet(urlPatterns = "/demo3",loadOnStartup = 1)
public class ServletDemo3 implements Servlet {

    private ServletConfig servletConfig;
    
    public void init(ServletConfig config) throws ServletException {
        this.servletConfig = config;
        System.out.println("init...");
    }
    public ServletConfig getServletConfig() {
        return servletConfig;
    }
    
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("servlet hello world~");
    }

    public void destroy() {
        System.out.println("destroy...");
    }
    
    public String getServletInfo() {
        return "";
    }
}

5. アーキテクチャ

▶ はじめに

 サーブレットを書きたい場合は、サーブレットのインターフェースを実装し、インターフェースの5つのメソッドを書き直さなければなりません.要件は満たせますが、サービスメソッドだけに注目するだけなので、書くのはさらに面倒です.もっと簡単な方法がありますか? サーブレットを作成するのはどうですか? この問題を解決するには、まずサーブレットのアーキテクチャを理解する必要があります。

 今後は B/S アーキテクチャの Web プロジェクトを開発する予定ですが、いずれも HTTP プロトコルを対象としているため、HttpServlet を継承してサーブレットをカスタマイズします。

▶ 書き方

@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //TODO GET 请求方式处理逻辑
        System.out.println("get...");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //TODO Post 请求方式处理逻辑
        System.out.println("post...");
    }
}

▷ サーブレットをリクエストする GET リクエストを送信するには、ブラウザから「http://localhost:8080/web-demo/demo4」を送信するだけで、doGet メソッドが実行されていることがわかります。サーブレットを要求するPOST
リクエストは、ブラウザだけでは実現できません. このとき、リクエストを送信するためのフォーム form を記述し、webapp の下に `a.html` ページを作成する必要があります。その内容は次のとおりです。 :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/web-demo/demo4" method="post">
        <input name="username"/><input type="submit"/>
    </form>
</body>
</html>

  テストを開始すると、doPost メソッドが実行されていることがわかります。

▶ なぜ HttpServlet は、リクエスト メソッドごとに異なるメソッドを呼び出すのですか?

 フロント エンドが GET および POST リクエストを送信するとき、パラメータの位置が矛盾しています. GET リクエスト パラメータはリクエスト行にあり、POST リクエスト パラメータはリクエスト ボディにあります. 異なるリクエスト メソッドを処理するには、 service メソッドで判断し、別のビジネス処理を記述します。

package com.itheima.web;

@WebServlet("/demo5")
public class ServletDemo5 implements Servlet {

    public void init(ServletConfig config) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        //如何调用?
        //获取请求方式,根据不同的请求方式进行不同的业务处理
        HttpServletRequest request = (HttpServletRequest)req;
       //1. 获取请求方式
        String method = request.getMethod();
        //2. 判断
        if("GET".equals(method)){
            // get方式的处理逻辑
        }else if("POST".equals(method)){
            // post方式的处理逻辑
        }
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

▶ 開発の簡素化

 上記は達成できますが、各サーブレット クラスに同様のコードが存在します.この問題に対する最適化戦略はありますか?

1.コード開発を簡素化するために、サーブレットインターフェースを継承およびカプセル化できます。

package com.itheima.web;

public class MyHttpServlet implements Servlet {
    public void init(ServletConfig config) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest)req;
        //1. 获取请求方式
        String method = request.getMethod();
        //2. 判断
        if("GET".equals(method)){
            // get方式的处理逻辑
            doGet(req,res);
        }else if("POST".equals(method)){
            // post方式的处理逻辑
            doPost(req,res);
        }
    }

    protected void doPost(ServletRequest req, ServletResponse res) {
    }

    protected void doGet(ServletRequest req, ServletResponse res) {
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

2. MyHttpServlet クラスを使用すると、将来 Servlet クラスを作成するときに、MyHttpServlet を継承し、親クラスの doGet メソッドと doPost メソッドを書き換えて、GET および POST リクエストのビジネス ロジックを処理するだけで済みます。

@WebServlet("/demo5")
public class ServletDemo5 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("get...");
    }

    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
        System.out.println("post...");
    }
}

MyHttpServlet のようなサーブレット、つまり HttpServlet の `service()` メソッドが提供されています。HttpServlet はソース コードでより多くのことを行い、GET と POST を処理できるだけでなく、他の 5 つの要求メソッドも処理できることがわかります。

6.urlPattern の設定

サーブレット クラスを作成したら、アクセスするには、そのアクセス パス (urlPattern) を構成する必要があります。

▶ サーブレットは複数の urlPatterns を構成できます

 package com.itheima.web;
 
  /**
  * urlPattern: 一个Servlet可以配置多个访问路径
  */
  @WebServlet(urlPatterns = {"/demo7","/demo8"})
  public class ServletDemo7 extends MyHttpServlet {
  
      @Override
      protected void doGet(ServletRequest req, ServletResponse res) {
          
          System.out.println("demo7 get...");
      }
      @Override
      protected void doPost(ServletRequest req, ServletResponse res) {
      }
  }

ブラウザに「http://localhost:8080/web-demo/demo7」と「http://localhost:8080/web-demo/demo8」を入力すると、この2つのアドレスでServletDemo7のdoGetメソッドにアクセスできます。

▶ urlPattern 設定ルール

 ▷ 完全一致

 @WebServlet(urlPatterns = "/user/select")
    public class ServletDemo8 extends MyHttpServlet {
    
        @Override
        protected void doGet(ServletRequest req, ServletResponse res) {
    
            System.out.println("demo8 get...");
        }
        @Override
        protected void doPost(ServletRequest req, ServletResponse res) {
        }
    }

    ● アクセスパス `http://localhost:8080/web-demo/user/select`

▷ ディレクトリマッチング

     

    @WebServlet(urlPatterns = "/user/*")
    public class ServletDemo9 extends MyHttpServlet {
    
        @Override
        protected void doGet(ServletRequest req, ServletResponse res) {
    
            System.out.println("demo9 get...");
        }
        @Override
        protected void doPost(ServletRequest req, ServletResponse res) {
        }
    }

● アクセスパス `http://localhost:8080/web-demo/user/any`

● 結論: `/user/*` の `/*` は、ゼロ以上の階層アクセス ディレクトリを表し、完全一致の優先度はディレクトリ一致の優先度よりも高くなります。

▷延長戦

   

    @WebServlet(urlPatterns = "*.do")
    public class ServletDemo10 extends MyHttpServlet {
    
        @Override
        protected void doGet(ServletRequest req, ServletResponse res) {
    
            System.out.println("demo10 get...");
        }
        @Override
        protected void doPost(ServletRequest req, ServletResponse res) {
        }
    }

● アクセスパス `http://localhost:8080/web-demo/any.do`

● 注:

    1. パス構成が拡張子でない場合は、パスの前に「/」を追加する必要があります。そうしないと、エラーが報告されます

    2. パス構成が `*.do` の場合、`/` を *.do の前に追加することはできません。そうしないと、エラーが報告されます。

▷任意の試合

   

    @WebServlet(urlPatterns = "/")
    public class ServletDemo11 extends MyHttpServlet {
    
        @Override
        protected void doGet(ServletRequest req, ServletResponse res) {
    
            System.out.println("demo11 get...");
        }
        @Override
        protected void doPost(ServletRequest req, ServletResponse res) {
        }
    }

● アクセスパス `http://localhost:8080/demo-web/arbitrary`

    @WebServlet(urlPatterns = "/*")
    public class ServletDemo12 extends MyHttpServlet {
    
        @Override
        protected void doGet(ServletRequest req, ServletResponse res) {
    
            System.out.println("demo12 get...");
        }
        @Override
        protected void doPost(ServletRequest req, ServletResponse res) {
        }
    }

●アクセスパス`http://localhost:8080/demo-web/arbitrary

● 注: `/` と `/*` の違いは何ですか?


    1. プロジェクトのサーブレットが「/」で構成されている場合、Tomcatの    DefaultServlet が上書きされ、他の URL パターンが一致しない場合にこのサーブレットが使用されます。, 任意のアクセスパスに一致することを意味します.
    3. DefaultServlet は静的リソースを処理するために使用されます. "/" が設定されている場合, デフォルトは上書きされます.サーブレット クラスにより、最終的に静的リソースにアクセスできなくなります。

7.XML 構成

  以前のサーブレット構成では、すべて @WebServlet を使用します。これは、サーブレットがバージョン 3.0 以降のアノテーション構成をサポートする構成方法です。バージョン 3.0 より前では、XML 構成ファイルのみがサポートされています。XML 構成ステップには 2 つのステップがあります。

▶ 最初のステップ: Servlet クラスを書く

public class ServletDemo13 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo13 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

▶ ステップ 2: web.xml でサーブレットを構成する

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- 
        Servlet 全类名
    -->
    <servlet>
        <!-- servlet的名称,名字任意-->
        <servlet-name>demo13</servlet-name>
        <!--servlet的类全名-->
        <servlet-class>com.itheima.web.ServletDemo13</servlet-class>
    </servlet>

    <!-- 
        Servlet 访问路径
    -->
    <servlet-mapping>
        <!-- servlet的名称,要和上面的名称一致-->
        <servlet-name>demo13</servlet-name>
        <!-- servlet的访问路径-->
        <url-pattern>/demo13</url-pattern>
    </servlet-mapping>
</web-app>

この設定方法はアノテーションに比べて確認が大変面倒なので、開発にはアノテーションを利用することをお勧めします。

おすすめ

転載: blog.csdn.net/yzh2776680982/article/details/126807089