創建實體
在
entities
包中,我們將創建一個
User
具有兩個私有字符串變量的類:
name
和
password
。創建構造函數(默認構造函數和接受兩個值的構造函數)和 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 請求
,我們覆蓋了
HttpServlet
doGet()
類中的方法。為了讓我們的 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 列表):
List<String> names = (List<String>) request.getAttribute("userNames");
if (names != null && !names.isEmpty()) {
for (String s : names) {
out.println("<li>" + s + "</li>");
如果我們只需要在有用戶時顯示列表,否則顯示沒有用戶的警告,那麼我們可以稍微改寫這部分:
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" %>
<title>Add new user</title>
</head>
<h1>Super app!</h1>
if (request.getAttribute("userName") != null) {
out.println("<p>User '" + request.getAttribute("userName") + "' added!</p>");
<h2>Add user</h2>
<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>
<button onclick="location.href='/'">Back to main</button>
</body>
</html>
頁面主體由以下部分組成:
帶有標題的 div;
內容的 div 容器,其中包括檢查是否存在具有用戶名的屬性;
帶有添加用戶表單的 div;
在底部,一個帶有返回主頁按鈕的頁腳。
這可能看起來像太多的 div,但我們稍後會在添加樣式時使用它們。
這是list.jsp
的最終版本:
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<title>Users</title>
</head>
<h1>Super app!</h1>
<h2>Users</h2>
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>");
<button onclick="location.href='/'">Back to main</button>
</body>
</html>
因此,我們有一個可以保存和添加用戶並顯示他們姓名列表的完整工作的 Web 應用程序。現在我們只需要讓它漂亮...... :)
添加樣式。我們將使用 W3.CSS 框架
目前,我們的應用程序可以運行,但它看起來絕對離譜。因此,讓我們添加背景、為文本和按鈕著色、為列表添加樣式、對齊元素、添加縮進等等。手動編寫樣式會花費大量時間並耗費我們的精力。所以我建議使用
W3.CSS
框架。它已經有帶有樣式的現成類。我們只需要將要使用的 CSS 類安排在正確的位置即可。要將它們添加到我們的頁面,我們首先連接樣式文件。有兩種方法可以做到這一點:
瀏覽我們的頁面並在標題部分插入以下樣式文件的直接鏈接
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
如果您有永久的 Internet 連接,則此選項適用。當您在本地服務器上打開您的頁面時,樣式將從 Internet 中提取。
但是如果你想在本地擁有所有樣式而不依賴於 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">
<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 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>
</body>
</html>
添加.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<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 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>
<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 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>
</body>
</html>
列表.jsp
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<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 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>
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 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>
</body>
</html>
就是這樣。:) 如果您還有任何問題或意見,或者有什麼不對,請發表評論。我將附上幾張截圖,說明結果如何。
最後
,如果你想練習這個項目,你可以嘗試以下方法:
製作一個 servlet 和 JSP 來刪除用戶,並添加另一對來編輯現有用戶。結果將是使用 servlet 構建的真正的 CRUD Web 應用程序。;)
將List替換為數據庫,這樣添加的用戶不會在服務器重啟後消失。:)
祝你好運!
CodeGym 是幫助您從零開始學習 Java 程式設計的線上課程。這個課程是讓初學者成為 Java 大師的完美途徑。內容有 1200+ 個任務,並為您即時驗證,還提供 Java 基礎理論中不可不知的內容。為了讓你在學習上取得成功,我們實作了一系列激勵性功能,像是小測驗、編碼專案,還有關於高效學習以及 Java 開發人員職涯的內容。