題目
?頁面StudentLogin.html中有一HTML的表單代碼如下:
<form action="studentLogin" method="post">學生姓名:<input type="text" name="stuName" value=""><br>登錄密碼:<input type="password" name="stuPwd" value=""><br><input type="submit" name= "" value="登錄">
</form>
現按下面的要求定義一個Servlet:
1)定義一個Servlet,將StudentLogin.html的表單數據提交到這個Servlet,根據StudentLogin頁面表單中的設置來配置本Servlet的訪問路徑,要求采用注解方式配置訪問路徑;
2)本Servlet中獲取StudentLogin.html表單提交的學生姓名、登錄密碼,若姓名為“趙錢孫”,且密碼為“123456”,則將該學生姓名添加為request對象以實現數據流轉,再將請求內部派發home.jsp;反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;
3)設置輸出Servlet的響應數據類型為html。
注釋:
1)設置request作用域:
request.setAttribute(String,Object);
2)頁面請求內部派發:
request.getRequestDispatcher(url).forward(request,response);
3)3秒后頁面自動跳轉
response.setHeader("Refresh","3;URL=路徑");
注意:只用編寫Servlet文件,不用編寫jsp和html文件。
本章知識重點:?
目錄
HTML里的表單元素
解讀表單代碼:###
1.定義Servlet:
?1.2 方便驗證——創建一個html文件?##
?1.3?編寫Servlet_注解方式配置Servlet路徑?
2. doPost方法重寫(重載)#####
2.1 分析題意:?#####
2.2 設置request作用域:###
請求作用域是何物
2.3 將請求內部派發:
?2.4 3秒后頁面自動跳轉
完整代碼參考 :
前文鏈接:JAVAWeb_Servlet初識與代碼入門-CSDN博客
JAVAWeb_Servlet初識與代碼入門-CSDN博客
我們本節重中之重,便是學會處理POST請求。但是先來看“題目”一上來,給了我們一段代碼——“StudentLogin.html中有一HTML的表單代碼”。這段代碼是什么,對于我們處理的POST請求有什么關系?
HTML里的表單元素
<form ......>......
</form>
<form>一出現,而</form>一結尾(體現標簽成對出現的特點),就表示兩個標簽中間的代碼是表單代碼。
表單代碼一般放在HTML文件里。因為:HTML是一種用于構建網頁的標記語言,它包含多種元素,用于定義網頁的結構、內容和布局。表單只是HTML中眾多元素之一,用于收集用戶輸入的數據并提交到服務器。
表單代碼收集用戶數據?這就很妙了,請求正是要收集(服務器所需的)用戶數據:GET請求里我們通過URL的查詢字符串的方法收集用戶數據;POST請求里我們就用表單收集用戶數據。
解讀表單代碼:
接下來,我們通過解讀這段表單代碼來了解表單代碼怎么收集用戶信息。
<form action="studentLogin" method="post">...
</form>
?<form>
?標簽成對出現。所以一頭為<form>,末尾</form>。
我們再著重看第一行:
<form action="studentLogin" method="post">
//?在寫form代碼時,就要規定action和method,這是<form> 標簽的屬性,它們定義了表單提交時的行為。
// action="studentLogin" ,指定表單數據提交的目標URL ——因為這里的表單數據不是為了收集而收集,而是為了交給服務器處理。服務器怎么處理,自然是交給能處理的POST請求的Servlet。所以這個URL,正是Servlet的URL映射路徑,表單收集到的數據都會通過URL,找到并交給能處理這段數據的Servlet。//指定表單數據提交的方式為HTTP POST方法。POST方法通常用于提交敏感數據(如登錄信息),因為它不會將數據暴露在URL中。
若讀者通過了GET請求那一題,便知道GET請求傳數據是直接在URL里傳參數的鍵值對(可謂是光明正大,密碼都是通過明文并且不加修飾直接交給Servlet。客戶敢用,我們都不敢這么寫)。?
現在來看:<form>標簽里的代碼,為了更好理解,我們結合運行.html文件出的表單。
學生姓名:<input type="text" name="stuName" value=""><br>
登錄密碼:<input type="password" name="stuPwd" value=""><br><input type="submit" name= "" value="登錄">
?先來直觀理解<form>生成的表單內容:
?可以看到:
①:“學生姓名:”就直接顯示,后面"<input ......>"對應了網頁里生成的輸入框。
②:“登錄密碼:”也直接顯示,后面"<input ......>"對應了網頁里生成的輸入框。
③:因為只有<input......>它其實也是輸入框,不過它已經被賦值了“登錄”。所以這個框直接顯示“登錄”。
?這里大家會注意新的標簽<input>:介紹如下
<input type="text" name="username" value="default value"><br>
//<input>也有三個關鍵屬性:在定義時會讓我們初始化
// 1. type 屬性定義了輸入字段的類型。text:普通文本輸入框,用戶可以輸入任意文本。
// 2. name 屬性為輸入字段指定一個名稱,這個名稱在表單提交時用于標識該輸入字段(說人話,就是該輸入框的名稱&&參數的鍵值對中的“鍵”)
// 3. value 屬性定義了輸入字段的默認值或當前值。(說人話,就是輸入框里的數據 && 參數鍵值對中的“值”)// <br>是換行
那么此處這三句代碼就好理解了:
學生姓名:<input type="text" name="stuName" value=""><br>
// 學生姓名:直接打印輸出在頁面
// <input> 為HTML輸入元素,用于創建一個輸入框
// type="text" 表示為一個文本輸入框,用戶可以在其中輸入任意文本。
// name="stuName" 為輸入框指定一個名稱,服務器端可以通過這個名稱來獲取對應的值
// value="" 指定輸入框的默認值。這里默認值為空,表示用戶需要手動輸入學生姓名。
登錄密碼:<input type="password" name="stuPwd" value=""><br>
// 這是一個密碼輸入框,類型(type)為"password"。其特點:輸入時會以隱藏形式顯示(通常顯示為圓點或星號),以保護用戶輸入的敏感信息。
// 輸入框名稱為stuPwd (鍵值對中的鍵)
// 默認輸入值為空,等待學生輸入密碼 (鍵值對中的值)
<input type="submit" name= "" value="登錄">
//這個輸入框,前面就不顯示什么文本信息了。
//類型為"submit",name=""為按鈕指定一個名稱。這里名稱為空,表示該按鈕沒有特定的名稱。
// 但這個按鈕(輸入框)默認值為“登錄”,于是在網頁上就會在這個按鈕上浮現這個值
// submit類型的輸入框:用戶點擊后觸發表單提交操作。
也就是說,提交的表單包含了兩個參數對(學生姓名 和登錄密碼 與其對應的值們)?當點擊submit類型的按鈕,就會提交表單。表單會提交到我們編寫的servlet里(因為收集用戶端數據,就是為了交給服務器端處理)。為了處理這種以表單形式收集數據的請求,我們將這種請求稱為POST請求,于是Servlet編寫的處理請求的方法—— 正是doPost(一種專門處理POST請求)方法。
1.定義Servlet:
接下來,我們開始寫代碼。
首先得創建JAVA Web項目,作者這里就創建好了:
?
接著需要新建一個Servlet文件:
?
Servlet名字也沒規定,作者自定義了。
?Eclipse生成的代碼,我刪了些(鍛煉代碼能力嘛)
?1.2 方便驗證——創建一個html文件
如標題所示,就是為了方便驗證。接下來展示怎么創建一個html文件。
?
自動生成的HTML File具有以下代碼:
?
這里我們需要編寫的HTML代碼是一段表單,因為題上已經給出,我們直接copy上去(呵呵)
?(忽略.html的名字,就按照題意取名,作者是后面發現不對勁的?T_T)
1.3?編寫Servlet_注解方式配置Servlet路徑
使用注解方式配置Servlet,我們都會采用@WebServlet(),這是前面提過的以及Servlet的代碼開頭、整體框架,我就直接開頭嘍~
@WebServlet("/")
public class stuLoginservlet extends HttpServlet
{// 繼承HttpServlet,是為了什么?為了保證自己寫的Servlet在語法上實現Servlet所有方法;語法上實現,意味著我們開發者不需要寫那些代碼// 而又可以繼承HttpServlet提供的doGet和doPost方法,根據我們的需要進行改寫
}
類名須于.java文件名一致。?
我們現在來思考:用戶可以通過哪個URL訪問到我們的Servlet,這也是@WebServlet注釋的作用。
再看一眼題意:
根據我們前面“表單代碼”?以及這里不斷明示,為Servlet配置的路徑,正是表單要提交的URL("studentLogin"),而表單提交的方式"method = "post"",也意味著這份表單要交給能處理post請求的servlet。
@WebServlet("/studentLogin")//表單根據action的值找到g該值映射的這個servlet
public class stuLoginservlet extends HttpServlet
{//為了處理post請求,我們得改寫doPost方法protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{}
}
2. doPost方法重寫(重載)
2.1 分析題意:?
在分析題意中,我們會把整體代碼邏輯和能寫的代碼完成~
本Servlet獲取StudentLogin.html表單提交的學生姓名、登錄密碼
很明顯,我們需要先獲取參數,沒問題—— request.getParameter();?
String name = request.getParameter("stuName");//傳進去的參數,一定是參數對的鍵。因為要獲取用戶輸入的值:這里獲取的是stuName的值
String pwd = request.getParameter("stuPwd");//這里pwd獲取的是:用戶對應stuPwd這個輸入框的值
“若則”關系,那么需要使用if-else?:
//獲取參數的值
String name = request.getParameter("stuName");
String pwd = request.getParameter("stuPwd");
//若則關系
if()
{}
else
{}
//若姓名為"趙錢孫",密碼為"123456"
if("趙錢孫".equals(name) && "123456".equals(pwd))
//String.equals(String) 判斷兩個字符串是否相等,第一個String不能為null否則會拋出異常
接下來寫偽代碼:?
//獲取參數的值
String name = request.getParameter("stuName");
String pwd = request.getParameter("stuPwd");
//若則關系
if("趙錢孫".equals(name) && "123456".equals(pwd))
{//將該學生姓名添加為request對象以實現數據流轉,再將請求內部派發home.jsp
}
else
{//反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;
}
在瀏覽器上顯示頁面信息?這我們學過啊,直接寫:
//在瀏覽器上顯示信息//1.獲取響應輸出流
PrintWriter out = response.getWriter();
//2.輸出信息
out.println("登錄失敗,3秒鐘后請重新登錄");
//獲取參數的值
String name = request.getParameter("stuName");
String pwd = request.getParameter("stuPwd");
//若則關系
if("趙錢孫".equal(name) && "123456".equal(pwd))
{//將該學生姓名添加為request對象以實現數據流轉,再將請求內部派發home.jsp
}
else
{//反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;PrintWriter out = response.getWriter();out.println("登錄失敗,3秒鐘后請重新登錄");
}
其他的“內部派發”,"自動跳轉",我們還沒學,但是代碼邏輯基本完整,后續補充一下就能上手。還有些細節需要處理:
3)設置輸出Servlet的響應數據類型為html。
//這也是我們學習過的—— response.setContentType();
response.setContentType("text/html;charset=UTF-8");
?現在來綜合我們寫的代碼,來發現還有哪些還沒解決:
@WebServlet("/studentLogin")
public class stuLoginservlet extends HttpServlet
{protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{//以后都要習慣,只要涉及到中文;不管題上是否讓響應輸出html格式,都得第一步設置響應的編碼格式// 1.設置編碼response.setContentType("text/html;charset=UTF-8");// 2. 獲取請求參數的值String name = request.getParameter("stuName");String pwd = request.getParameter("stuPwd");// 3. 判斷請求參數值if("趙錢孫".equals(name) && "123456".equals(pwd)){//將該學生姓名添加為request對象以實現數據流轉,再將請求內部派發home.jsp}else{//反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;PrintWriter out = response.getWriter();out.println("登錄失敗,3秒鐘后請重新登錄");}}
}
還沒解決的問題:
1. 對于請求體的編碼,服務器并沒設置編碼—— 如果請求體參數的值為中文,服務器默認的編碼是不支持識別中文。
2.??將該學生姓名添加為request對象以實現數據流轉,再將請求內部派發home.jsp
3.? 在3秒后自動跳轉StudentLogin.html頁面;
對于第1點,我們只需熟悉(掌握)這句話:
request.setCharacterEncoding("UTF-8");
//處理表單數據,一定要設置請求體的編碼,確保服務器能正確解析傳來的字符(中文)
所以處理Post請求,一定二話不說,方法體的第一步是兩個編碼:
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");?
?還剩最后兩點:
出題人也是很善良體貼了,都貼上了相應的方法,所以這篇作者會重點討論第一個方法,后面兩個方法直接考慮怎么用就完了(鍛煉我們現學現賣的技能):
2.2 設置request作用域:
方法介紹(參考官方文檔格式)
public void request.setAttribute(String name,Object obj);
即 request.setAttribute(String name,Object obj);
方法描述
將一個對象obj與指定的名稱name綁定到當前請求的作用域中。此方法允許將數據存儲
HttpServletRequest
對象(此處為doPost里的request)中,以便在同一個請求的后續處理過程中訪問這些數據。例如,可以將數據傳遞給后續的Servlet或JSP頁面。(此處題意為傳給home.jsp)
參數
name
:要綁定到請求作用域的屬性名稱。該名稱必須是String
類型,且不能為null。
o
:要綁定到請求作用域的屬性值。該值可以是任何Object
類型,包括null
異常
IllegalArgumentException
:如果name
為null
。
注意:
· 作用域限制:
使用
setAttribute
方法設置的屬性僅在當前請求的作用域中有效。一旦請求結束,這些屬性將不再可用。· 覆蓋屬性:
如果已經存在一個與指定名稱相同的屬性,調用
setAttribute
方法將覆蓋原來的屬性值。
請求作用域是何物
請求作用域 是Web應用程序中的一種數據存儲范圍,它與單個HTTP請求相關聯。好理解,這個作用域就是存數據的。
為什么需要請求作用域。(即它的作用):剛剛介紹的設置request的作用域方法,結合此處所說的請求作用域。就知道設置request的作用域實際上就是把一對參數(它的名稱和值)存進請求作用域。從題意上,我們其實能窺見請求作用域的作用——將數據傳遞給后續的Servlet或JSP頁面
(作者覺得這出題人這里描述得有問題,更恰當地——“將學生姓名添加到request對象”)?
更加完整的作用:
數據共享——在處理一個HTTP請求時,可能需要在多個組件(如Servlet、JSP頁面)之間共享數據。請求作用域提供了一個方便的地方來存儲這些數據,使得它們可以在請求的生命周期內被訪問。(重點)
簡化數據傳遞——通過將數據存儲在請求作用域中,可以避免在組件之間手動傳遞數據。例如,從Servlet到JSP頁面,或者從一個Servlet到另一個Servlet。
于是,結合分析,代碼如下:
request.setAttribute("StuName",name);//設為request作用域的對象之一,又是一個鍵值對啊盆油:鍵作者自己取了,值為我們獲取到的參數值name
@WebServlet("/studentLogin")
public class stuLoginservlet extends HttpServlet
{protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{// 1.設置編碼request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");// 2. 獲取請求參數的值String name = request.getParameter("stuName");String pwd = request.getParameter("stuPwd");// 3. 判斷請求參數值if("趙錢孫".equal(name) && "123456".equal(pwd)){//將該學生姓名添加為request對象以實現數據流轉request.setAttribute("StuName",name);//再將請求內部派發home.jsp}else{//反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;PrintWriter out = response.getWriter();out.println("登錄失敗,3秒鐘后請重新登錄");}}
}
2.3 將請求內部派發:
?2)頁面請求內部派發:
request.getRequestDispatcher(url).forward(request,response);
很明顯,若想實現“再將請求內部派發home.jsp”,我們只要把這句代碼copy上去,把參數正確填寫就能實現:
request.getRequestDispatcher("/home.jsp").forward(request,response);
// url 是一個字符串,表示目標資源的路徑。推薦加“/”,絕對路徑寫法
//后面的request,response不用改變,我們當前servlet的request,response就是這個名字
?2.4 3秒后頁面自動跳轉
3)3秒后頁面自動跳轉
response.setHeader("Refresh","3;URL=路徑");
題目要求:3s后頁面自動跳轉到?StudentLogin.html 頁面。只需要替換url的值就行(👌)
response.setHeader("Refresh","3;URL=StudentLogin.html");
我們所有代碼都已經完成:
@WebServlet("/studentLogin")
public class stuLoginservlet extends HttpServlet
{protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{// 1.設置編碼request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");// 2. 獲取請求參數的值String name = request.getParameter("stuName");String pwd = request.getParameter("stuPwd");// 3. 判斷請求參數值if("趙錢孫".equals(name) && "123456".equals(pwd)){//將該學生姓名添加為request對象以實現數據流轉request.setAttribute("StuName",name);//再將請求內部派發home.jsprequest.getRequestDispatcher("/home.jsp").forward(request,response);}else{//反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;PrintWriter out = response.getWriter();out.println("登錄失敗,3秒鐘后請重新登錄");response.setHeader("Refresh","3;URL=StudentLogin.html");}}
}
驗證:
顯示:
?
重新跳轉:?
另一種情況:?
沒事兒,現在保證自己寫的代碼邏輯寫對就行。我們本來也沒寫home.jsp?,后面我們揭曉jsp。
完整代碼參考 :
@WebServlet("/studentLogin")
public class stuLoginservlet extends HttpServlet
{protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{// 1.設置編碼request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");// 2. 獲取請求參數的值String name = request.getParameter("stuName");String pwd = request.getParameter("stuPwd");// 3. 判斷請求參數值if("趙錢孫".equals(name) && "123456".equals(pwd)){//將該學生姓名添加為request對象以實現數據流轉request.setAttribute("StuName",name);//再將請求內部派發home.jsprequest.getRequestDispatcher("/home.jsp").forward(request,response);}else{//反之則顯示“登錄失敗,3秒鐘后請重新登錄”,并在3秒后自動跳轉StudentLogin.html頁面;PrintWriter out = response.getWriter();out.println("登錄失敗,3秒鐘后請重新登錄");response.setHeader("Refresh","3;URL=StudentLogin.html");}}
}
經過這兩篇文章的鋪墊,對于定義基本Servlet我們至少不會再手足無措——多敲多敲,希望讀者(包括作者)能在定義Servlet時得心應手(放心,后面還有練習,作者補充知識的篇幅就不這么大了)。
?前文鏈接:JAVAWeb_Servlet初識與代碼入門-CSDN博客
JAVAWeb_Servlet初識與代碼入門-CSDN博客
作者有話說:(我真沒想到能破萬(扶額邪魅一笑),嘶~為了咱的讀者后期好查閱,我會將一些篇幅大的重要部分單拎出來(點頭))
不過能看到這里的讀者,作者也要為你點贊👍