JavaWeb (11. 会話テクノロジー)

11-会話テクノロジー

今日の目標

  • セッショントラッキングテクノロジーとは何かを理解する

  • Cookieの使用を理解する

  • セッションの使い方をマスターする

  • ユーザーログイン登録ケースの機能改善

1つ、セッショントラッキングテクノロジーの概要

  これら 4 つの単語については会话跟踪、説明するために分解する必要があります。まずそれらが何であるかを理解し会话、次にそれが何であるかを理解する必要があります会话跟踪

  • セッション:ユーザーがブラウザを開いて Web サーバーのリソースにアクセスすると、一方が切断してセッションが終了するまでセッションが確立されます。セッションには複数のリクエストとレスポンスを含めることができます

    • ブラウザがリクエストを発行し、サーバーがフロントエンドにデータで応答すると、(ブラウザとサーバーの間の) セッションが確立されます。
    • セッションの確立後、ブラウザもサーバーも閉じていなければ、セッションは引き続き確立されます。
    • ブラウザとサーバーは引き続きセッションを使用してリクエストを送信し、応答することができます。上記のプロセス全体が呼び出されます。セッション

      実際のシナリオを使用して会話を理解します。たとえば、JD.com にアクセスすると、ブラウザを開いて JD.com のホームページに入ると、ブラウザと JD.com のサーバーの間にセッションが確立されます。その後、製品を検索し、商品の詳細を確認し、参加する このセッションでショッピングカートなどの入力はすべて完了します。
      考えてみます: 下の図では、合計でいくつのセッションが確立されていますか?
    ここに画像の説明を挿入します
    各ブラウザはサーバーとのセッションを確立し、合計は次のようになります。3セッション。

  • セッション追跡:ブラウザの状態を維持する方法。サーバーは、同じセッション内の複数のリクエスト間でデータを共有するために、複数のリクエストが同じブラウザから送信されたかどうかを識別する必要があります。

    • サーバーは、複数のブラウザから送信される可能性のある複数のリクエストを受信します。たとえば、上の図の 6 つのリクエストは 3 つのブラウザから送信されます。

    • サーバーはリクエストが同じブラウザからのものであるかどうかを識別する必要があります

    • サーバーがブラウザを識別するために使用するプロセス。このプロセスはセッション追跡です。

    • サーバーがブラウザを認識すると、同じセッション内の複数のリクエスト間でデータを共有できます。

       次に、別の疑問が生じます。なぜセッション内の複数のリクエストがデータを共有する必要があるのでしょうか。このデータ共有機能を使用すると、どのような機能ができるようになりますか?実装されていますか?

    • ショッピング カート:加入购物车と は去购物车结算2 つのリクエストですが、前のリクエストで追加された商品を後続のリクエストで表示したい場合は、データ共有を使用する必要があります。

    • このページにはユーザーのログイン情報が表示されます。多くの Web サイトは、ログイン後に複数の機能にアクセスします。複数のリクエストを送信した後、ブラウザーは現在ログインしているユーザー [ユーザー名] に関する情報が表示されます。、Baidu、JD.com、Code Cloud など。

    • ウェブサイトのログインページの機能记住我: ユーザーがログインに成功すると、记住我ボタンをチェックした後、次回ログイン時にユーザー名とパスワードが自動的に入力され、ユーザーのログイン操作が簡素化されます。また、次の間でデータを共有することも含まれます。

    • ログイン ページの確認コード機能: 確認コードを生成し、確認コードを入力してクリックして登録します。これらも 2 つのリクエストです。2 つのリクエストのデータを比較する必要があります。それらが同じである場合、登録は許可されます。この機能の実装には、同じセッション内でデータを共有することも必要です。

  これらの事例の説明により、皆さんも会话追踪ある程度の技術は理解できたと思いますが、実際の開発においても非常に重要な技術です。会话跟踪これらのテクノロジーを学ぶ前に、なぜブラウザとサーバーが現在データ共有をサポートしていないのかを考える必要があります

  • HTTP リクエストは、ブラウザとサーバー間のデータ送信に使用されます。
  • HTTPプロトコルはステタスはありません、ブラウザがサーバーをリクエストするたびに、サーバーはリクエストを次のように扱います。新しい聞く
  • HTTP プロトコルはステートレスになるように設計されているため、各リクエストは互いに独立しており、互いに影響を与えません。
  • リクエストが独立すると、複数のリクエスト間でデータを共有することはできません。

特定の理由を分析した後、セッション トラッキング テクノロジを実装するにはどうすればよいですか? 具体的な実装方法は次のとおりです:
(1) クライアント セッション トラッキング テクノロジ:Cookie
(2) サーバー側のセッション追跡テクノロジー:Session
  どちらのテクノロジーもセッション トラッキングを実装できますが、それらの最大の違いは次のとおりです。Cookie はブラウザ側に保存され、セッションはサーバー側に保存されます。

具体的な学習アイデアは次のとおりです。

  • CooKie基本的な使い方、原理、使い方の詳細
  • Session基本的な使い方、原理、使い方の詳細
  • CookieおよびSessionの包括的な事例

1. 概要

この項では主に以下の内容を紹介します。セッションそしてセッション追跡テクノロジー、次のことに注意する必要があります。

  • HTTP プロトコルはステートレスであるため、HTTP プロトコルに依存してセッション追跡を行うことはできません。
  • セッション追跡を実装したい場合は、Cookie とセッションを使用する必要があります

このCookieとSessionの具体的な使い方ですが、まずはCookieから見ていきましょう。

二、クッキー

Cookie を学習するには、主に次の問題を解決します。

  • クッキーとは何ですか?
  • Cookieはどのように使用されますか?
  • Cookieはどのように実装されますか?
  • Cookieを使用する際の注意点は何ですか?

1、クッキーの基本的な使い方

①.コンセプト

クッキー: クライアント セッション テクノロジはデータをクライアントに保存し、後続の各リクエストにはアクセス用の Cookie データが含まれます。
②.Cookieワークフロー
ここに画像の説明を挿入します

  • サーバーは、ServletA と ServletB という 2 つのサーブレットを提供します。
  • ブラウザはHTTPリクエスト1をサーバに送信し、サーバServletAはリクエストを受信して​​業務処理を実行します。
  • サーバー側の ServletA は、処理中に Cookie オブジェクトを作成し、name=zsデータを Cookie に保存できます。
  • サーバー側の ServletA がデータに応答するとき、Cookie オブジェクトを使用してブラウザに応答します。
  • ブラウザは応答データを受信すると、そのデータをブラウザのメモリ内の Cookie オブジェクトに保存します。このとき、ブラウザとサーバーは、セッションが確立されました
  • 同じセッション内でブラウザは HTTP リクエスト 2 をサーバー ServletB に再度送信し、ブラウザはすべてのデータを Cookie オブジェクトに保持します。
  • ServletB がリクエストとデータを受信すると、Cookie オブジェクトに格納されているデータを取得できるため、同じセッション内の複数のリクエスト間でデータを共有できます。

③. Cookie の基本的な使い方
  . Cookie を使用する場合は、バックグラウンド コードが Cookie をどのように操作するかにさらに注意を払う必要があります. Cookie の操作は主に 2 つのカテゴリに分類されます。クッキーを送信するそしてクッキーを取得する,上記2つのコンテンツをそれぞれどのように実装すればよいでしょうか?

1.1. Cookieの送信

  • Cookieオブジェクトの作成とデータの設定
Cookie cookie = new Cookie("key","value");
  • Cookieをクライアントに送信します: 使用します応答物体
response.addCookie(cookie);

Cookie の送信に対応する手順を紹介した後、Cookie の送信を完了するケースを使用してみましょう。具体的な実装手順は次のとおりです。

要件: Cookie オブジェクトを生成し、データをサーブレットに保存し、そのデータをブラウザに送信します
(1)。プロジェクト名が cookie-demo である Maven プロジェクトを作成し、pom.xml に依存関係を追加します
(2)。サーブレットを作成します。クラス、名前は AServlet
(3)。AServlet で Cookie オブジェクトを作成し、データを保存し、フロントエンドに送信します
(4)。テストを開始し、ブラウザーで Cookie オブジェクトの値を表示します。

(1) Maven プロジェクト cookie-demo を作成し、pom.xml に依存関係を追加します。

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
    <!--servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!--jsp-->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
    <!--jstl-->
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>
</dependencies>

(2) という名前のサーブレット クラスを作成します。AServlet
(3) サーブレット内に Cookie オブジェクトを作成し、データを格納してフロントエンドに送信します。

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //发送Cookie
        //1. 创建Cookie对象
        Cookie cookie = new Cookie("username","zs");
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(4) テストを開始し、ブラウザの Cookie オブジェクトの値を確認します。
Chrome ブラウザにアクセスしてhttp://localhost:8080/cookie-demo/aServlet
Cookie 値を表示するには、次の 2 つの方法があります。

方法 1:
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ここに画像の説明を挿入します
方法 2 : 開発者ツールを開くか、ショートカット キー F12 または Ctrl+Shift+I を使用するかを選択します。

1.2. Cookieの取得

  • クライアントが保持するすべての Cookie を取得するには、次を使用します。リクエスト物体
Cookie[] cookies = request.getCookies();
  • 配列を走査し、各 Cookie オブジェクトを取得します。for
  • Cookie オブジェクトのメソッドを使用してデータを取得する
cookie.getName();
cookie.getValue();

  Cookie の取得に対応する手順を紹介した後、ケースを使用して Cookie の取得を完了しましょう。具体的な実装手順は次のとおりです。

要件: 前のケースで Cookie オブジェクトに格納されたデータをサーブレットで取得する
1. BServlet という名前の新しいサーブレット クラスを作成します;
2. BServlet のリクエスト オブジェクトを使用して Cookie 配列を取得し、配列を走査し、指定されたデータを取得しますデータの名前 対応する値
3. テストを開始し、取得した値をコンソールに出力します。

(1) BServlet という名前の新しいサーブレット クラスを作成します。
(2) BServlet のリクエスト オブジェクトを使用して Cookie 配列を取得し、配列を走査して、指定された名前に対応する値をデータから取得します。=

package com.itheima.web.cookie;

@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取Cookie
        //1. 获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2. 遍历数组
        for (Cookie cookie : cookies) {
    
    
            //3. 获取数据
            String name = cookie.getName();
            if("username".equals(name)){
    
    
                String value = cookie.getValue();
                System.out.println(name+":"+value);
                break;
            }
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3) テストを開始し、得られた値をコンソールに出力します。
http://localhost:8080/cookie-demo/bServlet
ここに画像の説明を挿入します
IDEA コンソールにアクセスして、出力結果を確認します。
ここに画像の説明を挿入します

考える:テストするとき

  • AServlet と BServlet にアクセスする間にブラウザを閉じ、ブラウザを再起動してから BServlet にアクセスすることで、Cookie 内のデータを取得できますか? [個人テスト、可能です!

この問題については Cookie の使用の詳細で説明しますので、まずは試してみてください。

1.3. 概要

このセクションでは、主に Cookie の基本的な使い方を 2 つのパートに分けて説明します。

  • クッキーを送信:
    • Cookie オブジェクトを作成し、値を設定します。Cookie cookie = new Cookie("key","value");
    • クライアントに Cookie を送信する応答オブジェクト:response.addCookie(cookie);
  • Cookie を取得します。
    • 使用リクエストオブジェクトCookie 配列を取得します。Cookie[] cookies = request.getCookies();
    • トラバース配列
    • 配列内の各 Cookie オブジェクトの値を取得します。cookie.getName()和cookie.getValue()

  Cookie の基本的な使用法を紹介した後、Cookie の最下層はセッション内の 2 つのリクエスト間のデータ共有をどのように実現するのでしょうか?

2. Cookieの原理分析(知っておくだけ)

Cookie の実装原理は HTTP プロトコルに基づいており、HTTP プロトコルの 2 つのリクエスト ヘッダー情報が設計されています: (応答とリクエストはサーバーに関連しています)

  • レスポンスヘッダー:set-cookie
  • リクエストヘッダー: Cookie
    ここに画像の説明を挿入します
  • 先ほどのケースでは、AServletがフロントエンドにCookieを送信し、BServletがリクエストからCookieを取得する機能を実装することができました。
  • AServlet がデータに応答すると、Tomcat サーバーは HTTP プロトコルに基づいてデータに応答します。
  • Tomcat は、バックエンドが Cookie オブジェクトを返していることを検出すると、応答ヘッダーにデータ行を追加します。Set-Cookie:username=zs
  • ブラウザは応答結果を取得した後、応答ヘッダーからSet-Cookie対応する値を取得しusername=zs、そのデータをブラウザのメモリに保存できます。
  • ブラウザが BServlet にリクエストを再度送信すると、ブラウザはそのリクエストをリクエスト ヘッダーに自動的に追加します。Cookie: username=zsサーバーBServletに送信
  • Request オブジェクトは、リクエスト ヘッダー内の Cookie に対応する値を Cookie オブジェクトにカプセル化し、最終的に配列を形成します。
  • BServlet が Request オブジェクトを通じて Cookie[] を取得すると、そこから必要なデータを取得できます。

次に、先ほどのケースを使用して上記の結論を検証します。
(1) AServlet に対応するアドレスにアクセスしhttp://localhost:8080/cookie-demo/aServlet
  、Chrom ブラウザを使用して開発者ツール (F12 または Crtl+Shift+I) を開き、表示します。応答ヘッダー(2)のデータは、
ここに画像の説明を挿入します
BServlet に対応するアドレス `http://localhost:8080/cookie-demo/bServlet にアクセスします。
  Chrom ブラウザを使用して開発者ツール (F12 または Crtl+Shift+I) を開き、表示します。リクエストヘッダーデータの内容:
ここに画像の説明を挿入します

3、Cookie の使用状況の詳細 (重度)

  このセクションでは主に 2 つの知識、1 つ目は Cookie の生存時間、2 つ目は Cookie が漢字をどのように保存するかについて説明します。

3.1. Cookie の生存時間 (重い

前に次の質問について考えてもらいました。ここに画像の説明を挿入します

(1) ブラウザは AServlet にリクエストを送信し、AServlet はusernanme=zsブラウザへの既存の Cookie オブジェクトに応答します
。 (2) ブラウザは応答データを受信し、ブラウザのメモリに Cookie を保存します。
(3) ブラウザが AServlet にリクエストを送信すると、 BServlet、BServlet は Request オブジェクトを使用して Cookie データを取得できます
(4) BServlet にリクエストを送信する前に、ブラウザを閉じて再度開いてアクセスすると、BServlet は Cookie データを取得できますか?
注: ブラウザを閉じて開くことは、選択した新しいグラフィック カードを開くことを意味するわけではありません。ブラウザを閉じてから開く必要があり、順序を変更することはできません。
ここに画像の説明を挿入します

  上記の問題に対し、デモを通してBServletでCookieデータが取得できなくなっていることが分かりますが、これはなぜでしょうか?

  • デフォルトでは、Cookie はブラウザのメモリに保存され、ブラウザを閉じてメモリが解放されると、Cookie は破棄されます。
    この結論は、上記のデモンストレーション効果を裏付けるものですが、このデフォルト Cookie を使用すると、一部の要件を達成できないことがあります (例:
    ここに画像の説明を挿入します
    上記の Web サイトのログイン ページには记住我誰もがよく知っている機能があります)。
  • 初めてユーザー名とパスワードを入力し、チェックボックス记住我をオンにしてログインします。
  • 次回ログインするときは、ユーザー名とパスワードが自動的に入力されるため、ログインするために再入力する必要はありません。
  • たとえば、记住我この機能ではユーザー名とパスワードを 1 週間記憶する必要があるため、デフォルトの Cookie を使用すると問題が発生します。
  • デフォルトでは、Cookie はブラウザを閉じるとすぐにブラウザのメモリから削除され、记住我機能を実装できないためです。

そこで、次の問題が発生します。Cookie を永続的に保存する方法?

実際、Cookie はこれを実現するための対応する API を提供しています。この API は次のとおりです。setMaxAge

  • Cookie の生存時間を設定する
setMaxAge(int seconds)

パラメータ値は
次のとおりです。1.正の数: ブラウザが存在するコンピュータのハード ドライブに Cookie を書き込み、永続ストレージとして使用します。時間が経過すると自動的に削除されます
2.負の数: デフォルト値、Cookie は現在のブラウザのメモリ内にあります。ブラウザを閉じると、Cookie は破棄されます。
3. ゼロ: 対応する Cookie を削除します
次に、AServlet で Cookie の生存時間を設定します。

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //发送Cookie
        //1. 创建Cookie对象
        Cookie cookie = new Cookie("username","zs");
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60*60*24*7); //易阅读,需程序计算
        //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

コードを変更した後、テストを開始し、次のサイトにアクセスします。http://localhost:8080/cookie-demo/aServlet

  • AServlet にアクセスした後、ブラウザを閉じて再起動し、再度アクセスしてhttp://localhost:8080/cookie-demo/bServetコンソールに表示される場合username:zsは、ブラウザを閉じても Cookie が破棄されていないことを意味します。
  • ブラウザで Cookie の内容を表示すると、Cookie 関連の情報が表示されます。
    ここに画像の説明を挿入します

3.2. Cookie ストアの中国語 (重い

まず、効果をデモンストレーションしましょう。username=zs前の値を変更してCookie に中国語の文字を保存し、その効果を確認しますusername=张三张三

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //发送Cookie
        //1. 创建Cookie对象
        String value = "张三";
        Cookie cookie = new Cookie("username", value);
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60 * 60 * 24 * 7); //易阅读,需程序计算
        //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

アクセス テストを開始します。アクセスすると、http://localhost:8080/cookie-demo/aServletブラウザにエラー メッセージが表示されることがわかります。
ここに画像の説明を挿入します
上記のケースのデモンストレーションを通じて、次の結論に達しました。

  • Cookie は漢字を直接保存できません

  Cookie は中国語を保存できませんが、その必要がある場合、この時点でどのように解決すればよいでしょうか? 現時点では、
  以前に学習した知識ポイントを使用できるURL编码ため、中国語を保存する必要がある場合は、トランスコードする必要がある、具体的な実装アイデアは次のとおりです。

1. AServlet で中国語の URL をエンコードして使用し、URLEncoder.encode()エンコードされた値を Cookie に格納します。
2. BServlet の Cookie の値を取得し、取得された値が URL エンコードされた値になります。
3. 取得された値を URL デコードして格納し、それを使用しますURLDecoder.decode()。対応する中国語の値を取得できます

(1) AServlet における中国語の URL エンコード

package com.itheima.web.cookie;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //发送Cookie
        //1. 创建Cookie对象
        String value = "张三";
        //对中文进行URL编码
        value = URLEncoder.encode(value, "UTF-8");
        System.out.println("存储数据:" + value);
        //将编码后的值存入Cookie中
        Cookie cookie = new Cookie("username", value);
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60 * 60 * 24 * 7); //易阅读,需程序计算
        //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(2) BServletの値を取得し、その値をデコードする

package com.itheima.web.cookie;

@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //获取Cookie
        //1. 获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2. 遍历数组
        for (Cookie cookie : cookies) {
    
    
            //3. 获取数据
            String name = cookie.getName();
            if ("username".equals(name)) {
    
    
                String value = cookie.getValue(); //获取的是URL编码后的值 %E5%BC%A0%E4%B8%89
                //URL解码
                value = URLDecoder.decode(value, "UTF-8");
                System.out.println(name + ":" + value);//value解码后为 张三
                break;
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

プログラムを実行し、ブラウザで上記 2 つのファイルのアドレスをそれぞれ実行すると、コンソールに次の 2 つの文が出力されます。

存储数据:%E5%BC%A0%E4%B8%89
username:张三

この時点で、中国語を Cookie に保存して使用できるようになります。

3.3、まとめ

Cookie の使用の詳細では、 Cookie の存活时间合計について説明しました存储中文

  • 生存時間にはsetMaxAage()API の使い方をマスターする必要がある
  • 中国語を保存するには、URL エンコードとデコードの使用をマスターする必要があります。

三つ、セッション

  Cookie は、セッション内の複数のリクエスト間のデータ共有をすでに完了できます。また、セッションも実装できることにも言及しました。

  • セッションとは何ですか?
  • セッションの使い方は?
  • セッションはどのように実装されますか?
  • Sessionを利用する際の注意点は何ですか?

1、セッションの基本的な使い方

1.コンセプト
セッションサーバー側のセッション追跡テクノロジー: データをサーバーに保存します。

  • セッションはサーバー側に保存され、Cookie はクライアント側に保存されます。
  • クライアントに保存されているデータは簡単に盗まれたり傍受されたりするため、安全でない要素が数多くあります。
  • サーバー側に保存されるデータは、クライアント側に保存されるデータよりも小さくなります。より安全な

2.セッションワークフロー
ここに画像の説明を挿入します

  • サーバー側の AServlet は Session オブジェクトを取得し、そこにデータを保存します。
  • サーバー側の BServlet は同じ Session オブジェクトを取得し、そこからデータを取得します。
  • これにより、セッション内の複数のリクエスト間でのデータ共有が可能になります。
  • 現在の最大の疑問は、AServlet と BServlet が同じ Session オブジェクトを使用することを確認する方法です (原理分析セッションで説明)。

3. Session の基本的な使い方
  JavaEE では、セッション内の複数のリクエスト間のデータ共有機能を実現するために、HttpSession インターフェースが提供されています。
具体的な使用手順は次のとおりです。

  • セッションオブジェクトの取得requestオブジェクトを使用して
HttpSession session = request.getSession();
  • Session オブジェクトによって提供される関数:
    • セッションフィールドにデータを保存する
      void setAttribute(String name, Object o)
      
    • キーに基づいて値を取得します
      Object getAttribute(String name)
      
    • キーに基づいてキーと値のペアを削除します
      void removeAttribute(String name)
      

  Session 関連の API を導入した後、ケースを使用して Session の使用を完了しましょう。具体的な実装手順は次のとおりです。

要件: 1 つのサーブレットのセッションにデータを保存し、別のサーブレットのセッションに保存されたデータを取得します。
1. SessionDemo1 という名前のサーブレット クラスを作成します
。 2. SessionDemo2 という名前のサーブレット クラスを作成します
。 3. SessionDemo1 のメソッド内: Session オブジェクトを取得します。 4. SessionDemo2 のメソッド内: Session オブジェクトを取得
し、データを取得します
。 5. テストを開始します。

(1) SessionDemo1 という名前のサーブレット クラスを作成します
(3) SessionDemo1: Session オブジェクトを取得してデータを格納します

package com.itheima.web.session;

@WebServlet("/demo1")
public class SessionDemo1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //存储到Session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        //2. 存储数据
        session.setAttribute("username", "zs");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(2) SessionDemo2という名前のServletクラスを作成します
(4) SessionDemo2: Sessionオブジェクトを取得してデータを取得します

package com.itheima.web.session;

@WebServlet("/demo2")
public class SessionDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取数据,从session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        //2. 获取数据
        Object username = session.getAttribute("username");
        System.out.println(username);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(5) テストを開始します。

  • 最初にアクセスしhttp://localhost:8080/cookie-demo/demo1、セッションにデータを保存します
  • アクセス中にhttp://localhost:8080/cookie-demo/demo2Sessionからデータを取得
  • コンソールを表示します。
    ここに画像の説明を挿入します
    ケースの効果により、Session が 1 つのセッション内の 2 つのリクエスト間でデータを共有できることがわかります。

1.1、まとめ

これで、Session の基本的な使い方が完了しました。マスターするための重要なポイントは次のとおりです。

  • セッションの取得
    HttpSession session = request.getSession();
    
  • 共通セッションメソッドの使用
    void setAttribute(String name, Object o)
    Object getAttribute(String name)
    
    注: Session に保存できるのはオブジェクト型のデータです。つまり、任意のデータ型を Session に保存できます。

  Session の基本的な使用法を紹介した後、Session の基礎となる層はセッション内の 2 つのリクエスト間のデータ共有をどのように実現するのでしょうか?

2. セッション原理の分析

  • セッションはCookieに基づいて実装されます

  実際、この文では、Session の基礎となる実装を詳しく説明することはできません。次に、Session の具体的な実装原理を段階的に分析してみましょう。

(1)前提条件
ここに画像の説明を挿入します
  Session がセッション内の複数のリクエスト間でデータ共有を実現したい場合、複数のリクエストによって取得されたオブジェクトが同じセッションであることを保証する必要があります。
  では、それらはオブジェクトなのでしょうか?この結論を検証するのは非常に簡単で、上記の場合、2 つのサーブレットのセッション オブジェクトを出力するだけで済みます。
セッションデモ1

        //1. 获取Session对象
        HttpSession session = request.getSession();
        System.out.println(session);

セッションデモ2

        //获取数据,从session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        System.out.println(session);

テストと訪問をそれぞれ開始し、
http://localhost:8080/cookie-demo/demo1
http://localhost:8080/cookie-demo/demo2
ここに画像の説明を挿入します
印刷すると、次の結論が得られます。

  • 2 つのサーブレット クラスで取得される Session オブジェクトは同じです
  • デモ 1 とデモ 2 のリクエストを複数回更新しても、コンソールに表示される最終結果は同じになります。

  新しいブラウザを開いてデモ 1 またはデモ 2 にアクセスした場合、コンソールに表示されるセッションは同じオブジェクトのままでしょうか?
ここに画像の説明を挿入します
  注: コンピュータでデモンストレーションを行う場合、同じブラウザの場合は、すべてのブラウザを閉じてから再度開き、新しいブラウザを開く必要があります。
  もちろん、テストに別のブラウザを使用することもできるため、以前のブラウザをすべて閉じる必要はありません。
  試験結果: 別のブラウザを使用している場合、またはブラウザを再度開いた後、印刷されるセッションは異なります。
  したがって、Session はセッション内の複数のリクエスト間のデータ共有も実装します。
  次に、主要な質問が来ます。Session は、セッションで取得した Session オブジェクトが同じであることをどのように確認しますか?
ここに画像の説明を挿入します

(1) デモ 1 が初めてセッション オブジェクトを取得したとき、セッション オブジェクトは一意の識別子を持ちますid:10
(2) デモ 1 がセッションに他のデータを格納し、すべての業務を処理した後、その結果を応答する必要があります。 Tomcat サーバー ブラウザ(3) Tomcat サーバーは、セッション オブジェクトがビジネス処理で使用されていることを検出すると、セッションの一意の識別子をcookie として
扱い、応答ヘッダーに追加してブラウザに応答します(4)ブラウザは応答結果を受信すると、応答ヘッダー内の Cookie データをブラウザーのメモリに保存します。(5) ブラウザーが同じセッションでデモ 2 にアクセスすると、Cookie 内のデータを次の形式でリクエスト ヘッダーに追加します。それをサーバー Tomcat に送信します(6) デモ 2 はリクエストを取得した後、リクエスト ヘッダーから Cookie 内の JSESSIONID 値を 10 として読み取り、サーバー メモリ内でセ​​ッション オブジェクトを検索します。見つかった場合は、オブジェクト(7) を閉じてブラウザを開くと、ブラウザの Cookie が破棄されているため、JESSIONID データがなく、サーバーによって取得されたセッションは新しいセッション オブジェクトになります。 。id:10Set-Cookie:JESSIONID=10

cookie: JESSIONID=10
id:10

ここまででSession是基于Cookie来实现的説明は終わりましたので、次は例を挙げて説明していきます:
(1) Chrome ブラウザで にアクセスしhttp://localhost:8080/cookie-demo/demo1、開発者モード (F12 または Ctrl+Shift+I) を開き、表示します。応答ヘッダーデータ:
ここに画像の説明を挿入します
(2) Chrome ブラウザを使用して再度アクセスしhttp://localhost:8080/cookie-demo/demo2、表示します。リクエストヘッダーデータ:
ここに画像の説明を挿入します

2.1、まとめ

セッションの原理を導入した後、覚えておく必要があるのは、

  • セッションはCookieに基づいて実装されます

3、セッションの使用状況の詳細

  このセクションでは主に 2 つの知識を説明します。セッションのパッシベーションとアクティブ化、2つ目はセッションの破棄、まずセッションのパッシベーションとアクティベーションとは何なのかを学びましょう。

3.1、セッションのパッシベーションとアクティブ化

誰もが考える必要がある最初の質問は次のとおりです。

  • サーバーが再起動された後、セッション内のデータはまだそこにありますか?
    この質問に答えるには、まず下の図を見てください
    ここに画像の説明を挿入します
    (1) サーバー側の AServlet と BServlet によって共有されるセッション オブジェクトは、サーバーのメモリ
    (2) ) サーバーの再起動後、メモリ内のデータは解放され、オブジェクトは破棄されているはずなので、
    セッション データは存在しなくなるはずです。しかし、セッションが存在しない場合、どのような問題が発生するのでしょうか?

    例えば、
    (1) ユーザーが購入したい商品をショッピングカートに追加すると、データ共有のために同じセッションを複数回要求する必要があるため、そのデータはSession オブジェクトに格納されているものとします
    。ユーザーが支払いをしようとしている ユーザーが電話を受けると、支払いアクションが中断された
    (3) ユーザーが電話をかけている間に、何らかの理由でショッピング サイトの再起動が必要になった
    (4) 再起動後、セッションが切断されたデータが破壊され、ショッピングカート内の商品情報も消えてしまいました
    (5) ユーザーが再度支払いを開始したい場合、問題が発生します。

      したがって、セッションデータについては、サーバーが再起動されてもデータを保存できる必要があります。
      ここまで分析した後、Tomcat サーバーが再起動されたときに、セッション データが保存されるかどうか、およびどのように保存されるかを実際のケースを通じて実証できます。
      注: ここで説明したシャットダウンと起動では、正常にシャットダウンと起動が行われる必要があります。
    では、Tomcat サーバーを通常どおりにシャットダウンするにはどうすればよいでしょうか?
    Tomcat サーバーを起動および停止するには、コマンド ラインを使用する必要があります。
    起動する: プロジェクト pom.xml が配置されているディレクトリを入力して実行します。tomcat7:run
    ここに画像の説明を挿入します
    停止:起動したコマンドラインインターフェイスで、次のように入力します。ctrl+c

    上記の 2 つの通常の起動およびシャットダウン方法を使用した場合、次のテスト プロセスは次のようになります。

    (1) まず Tomcat サーバーを起動します
    (2)http://localhost:8080/cookie-demo/demo1セッション内のデータにアクセスして保存します
    (3) Tomcat サーバーを正しく停止します
    (4) Tomcat サーバーを再度再起動します
    (5)http://localhost:8080/cookie-demo/demo2セッション内のデータが取得できるかアクセスして確認します
    ここに画像の説明を挿入します

      テスト後、サーバーがシャットダウンされ、正常に起動されている限り、セッション内のデータを保存できることがわかります。
    では、Tomcat サーバーはどのようにしてこれを行うのでしょうか?
    具体的な理由は次のとおりです。セッションのパッシベーションとアクティブ化:

    • 不動態化: サーバーが正常にシャットダウンされた後、Tomcat はセッション データをハードディスク上のファイルに自動的に書き込みます。
      • パッシベーションされたデータ パスは次のとおりです。项目目录\target\tomcat\work\Tomcat\localhost\项目名称\SESSIONS.ser
        ここに画像の説明を挿入します
    • アクティベーション: サーバーを再起動した後、ファイルからセッションにデータをロードします。
      • データがセッションにロードされると、パス内のファイルがSESSIONS.ser削除されます。

  必要なのは、上記のプロセス全体を理解することだけです。すべての処理は Tomcat 自体で完了するため、私たちが参加する必要はありません。

まとめ
セッションのパッシベーションとアクティブ化を導入した後は、次の点に注意する必要があります。

  • セッションデータはサーバー側に保存され、サーバー再起動後にセッションデータが保存されます。
  • ブラウザを閉じて起動した後、再確立された接続はすでに新しいセッションであり、取得されたセッション データも新しいオブジェクトです。
  • セッションデータを共有したい場合、ブラウザを閉じることができないため、セッションデータを長時間保存することができません。
  • Cookie はクライアント側に保存され、長期間保存される可能性があります。

3.2. セッションの破棄

セッションを破棄するには 2 つの方法があります。

  • デフォルトでは、操作は実行されず、30 分後に自動的に破棄されます。
    • この有効期限は構成を通じて変更できます。
      • プロジェクトの 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_3_1.xsd"
                 version="3.1">
        
            <session-config>
                <session-timeout>100</session-timeout>
            </session-config>
        </web-app>
        
      • 構成されていない場合、デフォルトは 30 分です。デフォルト値は Tomcat の web.xml 構成ファイルにハードコーディングされています。ここに画像の説明を挿入します
  • Session オブジェクトの validate() を呼び出して破棄します。
    • SessionDemo2 クラスにセッション破棄メソッドを追加します。
package com.itheima.web.session;

@WebServlet("/demo2")
public class SessionDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取数据,从session中
        //1. 获取Session对象
        HttpSession session = request.getSession();
        // 销毁
        session.invalidate();
        //2. 获取数据
        Object username = session.getAttribute("username");
        System.out.println(username);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}
  • アクセス テストを開始し、最初にデモ 1 にアクセスしてセッションにデータを保存し、次に再びデモ 2 にアクセスしてセッションからデータを取得します。
    ここに画像の説明を挿入します
  • この破棄方法では通常、ユーザーが終了するときにセッションを破棄する必要があります。

4、Cookie とセッションの概要

  • Cookie とセッションは両方とも、セッション内の複数のリクエストを完了するために使用されます。データ共有の。
    2 つの必要なオブジェクトを組み合わせると、「
    Cookie とセッションの違いは何ですか?
    Cookie とセッションのアプリケーション シナリオは何ですか?」について考える必要があります。

  • 違い:

    • 保存場所: Cookie はクライアント側にデータを保存し、Session はサーバー側にデータを保存します。
    • セキュリティ: Cookie は安全ではありませんが、セッションは安全です
    • データサイズ: Cookie 最大 3KB、セッションのサイズ制限なし
    • 保存時間: Cookie は setMaxAge() を使用して長期間保存でき、セッションのデフォルトは 30 分です。
    • サーバーのパフォーマンス: Cookie はサーバー リソースを占有せず、セッションはサーバー リソースを占有します。
  • アプリケーションシナリオ:

    • ショッピング カート: 保存に Cookie を使用します
    • ログインユーザー名で表示:Sessionを使用して保存
    • 「私を記憶」機能: Cookie を使用して保存します
    • 検証コード: セッションを使用して保存します
  • 結論は

    • Cookieは、ログインしていないときにユーザーを確実に識別するために使用されます。
    • セッションはユーザーのログイン後にデータを保存するために使用されます

  Cookieとセッションを導入した後、どちらを使用するかは、具体的なビジネスに基づいて詳細に分析する必要があります。

四、ユーザーログイン登録事例

1. 需要分析

ニーズの表明:

  1. ユーザーログイン機能を完了します。ユーザーが「ユーザーを記憶する」にチェックを入れると、次回からログインページにアクセスします。自動入力ユーザー名パスワード
  2. 登録機能を完了して実装する検証コード関数
    ここに画像の説明を挿入します

2、ユーザーログイン機能

1. 要件:
ここに画像の説明を挿入します

  • ユーザーがログインに成功すると、リスト ページにジャンプし、現在ログインしているユーザーの名前がページ上に表示されます。
  • ユーザーがログインに失敗した後、ログイン ページに戻り、ページ上に対応するエラー メッセージを表示します。

2.プロセス分析の実施
ここに画像の説明を挿入します

(1) フロントエンドはリクエストとデータを Web 層の LoginServlet にフォーム経由で送信します
(2) LoginServlet でリクエストとデータ [ユーザー名とパスワード] を受け取ります
(3) LoginServlet がリクエストとデータを受信すると、ユーザー名とパスワードに基づいてクエリを完了するためにサービス層を呼び出します ユーザー オブジェクト
(4) サービス層では、UserService クラスを作成し、そのクラスにログイン メソッドを実装し、Dao 層の UserMapper を呼び出す必要がありますメソッド内
(5) UserMapper インターフェイスで、ユーザー名とパスワードに基づいてユーザー情報をクエリするメソッドを宣言します
(6) Dao レイヤーがデータをクエリした後、返されたデータを User オブジェクトにカプセル化し、そのオブジェクトをユーザーに渡しますサービス層
(7) サービス層はデータを Web 層に返します
(8) Web 層は User オブジェクトを取得した後、User オブジェクトを決定し、それが Null の場合は、ログイン ページにエラー メッセージを応答します。 Nullでない場合は一覧ページにジャンプし、現在ログインしているユーザーの情報をセッションに保存して一覧ページに引き継ぎます。

3. 具体的な実装

(1) Dao レイヤーのコード記述
(1.1) を完了し、04-资料\1. 登录注册案例\2. MyBatis环境\UserMapper.javaそれを com.itheima.mapper` パッケージの下に配置します。

package com.itheima.mapper;

public interface UserMapper {
    
    
    /**
     * 根据用户名和密码查询用户对象
     * @param username
     * @param password
     * @return
     */
    @Select("select * from tb_user where username = #{username} and password = #{password}")
    User select(@Param("username") String username,@Param("password")  String password);

    /**
     * 根据用户名查询用户对象
     * @param username
     * @return
     */
    @Select("select * from tb_user where username = #{username}")
    User selectByUsername(String username);

    /**
     * 添加用户
     * @param user
     */
    @Insert("insert into tb_user values(null,#{username},#{password})")
    void add(User user);
}

(1.2)、(エンティティクラスオブジェクトの作成) はパッケージの下に04-资料\1. 登录注册案例\2. MyBatis环境\User.java配置されます。com.itheima.pojo

package com.itheima.pojo;
public class User {
    
    

    private Integer id;
    private String username;
    private String password;

    public Integer getId() {
    
    
        return id;
    }
    public void setId(Integer id) {
    
    
        this.id = id;
    }
    public String getUsername() {
    
    
        return username;
    }
    public void setUsername(String username) {
    
    
        this.username = username;
    }
    public String getPassword() {
    
    
        return password;
    }
    public void setPassword(String password) {
    
    
        this.password = password;
    }
    @Override
    public String toString() {
    
    
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

(1.3) は次のディレクトリ04-资料\1. 登录注册案例\2. MyBatis环境\UserMapper.xmlに配置されます。resources/com/itheima/mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.UserMapper">

</mapper>

(2) Service層のコード記述完了
(2.1)com.itheima.serviceパッケージ配下にUserServiceクラスを作成

public class UserService {
    
    
    //1.使用工具类获取SqlSessionFactory
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    /**
     * 登录方法
     * @param username
     * @param password
     * @return
     */
    public User login(String username,String password){
    
    
        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取UserMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //4. 调用方法
        User user = mapper.select(username, password);
        //释放资源
        sqlSession.close();

        return  user;
    }
}

(3) ページと Web レイヤーのコード記述を完了する

(3.1)04-资料\1. 登录注册案例\1. 静态页面プロジェクトwebappディレクトリにコピーします。
ここに画像の説明を挿入します
(3.2)login.html内容を次のように変更します。login.jsp

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false"  language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link href="css/login.css" rel="stylesheet">
</head>

<body>
<div id="loginDiv" style="height: 350px">
    <form action="/brand-demo/loginServlet" method="post" id="form">
        <h1 id="loginMsg">LOGIN IN</h1>
        <!-- <div id="errorMsg">用户名或密码不正确</div>-->
        <div id="errorMsg">${login_msg}</div>
        <p>Username:<input id="username" name="username" type="text"></p>

        <p>Password:<input id="password" name="password" type="password"></p>
        <p>Remember:<input id="remember" name="remember" type="checkbox"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
            <a href="register.html">没有账号?</a>
        </div>
    </form>
</div>
</body>
</html>

(3.3) LoginServletクラスの作成

package com.itheima.web;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    
    
    private UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //2. 调用service查询
        User user = service.login(username, password);

        //3. 判断
        if (user != null) {
    
    
            //登录成功,跳转到查询所有的BrandServlet

            //将登陆成功后的user对象,存储到session
            HttpSession session = request.getSession();
            //将user信息存储到session;
            session.setAttribute("user", user);

            String contextPath = request.getContextPath();//获取项目访问路径
            response.sendRedirect(contextPath + "/selectAllServlet");//Respones请求重定向
        } else {
    
    
            // 登录失败,
            // 将错误信息存储到request,setAttribute传递数据给转发的对象
            request.setAttribute("login_msg", "用户名或密码错误");
            // 跳转到login.jsp,请求转发
            request.getRequestDispatcher("/login.jsp").forward(request, response);  
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3.4) brand.jsp のラベルの下に、現在のユーザーを歓迎するプロンプト メッセージを追加します。

<h1>${user.username},欢迎您</h1>

(3.5)login.jspを修正しEL式を使用してエラー情報を取得する

修改前内容:<div id="errorMsg">用户名或密码不正确</div>
修改后内容: <div id="errorMsg">${login_msg}</div>

(4) 起動、アクセステスト

(4.1) ログイン ページにアクセスし、間違ったユーザー名またはパスワードを入力します。
ここに画像の説明を挿入します
(4.2) 正しいユーザー名とパスワード情報を入力します。
ここに画像の説明を挿入します

2.1. 概要

  • LoginServletでは、ログインに成功したユーザーデータをセッションに保存し、リストページに現在ログインしているユーザー情報を取得して表示します。
  • LoginServletでは、リクエストにログイン失敗のエラーメッセージが格納されますが、セッションに格納すると、このセッション内のすべてのリクエストにログイン失敗のエラーメッセージが含まれることになりますが、これは必要ないので格納する必要はありませんセッション中

3、私を忘れない - クッキーを設定

  1. 必要:
      ユーザーが「ユーザーを記憶する」にチェックを入れると、次回ログインページにアクセスしたときにユーザー名とパスワードが自動的に入力されます。これにより、ユーザー エクスペリエンスが向上します。
    ここに画像の説明を挿入します
    上記の要求に対する最大の疑問は、ユーザー名とパスワードをどのように自動的に入力するかということです。

  2. 実装プロセス分析ユーザーがブラウザを閉じて数日後に再訪問しても自動的に入力される効果を実現する機能であるため、ログイン情報は保存可能なファイルに保存する必要が
      ある记住我長期間保存されており、ブラウザを閉じて再起動した後も有効なままです。クッキー、それで:

  • ユーザー名とパスワードを書きますクッキー、Cookie は永続的に保存され、次回アクセスするときにブラウザが自動的に Cookie を保持します。
  • ページ上のCookieデータを取得したら、ユーザー名とパスワードのボックスに設定します。
  • Cookie はいつ書き込まれますか?
    • ユーザーは書き込む前に正常にログインする必要があります
    • ユーザーがログインページでチェックする必要がある记住我チェックボックス
      ここに画像の説明を挿入します

(1) リクエストとデータを送信するとき、フロントエンドはユーザーがチェックしたかどうかに関するもう 1 つのRememberデータを運ぶ必要があります
(2) LoginServlet がデータを取得した後、Service を呼び出してユーザー名とパスワードの決定を完了します
( 3) ログインが成功し、ユーザーはフロントエンドのチェックボックスをオンにします。選択した場合、记住我ユーザー名とパスワードのデータを Cookie に書き込み、Cookie の生存時間を設定する必要があります。
(4) 設定が成功したら、データはフロントエンドに応答されます。

  1. 実装

(1)login.jspのチェックボックスの値を設定します。

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link href="css/login.css" rel="stylesheet">
</head>

<body>
<div id="loginDiv" style="height: 350px">
    <form action="/brand-demo/loginServlet" method="post" id="form">
        <h1 id="loginMsg">LOGIN IN</h1>
        <!--        <div id="errorMsg">用户名或密码不正确</div>-->
        <div id="errorMsg">${login_msg}</div>
        <p>Username:<input id="username" name="username" type="text"></p>
        <p>Password:<input id="password" name="password" type="password"></p>
        <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">&nbsp;&nbsp;&nbsp;
            <a href="register.html">没有账号?</a>
        </div>
    </form>
</div>
</body>
</html>

(2) LoginServlet のチェックボックスの値を取得し、ログイン成功後に Cookie を設定する

package com.itheima.web;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    
    
    private UserService service = new UserService();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //获取复选框数据
        String remember = request.getParameter("remember");

        //2. 调用service查询
        User user = service.login(username, password);

        //3. 判断
        if (user != null) {
    
    
            //登录成功,跳转到查询所有的BrandServlet
            //判断用户是否勾选记住我,字符串写前面是为了避免出现空指针异常
            if ("1".equals(remember)) {
    
    
                //勾选了,发送Cookie
                //1. 创建Cookie对象
                Cookie c_username = new Cookie("username", username);
                Cookie c_password = new Cookie("password", password);
                // 设置Cookie的存活时间
                c_username.setMaxAge(60 * 60 * 24 * 7);
                c_password.setMaxAge(60 * 60 * 24 * 7);
                //2. 发送
                response.addCookie(c_username);
                response.addCookie(c_password);
            }
            //将登陆成功后的user对象,存储到session
            HttpSession session = request.getSession();
            session.setAttribute("user", user);

            String contextPath = request.getContextPath();//获取项目访问路径
            response.sendRedirect(contextPath + "/selectAllServlet");//Respones请求重定向
        } else {
    
    
            // 登录失败,
            // 存储错误信息到request
            request.setAttribute("login_msg", "用户名或密码错误");
            // 跳转到login.jsp,转发;
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3) アクセス テストを開始します。
  現在のユーザー名とパスワードが正しく入力され、[記憶する] チェックボックスがオンになっている場合にのみ、Cookie 関連のデータが応答ヘッダーに表示されます。
ここに画像の説明を挿入します

4、私を覚えてます - クッキーを入手

  1. 必要な
      ログインが成功し、Remeber がチェックされたら、バックエンドからフロントエンドに返された Cookie データが保存されています。次に、ページ上の Cookie 内のデータを取得し、そのデータをページ上のユーザー名とパスワードのボックスに設定する必要があります。ログインページ。
    ここに画像の説明を挿入します
    ページ上で Cookie の値を直接取得するにはどうすればよいですか?

  2. プロセス分析を実装するには
    、ページで EL 式を使用できます。${cookie.key.value}
    key: Cookie に保存されているキー名を参照します。
    ここに画像の説明を挿入します

(1) login.jsp ユーザー名のフォーム入力ボックスの value 値を使用して、form 要素にデフォルト値を追加します。${cookie.username.value}

(2) login.jsp のパスワード フォーム入力ボックスの value 値を使用して、form 要素にデフォルト値を追加します。${cookie.password.value}

  1. 具体的な実装
    (1)login.jspページを変更する
<p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p>

<p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p>
  1. テストにアクセスしてログイン ページに再度アクセスすると、ユーザーとパスワードが入力されていることがわかります。
    ここに画像の説明を挿入します

5、ユーザー登録機能

  1. 必要
  • 登録機能:ユーザー情報をデータベースに保存
  • 認証コード機能
    • 確認コードを表示: 確認コードの画像を表示し、クリックして切り替えます。
    • 認証認証コード: 認証コードが正しく入力されていない場合、登録は失敗します。

ここに画像の説明を挿入します
2. プロセス分析の実装
ここに画像の説明を挿入します
(1) フロントエンドはフォーム経由でWeb層のRegisterServletにリクエストとデータを送信します。

(2) RegisterServletでリクエストとデータを受信[ユーザー名とパスワード]

(3) RegisterServlet はリクエストとデータを受信すると、Service 層を呼び出してユーザー情報の保存を完了します。

(4) Service 層では、UserService クラスを記述し、クラス内に register メソッドを実装し、ユーザーが既に存在するかどうかを確認し、存在しない場合はユーザー データの保存を完了します。

(5) UserMapper インターフェースで、ユーザー名に基づいてユーザー情報を照会するメソッドと、ユーザー情報を保存するメソッドの 2 つを宣言します。

(6) UserService クラスでの保存が成功した場合は true を返し、失敗した場合は false を返し、Web 層にデータを返します。

(7) Web 層は結果を取得後、true が返された場合はプロンプトを表示して注册成功ログイン ページに転送し、false が返された場合はプロンプト用户名已存在を表示して登録ページに転送します。

  1. 実装

(1) Dao 層コード参考資料の内容を完成させる
(2) Service 層コードを記述する

public class UserService {
    
    
    //1.使用工具类获取SqlSessionFactory
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
    /**
     * 注册方法
     * @return
     */
    public boolean register(User user){
    
    
        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取UserMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //4. 判断用户名是否存在
        User u = mapper.selectByUsername(user.getUsername());

        if(u == null){
    
    
            // 用户名不存在,注册
            mapper.add(user);
            sqlSession.commit();//提交事务;
        }
        sqlSession.close();//关闭

        return u ;

    }
}

(3) ページと Web 層のコード記述を完了します
(3.1) register.html の内容を register.jsp に変更します

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎注册</title>
    <link href="css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
    <div class="reg-content">
        <h1>欢迎注册</h1>
        <span>已有帐号?</span> <a href="login.jsp">登录</a>
    </div>
    <form id="reg-form" action="/brand-demo/registerServlet" method="post">

        <table>
            <tr>
                <td>用户名</td>
                <td class="inputs">
                    <input name="username" type="text" id="username">
                    <br>
                    <span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
                </td>
            </tr>
            <tr>
                <td>密码</td>
                <td class="inputs">
                    <input name="password" type="password" id="password">
                    <br>
                    <span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
                </td>
            </tr>

            <tr>
                <td>验证码</td>
                <td class="inputs">
                    <input name="checkCode" type="text" id="checkCode">
                    <img src="imgs/a.jpg">
                    <a href="#" id="changeImg">看不清?</a>
                </td>
            </tr>
        </table>
        <div class="buttons">
            <input value="注 册" type="submit" id="reg_btn">
        </div>
        <br class="clear">
    </form>
</div>
</body>
</html>

(3.2)RegisterServletの書き込み

package com.itheima.web;

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    
    
    private UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        //2. 调用service 注册
        boolean flag = service.register(user);
        //3. 判断注册成功与否
        if(!flag){
    
    
            //注册功能,跳转登陆页面
            request.setAttribute("register_msg","注册成功,请登录");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
    
    
            //注册失败,跳转到注册页面

            request.setAttribute("register_msg","用户名已存在");
            request.getRequestDispatcher("/register.jsp").forward(request,response);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(3.3) バックグラウンドから返されたエラー情報をページに表示し、register.jsp を変更する必要があります。

修改前:<span id="username_err" class="err_msg" style="display:none">用户名不太受欢迎</span>
修改后:<span id="username_err" class="err_msg">${register_msg}</span>

(3.4) 登録が成功した場合、ログインページに成功情報を表示する必要があるため、login.jsp も変更する必要があります。

修改前:<div id="errorMsg">${login_msg}</div>
修改后:<div id="errorMsg">${login_msg} ${register_msg}</div>

(3.5)login.jspを修正し、登録ジャンプアドレスをregister.jspに変更します。

修改前:<a href="register.html">没有账号?</a>
修改后: <a href="register.jsp">没有账号?</a>

(3.6) テストを開始し、ブラウザにアクセスしますhttp://localhost:8080/brand-demo/login.jsp
登録済みのユーザー情報が既に存在する場合
ここに画像の説明を挿入します
登録済みのユーザー情報が存在しない場合、登録は成功です。
ここに画像の説明を挿入します

6、認証コード表示

  1. 需要分析

検証コードの表示: 検証コードの画像を表示し、クリックして切り替えます。
ここに画像の説明を挿入します
検証コードの生成は、ツール クラスを通じて実装されます。特定のツール クラスについては、を参照してください。
04-资料\1. 登录注册案例\CheckCodeUtil.java

テスト用にこのツール クラスに main メソッドを記述します。

public static void main(String[] args) throws IOException {
    
    
    //生成验证码的图片位置
    OutputStream fos = new FileOutputStream("d://a.jpg");
    //checkCode为最终验证码的数据
    String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, fos, 4);
    System.out.println(checkCode);
}

検証コードを生成すると、次のことがわかります。

  • 検証コードはJavaコードを使用して生成されたイメージです
  • 検証コードの機能: マシンがサーバーを自動的に登録して攻撃するのを防ぎます。
  1. プロセス分析の実施

ここに画像の説明を挿入します
(1) フロントエンドが CheckCodeServlet にリクエストを送信します。

(2) CheckCodeServlet がリクエストを受信すると、検証コード イメージを生成し、Response オブジェクトの出力ストリームを使用してそのイメージをフロント エンドに書き戻します。

考え中: 画像をフロントエンド ブラウザーに書き戻すにはどうすればよいでしょうか?

(1) Java には検証コードイメージを生成するツールクラスが既に存在しており、テストクラスではディスクにイメージを生成するだけ (
2) ディスクを生成する処理を利用するOutputStream流このイメージをサーバー上で生成する方法( 3) 以前は、オブジェクトを
書き込むときに、そのバイト出力ストリームを取得するメソッドがありました (4) 要約すると、ディスクに書き込まれるストリーム オブジェクトをバイト ストリームに変更して、ページへのイメージ応答を完了できます。フロントエンド。ReponsegetOutputStream()
Response

  1. 実装

(1)Register.jspページを変更し、背景から認証コード画像を取得します。

           <tr>
                <td>验证码</td>
                <td class="inputs">
                    <input name="checkCode" type="text" id="checkCode">
                    <img id="checkCodeImg" src="/brand-demo/checkCodeServlet">
                    <a href="#" id="changeImg">看不清?</a>
                </td>
            </tr>

            <script>
                document.getElementById("changeImg").onclick = function () {
                    //路径后面添加时间戳的目的是避免浏览器进行缓存静态资源
                    document.getElementById("checkCodeImg").src = "/brand-demo/checkCodeServlet?"+new Date().getMilliseconds();
                }
            </script>

(2) リクエストを受信して​​検証コードを生成する CheckCodeServlet クラスを記述する

package com.itheima.web;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 生成验证码
        ServletOutputStream os = response.getOutputStream();
        String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);
         // 存入Session
        HttpSession session = request.getSession();
        session.setAttribute("checkCodeGen",checkCode);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

看不清コードを実行します。クリックすると画像が変更されることがわかります。
ここに画像の説明を挿入します

7. 検証コード - 検証

  1. 必要
  • プログラムによって生成された認証コードが、ユーザーが入力した認証コードと同じであるかどうかを確認し、一致しない場合は登録がブロックされます。

  • 登録フォームにアクセスして送信するための認証コードの画像は、二度したがって、プログラムによって生成された検証コードはセッションに保存する必要があります。
    ここに画像の説明を挿入します
    考えてみると、なぜ検証コード データをセッションに保存する必要があるのでしょうか。

  • 検証コードの生成と検証コードの検証は 2 つのリクエストであり、セッション内の 2 つのリクエスト間でデータを共有する必要があります。

  • 検証コードはセキュリティ データ カテゴリに属しているため、検証コード データを保存するために [セッション] を選択します。

  1. プロセス分析の実施

ここに画像の説明を挿入します
(1) CheckCodeServletで検証コードを生成する際、Sessionオブジェクトに検証コードのデータを格納する

(2) フロントエンドは検証コードと登録データをバックグラウンドに送信し、RegisterServlet クラスに渡します。

(3) RegisterServlet クラスがリクエストとデータを受信すると、その中に検証コードが含まれており、セッション内の検証コードと比較されます。

(4) 一致していれば登録は完了ですが、一致していなければエラーメッセージが表示されます。

  1. 実装

(1)CheckCodeServletクラスを変更し、Sessionオブジェクトに検証コードを格納する

package com.itheima.web;

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 生成验证码
        ServletOutputStream os = response.getOutputStream();
        String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4);

        // 存入Session
        HttpSession session = request.getSession();
        session.setAttribute("checkCodeGen",checkCode);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

(2) でRegisterServletsessionページとオブジェクトの認証コードを取得し、比較します。

package com.itheima.web;

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    
    
    private UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //1. 获取用户名和密码数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        // 获取用户输入的验证码
        String checkCode = request.getParameter("checkCode");

        // 程序生成的验证码,从Session获取
        HttpSession session = request.getSession();
        String checkCodeGen = (String) session.getAttribute("checkCodeGen");

        // 比对,忽略大小写
        if(!checkCodeGen.equalsIgnoreCase(checkCode)){
    
    

            request.setAttribute("register_msg","验证码错误");
            //跳转
            request.getRequestDispatcher("/register.jsp").forward(request,response);

            // 不允许注册
            return;
        }

        //2. 调用service 注册
        boolean flag = service.register(user);
        //3. 判断注册成功与否
        if(!flag){
    
    
            //注册功能,跳转登陆页面
            request.setAttribute("register_msg","注册成功,请登录");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }else {
    
    
            //注册失败,跳转到注册页面

            request.setAttribute("register_msg","用户名已存在");
            request.getRequestDispatcher("/register.jsp").forward(request,response);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

プログラムを実行します。http://localhost:8080/brand-demo/login.jsp
認証コードを間違って入力した場合:
ここに画像の説明を挿入します
認証コードを正しく入力した場合:
ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/weixin_52223770/article/details/127672324