JavaRush /Java Blog /Random-TW /使用 servlet 和 jsp 建立簡單的 Web 應用程式(第 2 部分)
fatfaggy
等級 26
Киев

使用 servlet 和 jsp 建立簡單的 Web 應用程式(第 2 部分)

在 Random-TW 群組發布
我繼續描述使用 servlet、jsp、Maven 和 Tomcat 建立 Web 應用程式的過程。如有必要,請在文章開頭。
我們建立實體。
讓我們在entities包中建立一個User類,在其中我們將建立兩個私有字串變數name和password。讓我們建立建構函式(預設的和接受兩個值的建構子)、getters/setters、重寫 toString() 方法(以防萬一)以及 equals() 和 hashCode() 方法。 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 顯示用戶列表將完全不同。事實證明,我們需要一個兩個 servlet 共用的物件。一般來說,我們需要一個對程式中所有類別都通用的物件;整個程序的唯一對象。我希望您聽說過一些有關設計模式的知識。也許對於某些人來說,這是在他們的程式中使用 Singleton模板的第一個真正需求。您可以發揮創意並製作一些很酷的單例,透過雙重檢查和同步(是的,我們有一個多線程應用程序,因為Tomcat 在不同的線程中運行servlet),但我將使用早期初始化的選項,因為在這種情況下相當合適。
創建模型。
然後我們將在模型包中建立一個類別(並在其中實作單例模板),我們也稱之為「模型」。讓我們在其中建立一個私人用戶列表對象,並創建兩個方法:第一個用於添加用戶,第二個 - 讓它簡單地返回字串(用戶名)列表。由於我們的使用者物件由名稱和密碼組成,因此我們不想「洩漏」使用者密碼,因此我們只會傳回其名稱清單。 public class Model { private static Model instance = new Model(); private List model; public static Model getInstance() { return instance; } private Model() { model = new ArrayList<>(); } public void add(User user) { model.add(user); } public List list() { return model.stream() .map(User::getName) .collect(Collectors.toList()); } }
關於 mvc 的一些知識。
既然您聽說過單例,這意味著您可能聽說過另一種設計模式- MVC(模型-視圖-控制器,或俄語中的模型-視圖-控制器,或者就像英語中的模型-視圖-控制器)。其本質是將業務邏輯與表示分開。也就是說,將決定 要做什麼的程式碼與決定 如何顯示的程式碼分開。視圖(視圖或只是視圖)負責呈現某些資料的形式。在我們的例子中,視圖是我們的 JSP 頁面。這就是為什麼我將它們放在一個名為“views”的資料夾中。模型是程式運行時使用的實際數據。在我們的例子中,這些是用戶(用戶列表)。那麼,控制器就是它們之間的連接紐帶。他們從模型中獲取數據並將其傳輸到視圖,或從 Tomcat 接收一些數據,對其進行處理並將其傳輸到模型。業務邏輯(即 做什麼)應該在其中描述,而不是在模型或視圖中。於是,每個人都做自己的事:
  • 模型儲存數據
  • 視圖繪製出美麗的資料表示
  • 控制器處理數據
這使得它們都相當簡單且可維護。而不是一個類別中所有程式碼的巨大轉儲。MVC 不僅適用於 Web 編程,而且在該領域仍然很常見(如果不是總是)。在我們的例子中,Servlet 將充當控制器。是的,這是對該模式的非常膚淺甚至粗略的描述,但本文不是關於設計模式,而是關於如何製作一個簡單的 Web 應用程式:) 誰想了解更多 - Google 知道一切!:) 讓我們回到我們的觀點。
建立用於新增使用者的表單。
讓我們在 add.jsp 檔案中新增一個表單,其中包含兩個文字輸入(一個是常規輸入,另一個是密碼類型)和一個用於將資料傳送到伺服器的按鈕。 這裡的表單有一個值為 post 的 method 屬性。這意味著該表單中的資料將以 POST 請求的形式傳送到伺服器。未指定操作屬性,這表示該請求將發送到我們訪問該頁面的相同地址(/add)。因此,綁定到該位址的 servlet 在收到 GET 請求後,會傳回帶有新增使用者表單的 jsp,如果它收到 POST 請求,則該表單已將其資料傳送到那裡(我們將提取該資料)從doPost() 方法中的request 對象,對其進行處理並將其傳輸到模型進行保存)。值得注意的是,輸入在這裡有一個名稱參數(對於具有名稱的字段,它具有值 name,對於具有密碼的字段,它具有值 pass)。這是非常重要的一點。因為為了從請求(已經在 servlet 內部)獲取這些資料(將輸入的名稱和密碼),我們將準確地使用這些名稱和傳遞。但稍後會詳細介紹。用於發送資料的按鈕本身再次以按鈕的形式製成,而不是通常習慣的輸入形式。我不知道這個選項有多通用,但它在 Chrome 中對我有用:)
使用 servlet 處理 POST 請求。
讓我們回到 AddServlet servlet。我們已經知道,為了讓 servlet 能夠「捕獲」GET 請求,我們重寫了 HttpServlet 類別中的 doGet() 方法。為了教導我們的 servlet 也捕捉 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 servlet。我們已經實作了 doGet() 方法,它只是將控制權轉移到 list.jsp 視圖。如果您還沒有,請使用 AddServlet servlet 中的相同方法進行類別推。現在,最好從模型中獲取使用者名稱列表並將它們傳遞給視圖,視圖將在那裡接收它們並很好地顯示它們。為此,我們將再次使用從 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 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 頁面的不同之處)。為了執行一些程式碼,在我們需要的地方放置一個構造就足夠了。 <% // java 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「寫入」系統輸出。如果您在包含jsp 程式碼的部分中呼叫System.out.println() 方法,您將在Tomcat 控制台中看到結果,而不是像您希望的那樣在頁面上看到結果:) 您可以在jsp 中找到其他可用對象 這裡。使用 request 對象,我們可以獲得從 servlet 傳遞的名稱列表(我們將相應的屬性附加到該對象),並使用 out 對象,我們可以顯示這些名稱。現在讓我們簡單地以 html 列表的形式執行此操作: 如果我們只想在有用戶時顯示列表,否則顯示還沒有用戶的警告,我們可以稍微重寫此部分: 現在我們知道如何將資料從servlet 傳輸到視圖- 我們可以稍微改進AddServlet,以便顯示成功新增使用者的通知。為此,在 doPost() 方法中,將新使用者新增至模型後,我們可以將該使用者的名稱新增至 req 物件的屬性中,並將控制權傳回 add.jsp 視圖。並且在其中已經用Java程式碼建立了一個部分,您可以在其中檢查請求中是否存在這樣的屬性,如果是,則顯示一則訊息,表示使用者已成功新增。經過這些變更後,AddServlet servlet 的完整程式碼將如下所示: 這裡,在 doPost() 方法的末尾,我們設定一個屬性,其中包含新增到模型中的使用者名稱,然後呼叫 doGet( ) 方法,我們將目前請求和回應傳遞給該方法。doGet() 方法已將控制權轉移到視圖,並在其中傳送一個請求對象,其中新增的使用者名稱會作為屬性附加。仍需要修正 add.jsp 本身,以便在存在此類屬性時顯示此類通知。最終添加.jsp
    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { for (String s : names) { out.println("
  • " + s + "
  • "); } } %>
<% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    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); } } <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("

    User '" + request.getAttribute("userName") + "' added!

    "); } %>

    Add user

    頁面的主體由一個帶有標題的 div 組成,後面是一個內容容器,檢查其中是否存在帶有用戶名的屬性,然後是一個帶有用於添加用戶的表單的 div,最後是一個帶有按鈕返回主頁。看起來好像 div 太多了,但我們稍後在添加樣式時會用到它們:) 好吧,最終版本是 list.jsp。這樣, 我們就有了一個完全可以工作的Web 應用程序,它還可以儲存和新增使用者顯示他們的名字清單。剩下的就是修飾它......:) <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    新增樣式。我們使用W3.CSS框架。
    目前,我們的應用程式正在運行,但絕對瘋狂:)我們需要添加背景、文字和按鈕的顏色、風格化列表、進行對齊、添加縮進,一般來說有很多事情。如果您手動編寫樣式,可能會花費大量時間和精力。因此,我建議使用 CSS 框架 W3.CSS。它已經有了帶有樣式的現成類別;剩下的就是將我們想要應用到這些位置的 CSS 類別放置在正確的位置。為了將它們添加到我們的頁面中,首先我們需要包含一個帶有樣式的文件。這可以透過兩種方式完成: 1. 瀏覽我們的頁面,並在標題部分插入帶有樣式的文件的直接連結。 如果您有穩定的互聯網連接,則此選項適合。然後,當您在本機伺服器上開啟頁面時,樣式將從 Internet 中提取。2. 如果您想在本地擁有所有樣式並且不依賴 Internet 連接,您可以簡單地 下載帶有樣式的文件並將其放置在web 資料夾中的某個位置(例如web/styles/w3.css) ,然後瀏覽我們所有的頁面(index.html、add.jsp、list.jsp)並在 head 部分中輸入指向該文件的鏈接,並使用樣式。之後 ,只需瀏覽標籤並用您喜歡的樣式標記它們。我不會詳細討論這一點,但會立即提供我的三個文件的現成版本以及已安排的樣式類別。index.html add.jsp list.jsp 就是這樣 :) 如果您仍然有任何問題或有任何意見,或者相反,有些事情沒有解決 - 請留下評論。好吧,我將附上幾張截圖來說明這一切的結果。 最後。如果你想練習這個項目,你可以嘗試: Super app!

    Super app!

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("
    \n" + " ×\n" + "
    User '" + request.getAttribute("userName") + "' added!
    \n" + "
    "); } %>

    Add user

    <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users list

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println("
      "); for (String s : names) { out.println("
    • " + s + "
    • "); } out.println("
    "); } else out.println("
    \n" + " ×\n" + "
    There are no users yet!
    \n" + "
    "); %>
    應用程式首頁 新增使用者視窗 使用者列表
    • 製作一個 servlet 和 jsp 來刪除用戶,並製作幾個來更改/編輯現有用戶。您將在 servlet 上獲得真正的 CrUD Web 應用程式:)))
    • 替換列表(列表 )與資料庫一起使用,以便新增的使用者在伺服器重新啟動後不會消失:)
    祝你好運!
    留言
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION