JavaRush /Java Blog /Random-JA /サーブレットと JSP を使用した簡単な Web アプリケーションの作成 (パート 2)
Стас Пасинков
レベル 26
Киев

サーブレットと JSP を使用した簡単な Web アプリケーションの作成 (パート 2)

Random-JA グループに公開済み
サーブレットと JSP を使用した単純な Web アプリケーションの作成 (パート 1) 記事を理解するために必要な知識レベル:あなたはすでに Java Core をある程度理解しており、JavaEE テクノロジと Web プログラミングについて学びたいと考えています。これは、記事に近いトピックをカバーする Java Collections クエストを現在学習している場合に最も意味があります。
サーブレットと JSP を使用した簡単な Web アプリケーションの作成 (パート 2) - 1

エンティティの作成

エンティティパッケージでは、クラスUserを作成し、その中に 2 つのプライベート文字列変数namepasswordが存在します。コンストラクター (デフォルトと両方の値を受け入れるコンストラクター)、ゲッター/セッターを作成し、念のためtoString()メソッドと、 equals() メソッドhashCode()メソッドをオーバーライドしましょう。つまり、まともな Java 開発者がクラスを作成するときに行うことをすべて行います。
public class User {
    private String name;
    private String password;

    public User() {
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (name != null ? !name.equals(user.name) : user.name != null) return false;
        return password != null ? password.equals(user.password) : user.password == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (password != null ? password.hashCode() : 0);
        return result;
    }
}
これで、ユーザーのリストの作成を開始できます。ユーザーをそこに追加し、そこからユーザーを表示用に取得します。ただし、問題が 1 つあります。私たちがサーブレット オブジェクトを作成するのではなく、Tomcat が自動的に作成します。それらでオーバーライドするメソッドもすでに定義されており、パラメーターを追加することはできません。では、両方のサーブレットに表示される共有リストを作成するにはどうすればよいでしょうか? 各サーブレットに独自のリスト オブジェクトを作成するだけであれば、ユーザーを 1 つのリストに追加し、 ListServletサーブレットを使用しているユーザーのリストを別のリストに表示することがわかります。両方のサーブレットに共通のオブジェクトが必要であることがわかりました。一般的に言えば、プログラム内のすべてのクラスに共通のオブジェクトが必要です。プログラム全体の唯一のオブジェクトです。デザインパターンについて聞いたことがあると思います。そして、おそらく、これがプログラムでシングルトンパターンを使用する初めての実際のニーズである人もいるでしょう。ひねくれて、二重チェックと同期を使用してクールなシングルトンを作成することもできます (はい、Tomcat はサーブレットを別のスレッドで実行するため、マルチスレッド アプリケーションがあります)。ただし、ここでは非常に適切であるため、早期初期化を伴うオプションを使用します。十分だし、私たちの目的にも合っています。

モデルの作成

モデルパッケージ内にクラスを作成し (そしてその中にSingletonパターンを実装し) 、それを何か珍しい名前にしてみましょう。Modelとしましょう。クラス内にプライベート ユーザー リスト オブジェクトを作成し、2 つのメソッドを実装しましょう。1 つはユーザーを追加するためのもので、もう 1 つは文字列 (ユーザー名) のリストを返すためのものです。ユーザー オブジェクトは名前とパスワードで構成されており、ユーザー パスワードを「公開」したくないため、名前のリストのみを用意します。
public class Model {
    private static Model instance = new Model();

    private List<User> model;

    public static Model getInstance() {
        return instance;
    }

    private Model() {
        model = new ArrayList<>();
    }

    public void add(User user) {
        model.add(user);
    }

    public List<String> list() {
        return model.stream()
                .map(User::getName)
                .collect(Collectors.toList());
    }
}

MVC について少し

singletonについて聞いたことがあるなら、おそらく別の設計パターンであるMVC (モデル ビュー コントローラー、ロシア語ではモデル ビュー コントローラー、または英語ではモデル ビュー コントローラー)について聞いたことがあるでしょう。その本質は、ビジネス ロジックをプレゼンテーションから分離することです。つまり、何を行うかを決定するコードと、表示方法を決定するコードを分離します。ビュー(ビュー、または単にビュー) は、一部のデータが表示される形式を担当します。この場合、ビューは JSP ページです。そのため、それらをviewsというフォルダーに配置しました。 モデルは、プログラムが動作する実際のデータです。この場合、これらはユーザー (ユーザーのリスト) です。そうですね、コントローラーはそれらの間の接続リンクです。モデルからデータを取得してビューに渡します (または Tomcat からデータを受け取り、それを処理してモデルに渡します)。ビジネス ロジック (プログラムが正確に何をすべきか) は、モデルやビューではなく、それらの中で記述する必要があります。したがって、誰もが自分のことを行います。
  • モデルはデータを保存します。
  • ビューはデータの美しい表現を描画します。
  • コントローラーはデータ処理を処理します。
これにより、1 つのクラス内のすべてのコードの巨大なダンプではなく、プログラムがかなりシンプルで保守しやすくなります。 MVCは Web プログラミングに適しているだけではありませんが、特に頻繁に (ほぼ常に) 使用されるのはこの分野です。この例では、サーブレットがコントローラーとして機能します。これはパターンの非常に表面的で簡単な説明ですが、MVCはこの記事の主なトピックではありません。さらに詳しく知りたい人は、Google で助けてください。ユーザーを追加するためのフォームを作成する2 つのテキスト入力フィールド (1 つは通常のフィールド、もう 1 つはパスワード) とサーバーにデータを送信するためのボタンで構成されるフォームをadd.jspファイルに追加しましょう。
<form method="post">
    <label>Name:
        <input type="text" name="name"><br />
    </label>

    <label>Password:
        <input type="password" name="pass"><br />
    </label>
    <button type="submit">Submit</button>
</form>
ここで、フォームには値postを持つメソッド属性があります。これは、このフォームからのデータが POST リクエストの形式でサーバーに送信されることを意味します。action属性は指定されていません。これは、このページにアクセスしたときと同じアドレス ( /add )にリクエストが送信されることを意味します。したがって、このアドレスにバインドされたサーブレットは、GET リクエストを受信すると、ユーザーを追加するためのフォームを含むこの JSP を返します。POST リクエストを受信すると、フォームがデータをそこに送信したことを意味します (データは、 doPost() 入力フィールドにはnameパラメーターがあることに注意してください(名前のあるフィールドの場合は値 name があり、パスワードのあるフィールドの場合は値passがあります)。これはかなり重要な点です。このデータ (入力される名前とパスワード) をリクエスト (既にサーブレット内にある) から取得するには、これらの名前passを正確に使用します。しかし、それについては後で詳しく説明します。データを送信するためのボタン自体も、通常の出力フィールドとしてではなく、buttonの形式で作成されます。このオプションがどの程度普遍的であるかはわかりませんが、私 (Chrome ブラウザー) では機能します。

サーブレットを使用した POST リクエストの処理

AddServletサーブレットに戻りましょう。思い出してもらいたいのですが、サーブレットが GET リクエストを「キャッチ」できるようにするために、HttpServletクラスのdoGet()メソッドをオーバーライドしました。POST リクエストもキャッチするようにサーブレットに教えるには、doPost()メソッドをオーバーライドする必要もあります。これは、 Tomcatから同様の要求オブジェクトと応答オブジェクトを受け取ります。これを使用します。まず、リクエストから名前を抽出し、フォームが送信したパラメーターを渡します (フォーム内で別の名前を付けた場合は、それらの名前を記述します)。この後、受信したデータを使用してユーザー オブジェクトを作成します。次に、モデル オブジェクトを取得し、作成したユーザーをモデルに追加します。
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    String password = req.getParameter("pass");
    User user = new User(name, password);
    Model model = Model.getInstance();
    model.add(user);
}

ビューにデータを渡す

ListServletサーブレットに進みましょう。doGet()メソッドはここですでに実装されており、制御をlist.jspビューに移すだけです。これをまだ行っていない場合は、AddServletサーブレットの同じメソッドと同様に実行してください。ここで、モデルからユーザー名のリストを取得してビューに渡すと、それが受け取られて適切に表示されます。これを行うには、 Tomcatから受け取ったリクエスト オブジェクトを再度使用します。このオブジェクトに属性を追加して名前を付け、実際にはviewに転送したいオブジェクト自体を追加することができます。実行プロセスをサーブレットからビューに転送するときに、サーブレット自体が受信したのと同じリクエスト オブジェクトとレスポンス オブジェクトを渡します。その後、名前のリストをリクエスト オブジェクトに追加することで、このリクエストから次のことが可能になります。ビュー内のオブジェクトでユーザー名のリストを作成し、取得します。ListServletクラスの作成は完了したので、クラス全体のコードを次に示します。
package app.servlets;

import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class ListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Model model = Model.getInstance();
        List<String> names = model.list();
        req.setAttribute("userNames", names);

        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp");
        requestDispatcher.forward(req, resp);
    }
}

jspファイル内のJavaコードを実行する

list.jspファイルの作業を開始します。ListServlet がここで実行プロセスを渡す場合にのみ実行されます。さらに、そのサーブレットでは、モデルからユーザー名のリストをすでに準備しており、それをリクエスト オブジェクトで渡しています。名前のリストがあるので、それをループしそれぞれの名前を出力できます。すでに述べたように、jsp ファイルは Java コードを実行できます (これが静的 HTML ページとの違いです)。コードを実行するには、必要な場所に次の構造を配置するだけで十分です。
<!-- html code -->
<%
    // java code
%>
<!-- html code -->
この構造内では、いくつかの変数にアクセスできます。
  • request はサーブレットから渡したリクエストオブジェクトで、単にreqと呼ばれています。
  • responce -サーブレット内でrespと呼ばれる応答オブジェクト。
  • outはJspWriterタイプのオブジェクト(通常のWriterから継承) で、これを使用すると、HTML ページ自体に直接何かを「書き込む」ことができます。out.println("Hello world!")エントリはSystem.out.println("Hello world!")エントリと非常に似ていますが、この 2 つを混同しないでください。
    out.println() はHTML ページに「書き込み」、System.out.println はシステム出力に書き込みます。Java コードを含むセクション内でjsp メソッド System.out.println()を呼び出すと、結果はページではなくTomcatコンソールに表示されます。

ここで、 jsp 内の他の利用可能なオブジェクトを探すことができます。requestオブジェクトを使用すると、サーブレットから渡された名前のリストを取得でき (対応する属性をこのオブジェクトに付加しました)、outオブジェクトを使用すると、これらの名前を表示できます。これを実行しましょう (今のところは HTML リストの形式だけです):
<ul>
    <%
        List<String> names = (List<String>) request.getAttribute("userNames");

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
ユーザーがいる場合にのみリストを表示し、それ以外の場合はまだユーザーがいないという警告を表示する必要がある場合は、このセクションを少し書き直すことができます。
<%
    List<String> names = (List<String>) request.getAttribute("userNames");

    if (names != null && !names.isEmpty()) {
        out.println("<ui>");
        for (String s : names) {
            out.println("<li>" + s + "</li>");
        }
        out.println("</ui>");
    } else out.println("<p>There are no users yet!</p>");
%>
サーブレットからビューにデータを渡すことができるようになったので、ユーザーが正常に追加されたときに通知が表示されるように、AddServlet を少し改善できます。これを行うには、新しいユーザーをモデルに追加した後、doPost()メソッドでこのユーザーの名前をreqオブジェクトの属性に追加し、制御をadd.jspビューに戻すことができます。そして、その中には、そのような属性がリクエスト内にあるかどうかをチェックする Java コードを含むセクションがすでに作成されており、存在する場合は、ユーザーが正常に追加されたことを示すメッセージを出力します。これらの変更後、完全なAddServletサーブレット コードは次のようになります。
package app.servlets;

import app.entities.User;
import app.model.Model;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
        requestDispatcher.forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String password = req.getParameter("pass");
        User user = new User(name, password);
        Model model = Model.getInstance();
        model.add(user);

        req.setAttribute("userName", name);
        doGet(req, resp);
    }
}
ここでは、 doPost()メソッド の最後に、モデルに追加されたユーザーの名前を持つ属性を設定し、その後doGet()メソッドを呼び出して、現在のリクエストとレスポンスを渡します。また、doGet()メソッドはすでに制御をビューに渡しており、追加されたユーザーの名前が属性として付加されたリクエスト オブジェクトを送信します。残っているのは、そのような属性が存在する場合にそのような通知を表示するようにadd.jspを修正することだけです。最終的なadd.jsp は次のとおりです
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<p>User '" + request.getAttribute("userName") + "' added!</p>");
                }
            %>
            <div>
                <div>
                    <h2>Add user</h2>
                </div>

                <form method="post">
                    <label>Name:
                        <input type="text" name="name"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass"><br />
                    </label>
                    <button type="submit">Submit</button>
                </form>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
ページの本文は次のもので構成されます。
  • ヘッダー付きの div-a。
  • コンテンツの div コンテナーでは、ユーザー名を持つ属性が存在するかどうかがチェックされます。
  • div にはユーザーを追加するためのフォームが含まれます。
  • 最後にはメインページに戻るボタンを備えたフッターがあります。
div が多すぎるように思えるかもしれませんが、後でスタイルを追加するときに使用します。最終的なlist.jsp は次のとおりです。
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users</title>
    </head>

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <div>
                <div>
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ui>");
                        for (String s : names) {
                            out.println("<li>" + s + "</li>");
                        }
                        out.println("</ui>");
                    } else out.println("<p>There are no users yet!</p>");
                %>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
これにより、ユーザーを保存および追加したり、ユーザー名のリストを表示したりできる、完全に機能する Web アプリケーションが完成しました。残っているのはそれを装飾することだけです...:)

スタイルを追加します。W3.CSS フレームワークを使用します

現時点ではアプリケーションは動作していますが、完全にクレイジーです。したがって、背景、テキストとボタンの色、スタイルリストを追加し、配置を行い、インデントを追加するなどします。スタイルを手動で記述する場合、多くの時間と神経が必要になることがあります。したがって、W3.CSS CSS フレームワークを使用することをお勧めします。スタイルを備えた既製のクラスがすでに用意されているため、あとは適用する CSS クラスを適切な場所に配置するだけです。これらをページに追加するには、まずスタイルを含むファイルをインクルードします。これは次の 2 つの方法で実行できます。
  1. ページにアクセスし、head セクションにスタイルを含むファイルへの直接リンクを挿入します。

    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

    このオプションは、インターネットに常時接続している場合に適しています。その後、ローカル サーバーでページを開くと、スタイルがインターネットから取得されます。


  2. すべてのスタイルをローカルに置き、インターネット接続に依存しないようにしたい場合は、スタイルを含むファイルをダウンロードし、Webフォルダー(たとえば、web/styles/w3.css ) 内のどこかに配置して、すべてのスタイルを実行します。ページ ( index.html、add.jsp、list.jsp ) を選択し、headセクション内にスタイルを含むこのファイルへのリンクを入力します。

    <link rel="stylesheet" href="styles/w3.css">

    その後、タグを調べて、好きなスタイルを追加するだけです。これについては詳しく説明しませんが、スタイル クラスをアレンジした 3 つのファイルの既製バージョンをすぐに提供します。

インデックス.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Super app!</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center">
            <div class="w3-bar w3-padding-large w3-padding-24">
                <button class="w3-btn w3-hover-light-blue w3-round-large" onclick="location.href='/list'">List users</button>
                <button class="w3-btn w3-hover-green w3-round-large" onclick="location.href='/add'">Add user</button>
            </div>
        </div>
    </body>
</html>

add.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-padding">
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<div class=\"w3-panel w3-green w3-display-container w3-card-4 w3-round\">\n" +
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-green w3-border w3-border-green w3-hover-border-grey\">×</span>\n" +
                            "   <h5>User '" + request.getAttribute("userName") + "' added!</h5>\n" +
                            "</div>");
                }
            %>
            <div class="w3-card-4">
                <div class="w3-container w3-center w3-green">
                    <h2>Add user</h2>
                </div>
                <form method="post" class="w3-selection w3-light-grey w3-padding">
                    <label>Name:
                        <input type="text" name="name" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <button type="submit" class="w3-btn w3-green w3-round-large w3-margin-bottom">Submit</button>
                </form>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>

リスト.jsp

<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users list</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center w3-margin-bottom w3-padding">
            <div class="w3-card-4">
                <div class="w3-container w3-light-blue">
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ul class=\"w3-ul\">");
                        for (String s : names) {
                            out.println("<li class=\"w3-hover-sand\">" + s + "</li>");
                        }
                        out.println("</ul>");

                    } else out.println("<div class=\"w3-panel w3-red w3-display-container w3-card-4 w3-round\">\n"
+
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-red w3-border w3-border-red w3-hover-border-grey\">×</span>\n" +
                            "   <h5>There are no users yet!</h5>\n" +
                            "</div>");
                %>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
以上です:) まだ質問がある場合、またはコメントがある場合、または逆に、何かがうまくいかない場合は、コメントを残してください。UPD: すべてが正しく行われたにもかかわらず、ボタンをクリックしたときに 404 エラーの問題が発生する場合は、アイデアの展開構成を修正する必要があるかもしれません。これを行うには、[設定の編集] (スタート ボタンの近くの上部) に移動し、ウィンドウの右側にある [展開] タブに移動し、アプリケーション コンテキストでそれが単に示されていることを確認する必要があります。この結果得られたもののスクリーンショットをいくつか添付します。
サーブレットと JSP を使用した簡単な Web アプリケーションの作成 (パート 2) - 2
サーブレットと JSP を使用した簡単な Web アプリケーションの作成 (パート 2) - 3
サーブレットと JSP を使用した簡単な Web アプリケーションの作成 (パート 2) - 4
最後に 、このプロジェクトで練習したい場合は、次のことを試してみてください。
  • ユーザーを削除するためのサーブレットと JSP を作成し、既存のユーザーを変更/編集するためにさらにいくつかを作成します。本物の CrUD Web アプリケーションが得られます:) サーブレット上));
  • サーバーの再起動後に追加されたユーザーが消えないように、リスト (List) をデータベースの操作に置き換えます:)
幸運を!
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION