CodeGym/Java Blog/Toto sisi/使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)
John Squirrels
等級 41
San Francisco

使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)

在 Toto sisi 群組發布
個成員
使用 servlet 和 JSP 創建一個簡單的 Web 應用程序(第 1 部分) 理解本文所需的知識:您已經或多或少地了解了 Java Core,並希望了解 JavaEE 技術和 Web 編程。對您來說,目前正在研究 Java Collections 任務是最有意義的,它處理的主題與本文很接近。
使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)- 1

創建實體

entities包中,我們將創建一個User具有兩個私有字符串變量的類:namepassword。創建構造函數(默認構造函數和接受兩個值的構造函數)和 getter/setter,並重寫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;
    }
}
現在我們可以開始創建用戶列表了。我們將向其中添加用戶,並從中獲取用戶以顯示它們。但是,我們確實有一個問題。我們不創建我們的 servlet 對象。Tomcat為我們做了這件事。我們在其中重寫的方法已經為我們定義好了,我們不能傳參。那麼我們如何創建一個在我們的兩個 servlet 中都可見的共享列表呢?如果我們只是在每個 servlet 中創建一個列表對象,那麼我們會將用戶添加到一個列表中,但會在 ListServlet 中顯示另一個列表中的用戶. 所以我們需要一個由兩個 servlet 共享的對象。一般來說,我們需要一個由我們程序中的所有類共享的對象:一個對像用於整個程序。我希望你聽說過一些關於設計模式的事情。對於某些人來說,這可能是他們程序中第一次真正需要單例模式。您可以瘋狂地製作一些帶有雙重檢查和同步的甜蜜單例(是的,我們的應用程序是多線程的,因為 Tomcat servlet 在單獨的線程上運行)。但我將使用早期初始化技術,因為它完全可以滿足我們的目的。

創建模型

在模型包中創建一個類(並實現單例模式)並將其命名為不尋常的東西。例如,模型。我們將在我們的類中創建一個私有用戶列表,並實現兩個方法:一個添加用戶,另一個返回字符串列表(用戶名)。由於我們的用戶對象包含用戶名和密碼,並且我們不想洩露用戶密碼,因此我們只有一個名稱列表。
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中獲取一些數據,對其進行處理,並將其傳遞給模型)。您在其中定義您的業務邏輯(程序應該做什麼),而不是在模型或視圖中。因此,每個部分處理自己的業務:
  • 模型存儲數據;
  • 視圖呈現數據的漂亮表示;
  • 控制器處理數據處理。
這允許程序非常簡單和可維護,而不是一個類中所有代碼的巨大堆。 MVC不僅適用於 Web 編程,而且在該領域中使用得特別頻繁(幾乎總是如此)。在我們的例子中,servlet 將充當控制器。這是對模式的非常膚淺和簡短的描述,但MVC不是本文的主題。如果有人想了解更多,谷歌是你的朋友! 創建用於添加用戶的表單。 將表單添加到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>
這裡的表單有一個method屬性,其值為post這表示此表單中的數據將作為POST 請求發送到服務器。未指定action屬性,這意味著請求將發送到我們訪問此頁面的相同地址 ( / add )。因此,在收到GET 請求後,綁定到該地址的 servlet 會返回帶有添加用戶表單的JSP 。如果它收到一個POST 請求,那麼我們就知道表單在這裡發送了它的數據(我們從doPost()方法、過程,並傳遞給模型進行保存)。值得注意的是,輸入字段有一個名為name的參數(用於用戶名,或pass用於密碼)。這是非常重要的一點。因此,要從請求(在 servlet 內)接收此數據(將輸入的用戶名和密碼),我們將使用這些名稱傳遞字段。但稍後會詳細介紹。我用於發送數據的按鈕再次被製作為按鈕而不是通常的輸出字段。我不知道這種方法的採用有多廣泛,但它適用於我(Chrome 瀏覽器)。

POST 請求的 Servlet 處理

讓我們回到AddServlet。我提醒您,為了讓我們的 servlet 能夠“捕獲” GET 請求,我們覆蓋了HttpServletdoGet()類中的方法。為了讓我們的 servlet 也能捕獲POST 請求,我們還必須覆蓋該方法。Tomcat向它傳遞我們將使用的類似請求和響應對象。首先,提取請求的名稱並傳遞表單發送的參數(如果您在表單中指定了不同的名稱,則使用這些名稱)。之後,使用接收到的數據創建一個用戶對象。然後我們獲取模型對象並將創建的用戶添加到模型中。 doPost()
@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收到的請求對象。我們可以給這個對象添加一個屬性,給它起一個名字。其實我們可以把我們要傳遞的對象添加到視圖. 由於在將控制從 servlet 轉移到視圖時,我們向視圖傳遞了與 servlet 接收到的相同的請求和響應對象,因此我們可以將名稱列表添加到請求對象,然後從請求中獲取用戶名列表視圖中的對象。我們已經完成了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將控制權轉移給它時執行。此外,我們已經從 servlet 中的模型準備了用戶名列表,並將其傳遞到請求對像中。由於我們有姓名列表,我們可以使用循環對其進行迭代for並顯示每個姓名。正如我之前所說,JSP 文件可以執行Java 代碼(這就是它們與靜態 HTML 頁面的不同之處)。要執行一些代碼,我們需要做的就是將以下結構放在適當的位置:
<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
在這個結構中,我們可以訪問幾個變量:
  • request — 我們的請求對象,我們從 servlet 傳遞過來的,它被簡稱為req
  • response — 響應對象(在 servlet 中稱為resp );
  • out — 一個JspWriter對象(它繼承了一個普通的Writer),我們可以使用它來將某些內容直接“寫入”到HTML 頁面本身。語句out.println("Hello, World!")與System.out.println("Hello, World!")非常相似,但不要混淆它們!
  • out.println() “寫入”到HTML 頁面,而System.out.println寫入系統輸出流。如果您使用Java 代碼JSP部分中調用System.out.println() ,您將在Tomcat控制台中看到結果,而不是在頁面上。
您可以在此處查找 JSP 中可用的其他對象。我們可以使用request對象獲取從 servlet 傳遞的名稱列表(我們將相應的屬性附加到該對象),然後使用 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>");
%>
現在我們知道如何將數據從 servlet 傳遞到視圖,我們可以改進我們的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;
  • 內容的 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 應用程序。現在我們只需要讓它漂亮...... :) 使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)- 2

添加樣式。我們將使用 W3.CSS 框架

目前,我們的應用程序可以運行,但它看起來絕對離譜。因此,讓我們添加背景、為文本和按鈕著色、為列表添加樣式、對齊元素、添加縮進等等。手動編寫樣式會花費大量時間並耗費我們的精力。所以我建議使用W3.CSS框架。它已經有帶有樣式的現成類。我們只需要將要使用的 CSS 類安排在正確的位置即可。要將它們添加到我們的頁面,我們首先連接樣式文件。有兩種方法可以做到這一點:
  1. 瀏覽我們的頁面並在標題部分插入以下樣式文件的直接鏈接

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

    如果您有永久的 Internet 連接,則此選項適用。當您在本地服務器上打開您的頁面時,樣式將從 Internet 中提取。

  2. 但是如果你想在本地擁有所有樣式而不依賴於 Internet 連接,請下載樣式文件並將其放在 web文件夾中的某個位置(例如web/styles/w3.css)。然後瀏覽我們所有的頁面(index.html、add.jsp、list.jsp)並將以下鏈接添加到head部分內的樣式文件:

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

    之後,只需瀏覽標籤並添加您喜歡的樣式即可。這個我就不詳細說了。相反,我將只提供三個帶有光柵樣式類的文件的即用型版本。

索引.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>
添加.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>
就是這樣。:) 如果您還有任何問題或意見,或者有什麼不對,請發表評論。我將附上幾張截圖,說明結果如何。
使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)- 3
使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)- 4
使用 servlet 和 JSP 創建簡單的 Web 應用程序(第 2 部分)- 5
最後,如果你想練習這個項目,你可以嘗試以下方法:
  • 製作一個 servlet 和 JSP 來刪除用戶,並添加另一對來編輯現有用戶。結果將是使用 servlet 構建的真正的 CRUD Web 應用程序。;)
  • 將List替換為數據庫,這樣添加的用戶不會在服務器重啟後消失。:)
祝你好運!
留言
  • 受歡迎
你必須登入才能留言
此頁面尚無留言