1. 程式人生 > 其它 >4.Cookie和SessionJsp

4.Cookie和SessionJsp

Cookie&SessionJsp

1 會話技術

1.1 會話管理概述

1.1.1 什麼是會話

這裡的會話,指的是web開發中的一次通話過程,當開啟瀏覽器,訪問網站地址後,會話開始,當關閉瀏覽器(或者到了過期時間),會話結束。

舉個例子:

​ 例如,你在給家人打電話,這時突然有送快遞的配送員敲門,你放下電話去開門,收完快遞回來後,通話還在保持中,繼續說話就行了。

1.1.2 會話管理作用

什麼時候會用到會話管理呢?最常見的就是購物車,當我們登入成功後,把商品加入到購物車之中,此時我們無論再瀏覽什麼商品,當點選購物車時,那些加入的商品都仍在購物車中。

在我們的實際開發中,還有很多地方都離不開會話管理技術。比如,我們在論壇發帖,沒有登入的遊客身份是不允許發帖的。所以當我們登入成功後,無論我們進入哪個版塊發帖,只要許可權允許的情況下,伺服器都會認識我們,從而讓我們發帖,因為登入成功的資訊一直保留在伺服器端的會話中。

通過上面的兩個例子,我們可以看出,它是為我們共享資料用的,並且是在不同請求間實現資料共享。也就是說,如果我們需要在多次請求間實現資料共享,就可以考慮使用會話管理技術了。

1.1.3 會話管理分類

在JavaEE的專案中,會話管理分為兩類。分別是:客戶端會話管理技術和服務端會話管理技術。

客戶端會話管理技術

​ 它是把要共享的資料儲存到了客戶端(也就是瀏覽器端)。每次請求時,把會話資訊帶到伺服器,從而實現多次請求的資料共享。

服務端會話管理技術

​ 它本質仍是採用客戶端會話管理技術,只不過儲存到客戶端的是一個特殊的標識,並且把要共享的資料儲存到了服務端的記憶體物件中。每次請求時,把這個標識帶到伺服器端,然後使用這個標識,找到對應的記憶體空間,從而實現資料共享。

1.2 客戶端會話管理技術

1.2.1 Cookie概述

1)什麼是Cookie

它是客戶端瀏覽器的快取檔案,裡面記錄了客戶瀏覽器訪問網站的一些內容。同時,也是HTTP協議請求和響應訊息頭的一部分(在HTTP協議課程中,我們備註了它很重要)。

2)Cookie的API詳解

作用

它可以儲存客戶瀏覽器訪問網站的相關內容(需要客戶端不禁用Cookie)。從而在每次訪問需要同一個內容時,先從本地快取獲取,使資源共享,提高效率。

Cookie的屬性

屬性名稱 屬性作用 是否重要
name cookie的名稱 必要屬性
value cookie的值(不能是中文) 必要屬性
path cookie的路徑 重要
domain cookie的域名 重要
maxAge cookie的生存時間。 重要
version cookie的版本號。 不重要
comment cookie的說明。 不重要

細節

Cookie有大小,個數限制。每個網站最多隻能存20個cookie,且大小不能超過4kb。同時,所有網站的cookie總數不超過300個。

當刪除Cookie時,設定maxAge值為0。當不設定maxAge時,使用的是瀏覽器的記憶體,當關閉瀏覽器之後,cookie將丟失。設定了此值,就會儲存成快取檔案(值必須是大於0的,以秒為單位)。

3)Cookie涉及的常用方法

建立Cookie

/**
 * 通過指定的名稱和值構造一個Cookie
 *
 * Cookie的名稱必須遵循RFC 2109規範。這就意味著,它只能包含ASCII字母數字字元,
 * 不能包含逗號、分號或空格或以$字元開頭。
 * 建立後無法更改cookie的名稱。
 *
 * 該值可以是伺服器選擇傳送的任何內容。
 * 它的價值可能只有伺服器才感興趣。
 * 建立之後,可以使用setValue方法更改cookie的值。
 */
public Cookie(String name, String value) {
	validation.validate(name);
	this.name = name;
	this.value = value;
}

向瀏覽器新增Cookie

/**
 * 新增Cookie到響應中。此方法可以多次呼叫,用以新增多個Cookie。
 */
public void addCookie(Cookie cookie);

從伺服器端獲取Cookie

/**
 * 這是HttpServletRequest中的方法。
 * 它返回一個Cookie的陣列,包含客戶端隨此請求傳送的所有Cookie物件。
 * 如果沒有符合規則的cookie,則此方法返回null。
 */
 public Cookie[] getCookies();

1.2.2 Cookie的Path細節:瀏覽器什麼時候帶給伺服器,什麼時候不帶

1)需求說明

建立一個Cookie,設定Cookie的path,通過不同的路徑訪問,從而檢視請求攜帶Cookie的情況。

2)案例目的

通過此案例的講解,同學們可以清晰的描述出,客戶瀏覽器何時帶cookie到伺服器端,何時不帶。

3)案例步驟

第一步:建立JavaWeb工程

沿用第一個案例中的工程即可。

第二步:編寫Servlet

/**
 * Cookie的路徑問題
 * 前期準備:
 * 	1.在demo1中寫一個cookie到客戶端
 *  2.在demo2和demo3中分別去獲取cookie
 *  	demo1的Servlet對映是   /servlet/PathQuestionDemo1
 *  	demo2的Servlet對映是   /servlet/PathQuestionDemo2
 *  	demo3的Servlet對映是   /PathQuestionDemo3
 *
 * @author 黑馬程式設計師
 * @Company http://www.itheima.com
 *
 */
public class PathQuestionDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1.建立一個Cookie
		Cookie cookie = new Cookie("pathquestion","CookiePathQuestion");
		//2.設定cookie的最大存活時間
		cookie.setMaxAge(Integer.MAX_VALUE);
		//3.把cookie傳送到客戶端
		response.addCookie(cookie);//setHeader("Set-Cookie","cookie的值")
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

/**
 * 獲取Cookie,名稱是pathquestion
 * @author 黑馬程式設計師
 * @Company http://www.itheima.com
 */
public class PathQuestionDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1.獲取所有的cookie
		Cookie[] cs = request.getCookies();
		//2.遍歷cookie的陣列
		for(int i=0;cs!=null && i<cs.length;i++){
			if("pathquestion".equals(cs[i].getName())){
				//找到了我們想要的cookie,輸出cookie的值
				response.getWriter().write(cs[i].getValue());
				return;
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
/**
 * 獲取Cookie,名稱是pathquestion
 * @author 黑馬程式設計師
 * @Company http://www.itheima.com
 */
public class PathQuestionDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1.獲取所有的cookie
		Cookie[] cs = request.getCookies();
		//2.遍歷cookie的陣列
		for(int i=0;cs!=null && i<cs.length;i++){
			if("pathquestion".equals(cs[i].getName())){
				//找到了我們想要的cookie,輸出cookie的值
				response.getWriter().write(cs[i].getValue());
				return;
			}
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

第三步:配置Servlet

<!--配置Cookie路徑問題案例的Servlet-->
<servlet>
    <servlet-name>PathQuestionDemo1</servlet-name>
    <servlet-class>com.itheima.web.servlet.pathquestion.PathQuestionDemo1</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>PathQuestionDemo1</servlet-name>
    <url-pattern>/servlet/PathQuestionDemo1</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>PathQuestionDemo2</servlet-name>
    <servlet-class>com.itheima.web.servlet.pathquestion.PathQuestionDemo2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>PathQuestionDemo2</servlet-name>
    <url-pattern>/servlet/PathQuestionDemo2</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>PathQuestionDemo3</servlet-name>
    <servlet-class>com.itheima.web.servlet.pathquestion.PathQuestionDemo3</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>PathQuestionDemo3</servlet-name>
    <url-pattern>/PathQuestionDemo3</url-pattern>
</servlet-mapping>

第四步:部署工程

沿用第一個案例中的工程部署即可。

4)測試結果

通過分別執行PathQuestionDemo1,2和3這3個Servlet,我們發現由demo1寫Cookie,在demo2中可以取到,但是到了demo3中就無法獲取了,如下圖所示:

5)路徑問題的分析及總結

問題:
demo2和demo3誰能取到cookie?
答案:
demo2能取到,demo3取不到
分析:
首先,我們要知道如何確定一個cookie?
那就是使用cookie的三個屬性組合:domain+path+name
這裡面,同一個應用的domain是一樣的,在我們的案例中都是localhost。
​ 並且,我們取的都是同一個cookie,所以name也是一樣的,都是pathquestion。
​ 那麼,不一樣的只能是path了。但是我們沒有設定過cookie的path屬性,這就表明path是有預設值的。
接下來,我們開啟這個cookie來看一看,在ie瀏覽器訪問一次PathQuestionDemo1這個Servlet:

Cookie中的內容:

我們是通過demo1寫的cookie,demo1的訪問路徑是: http://localhost:9090/servlet/PathQuestionDemo1
通過比較兩個路徑:請求資源地址和cookie的path,可以看出:cookie的path預設值是:請求資源URI,沒有資源的部分(在我們的案例中,就是沒有PathQuestionDemo1)。

客戶端什麼時候帶cookie到伺服器,什麼時候不帶?
​ 就是看請求資源URI和cookie的path比較。

請求資源URI.startWith(cookie的path) 如果返回的是true就帶,如果返回的是false就不帶。

​ 簡單的說: 就是看誰的地址更精細

​ 比如:Cookie的path: /國家 /省份 /城市

	 	 請求資源URI	:   	  /國家			/省份														  不帶
	 	 請求資源URI   :	   /國家			/省份			/城市			/區縣				帶

在我們的案例中:

訪問URL URI部分 Cookie的Path 是否攜帶Cookie 能否取到Cookie
PathQuestionDemo2 /servlet/PathQuestionDemo2 /servlet/ 能取到
PathQuestionDemo3 /PathQuestionDemo3 /servlet/ 不帶 不能取到

1.3 服務端會話管理概述

1.3.1 HttpSession概述

1)HttpSession物件介紹

它是Servlet規範中提供的一個介面。該介面的實現由Servlet規範的實現提供商提供。我們使用的是Tomcat伺服器,它對Servlet規範進行了實現,所以HttpSession介面的實現由Tomcat提供。該物件用於提供一種通過多個頁面請求或訪問網站來標識使用者並存儲有關該使用者的資訊的方法。簡單說它就是一個服務端會話物件,用於儲存使用者的會話資料。

同時,它也是Servlet規範中四大域物件之一的會話域物件。並且它也是用於實現資料共享的。但它與我們之前講解的應用域和請求域是有區別的。

域物件 作用範圍 使用場景
ServletContext 整個應用範圍 當前專案中需要資料共享時,可以使用此域物件。
ServletRequest 當前請求範圍 在請求或者當前請求轉發時需要資料共享可以使用此域物件。
HttpSession 會話返回 在當前會話範圍中實現資料共享。它可以在多次請求中實現資料共享。

2)HttpSession的獲取

獲取HttpSession是通過HttpServletRequest介面中的兩個方法獲取的,如下圖所示:

這兩個方法的區別:

3)HttpSession的常用方法

1.3.2 HttpSession的入門案例

1)需求說明

在請求HttpSessionDemo1這個Servlet時,攜帶使用者名稱資訊,並且把資訊儲存到會話域中,然後從HttpSessionDemo2這個Servlet中獲取登入資訊。

2)案例目的

通過本案例的講解,同學們可以清楚的認識到會話域的作用,即多次請求間的資料共享。因為是兩次請求,請求域肯定不一樣了,所以不能用請求域實現。

最終掌握HttpSession物件的獲取和使用。

3)原理分析

HttpSession,它雖然是服務端會話管理技術的物件,但它本質仍是一個Cookie。是一個由伺服器自動建立的特殊的Cookie,Cookie的名稱就是JSESSIONID,Cookie的值是伺服器分配的一個唯一的標識。

當我們使用HttpSession時,瀏覽器在沒有禁用Cookie的情況下,都會把這個Cookie帶到伺服器端,然後根據唯一標識去查詢對應的HttpSession物件,找到了,我們就可以直接使用了。下圖就是我們入門案例中,HttpSession分配的唯一標識,同學們可以看到兩次請求的JSESSIONID的值是一樣的:

1.3.3 HttpSession的鈍化和活化

什麼是持久態

​ 把長時間不用,但還不到過期時間的HttpSession進行序列化,寫到磁碟上。

​ 我們把HttpSession持久態也叫做鈍化。(與鈍化相反的,我們叫活化。)

什麼時候使用持久化

​ 第一種情況:當訪問量很大時,伺服器會根據getLastAccessTime來進行排序,對長時間不用,但是還沒到過期時間的HttpSession進行持久化。

​ 第二種情況:當伺服器進行重啟的時候,為了保持客戶HttpSession中的資料,也要對HttpSession進行持久化

注意

​ HttpSession的持久化由伺服器來負責管理,我們不用關心。

​ 只有實現了序列化介面的類才能被序列化,否則不行。

2 頁面技術

2.1 JSP基礎

2.1.1 JSP簡介

JSP全稱是Java Server Page,它和Servlet一樣,也是sun公司推出的一套開發動態web資源的技術,稱為JSP/Servlet規範。JSP的本質其實就是一個Servlet。

2.1.2 JSP和HTML以及Servlet的適用場景

類別 適用場景
HTML 只能開發靜態資源,不能包含java程式碼,無法新增動態資料。
Servlet 寫java程式碼,可以輸出頁面內容,但是很不方便,開發效率極低。
JSP 它包括了HTML的展示技術,同時具備Servlet輸出動態資源的能力。但是不適合作為控制器來用。

2.1.3 JSP簡單入門

建立JavaWeb工程

在index.jsp中填寫內容

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>JSP的入門</title>
  </head>
  <body>
      這是第一個JSP頁面
  </body>
</html>

部署專案

沿用會話管理工程的部署方式即可。

測試執行

2.1.4 JSP說明

寫在之前: 明確JSP就是一個Servlet。是一個特殊的Servlet。

JSP的原理:

​ 客戶端提交請求

​ ——Tomcat伺服器解析請求地址

​ ——找到JSP頁面

​ ——Tomcat將JSP頁面翻譯成Servlet的java檔案

​ ——將翻譯好的.java檔案編譯成.class檔案

​ ——返回到客戶瀏覽器上。

1)執行過程分析圖

2)JSP的.java檔案內容分析

當我們開啟index.jsp翻譯的java檔案看到的就是public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase類的宣告,然後我們在Tomcat的原始碼中找到類的宣告,如下圖:

這張圖一出場,就表明我們寫的JSP它本質就是一個HttpServlet了。

同時,我們在index_jsp.java檔案中找到了輸出頁面的程式碼,並且在瀏覽器端檢視原始檔,看到的內容是一樣的。這也就是說明,我們的瀏覽器上的內容,在通過jsp展示時,本質都是用out.write()輸出出來的。

講到這裡,我們應該清楚的認識到,JSP它是一個特殊的Servlet,主要是用於展示動態資料。它展示的方式是用流把資料輸出出來,而我們在使用JSP時,涉及HTML的部分,都與HTML的用法一致,這部分稱為jsp中的模板元素,在開發過程中,先寫好這些模板元素,因為它們決定了頁面的外觀。

2.2 JSP應用

2.2.1 JSP語法

1)Java程式碼塊

在jsp中,可以使用java指令碼程式碼。形式為:<% 此處寫java程式碼 %>

但是,在實際開發中,極少使用此種形式編寫java程式碼。同時需要注意的是:

<%
	在裡面寫java程式指令碼需要注意:這裡面的內容由tomcat負責翻譯,翻譯之後是service方法的成員變數
%>

示例:

<!--Java程式碼塊-->
<% out.println("這是Java程式碼塊");%>
<hr/>

2)JSP表示式

在jsp中,可以使用特定表示式語法,形式為:<%=表示式%>

jsp在翻譯完後是out.print(表示式內容);

所以:<%out.print("當前時間);%>和<%="當前時間"%>是一樣的。

在實際開發中,這種表示式語法用的也很少使用。

示例:

<!--JSP表示式-->
<%="這是JSP表示式"%><br/>
就相當於<br/>
<%out.println("這是沒有JSP表示式輸出的");%>

3)JSP宣告

在JSP中也可以宣告一些變數,方法,靜態方法,形式為:<%! 宣告的內容 %>

使用JSP宣告需要注意:

<%! 
	需要注意的是: 寫在裡面的內容將會被tomcat翻譯成全域性的屬性或者類方法。
%>                                    

示例:

<!--JSP宣告-->
<%! String str = "宣告語法格式";%>
<%=str%>

4)JSP註釋

在使用JSP時,它有自己的註釋,形式為:<%--註釋--%>

需要注意的是:

​ 在Jsp中可以使用html的註釋,但是隻能註釋html元素,不能註釋java程式片段和表示式。同時,被html註釋部分會參與翻譯,並且會在瀏覽器上顯示

​ jsp的註釋不僅可以註釋java程式片段,也可以註釋html元素,並且被jsp註釋的部分不會參與翻譯成.java檔案,也不會在瀏覽器上顯示。

示例:

<%--JSP註釋--%>
<!--HTML註釋-->

5)語法的示例

JSP語法完整示例程式碼

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSP語法</title>
</head>
<body>

<!--Java程式碼塊-->
<% out.println("這是Java程式碼塊");%>
<hr/>

<!--JSP表示式-->
<%="這是JSP表示式"%><br/>
就相當於<br/>
<%out.println("這是沒有JSP表示式輸出的");%>

<hr/>
<!--JSP宣告-->
<%! String str = "宣告語法格式";%>
<%=str%>

<hr/>

<%--JSP註釋--%>
<!--HTML註釋-->

</body>
</html>

JSP語法執行結果

2.2.2 JSP指令

1)page指令

language:告知引擎,指令碼使用的是java,預設是java,支援java。不寫也行。

extends:告知引擎,JSP對應的Servlet的父類是哪個,不需要寫,也不需要改。

import:告知引擎,匯入哪些包(類)。

注意:引擎會自動匯入:java.lang.*,javax.servlet.*,javax.servlet.http.*,javax.servlet.jsp.*

匯入的形式:

<%@page import=”java.util.Date,java.util.UUID”%>或者:

<%@page import=”java.util.Date”%>

<%@page import=”java.util.UUID”%> 用Eclipse:Alt+/ 自動匯入

session:告知引擎是否產生HttpSession物件,即是否在程式碼中呼叫request.getSession()。預設是true。

buffer:JspWriter用於輸出JSP內容到頁面上。告知引擎,設定他的快取大小。預設8kb。

errorPage:告知引擎,當前頁面出現異常後,應該轉發到哪個頁面上(路徑寫法:/代表當前應用)

小貼士:當在errorpage上使用了isErrorPage=true之後,ie8有時候不能正常顯示

配置全域性錯誤頁面:web.xml

<error-page>    
    <exception-type>java.lang.Exception</exception-type>    			
    <location>/error.jsp</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/404.html</location>
</error-page>                                 

當使用了全域性錯誤頁面,就無須再寫errorPage來實現轉到錯誤頁面,而是由伺服器負責跳轉到錯誤頁面。

isErrorPage:告知引擎,是否抓住異常。如果該屬性為true,頁面中就可以使用exception物件,列印異常的詳細資訊。預設值是false。

contentType:告知引擎,響應正文的MIME型別。contentType="text/html;charset=UTF-8"

​ 相當於response.setContentType("text/html;charset=UTF-8");

pageEncoding:告知引擎,翻譯jsp時(從磁碟上讀取jsp檔案)所用的碼錶。pageEncoding="UTF-8"相當於告知引擎用UTF-8讀取JSP

isELIgnored*:告知引擎,是否忽略EL表示式,預設值是false,不忽略。

2)include指令

語法格式:<%@include file="" %>該指令是包含外部頁面。

屬性:file,以/開頭,就代表當前應用。

使用示例

靜態包含的特點

3)taglib指令

語法格式:<%taglib uri="" prefix=""%>

作用:該指令用於引入外部標籤庫。html標籤和jsp標籤不用引入。

屬性:

​ uri:外部標籤的URI地址。

​ prefix:使用標籤時的字首。

2.2.3 JSP細節

1)九大隱式物件

什麼是隱式物件呢?它指的是在jsp中,可以不宣告就直接使用的物件。它只存在於jsp中,因為java類中的變數必須要先宣告再使用。其實jsp中的隱式物件也並非是未宣告,只是它是在翻譯成.java檔案時宣告的。所以我們在jsp中可以直接使用。

隱式物件名稱 型別 備註
request javax.servlet.http.HttpServletRequest
response javax.servlet.http.HttpServletResponse
session javax.servlet.http.HttpSession Page指令可以控制開關
application javax.servlet.ServletContext
page Java.lang.Object 當前jsp對應的servlet引用例項
config javax.servlet.ServletConfig
exception java.lang.Throwable page指令有開關
out javax.servlet.jsp.JspWriter 字元輸出流,相當於printwriter
pageContext javax.servlet.jsp.PageContext 很重要

2)PageContext物件

簡介

它是JSP獨有的物件,Servlet中沒有這個物件。本身也是一個域(作用範圍)物件,但是它可以操作其他3個域物件中的屬性。而且還可以獲取其他8個隱式物件。

生命週期

它是一個區域性變數,所以它的生命週期隨著JSP的建立而誕生,隨著JSP的結束而消失。每個JSP頁面都有一個獨立的PageContext。

常用方法

在上圖中,同學們發現沒有頁面域操作的方法,其實是定義在了PageContext的父類JspContext中,如下圖所示:

3)四大域物件

域物件名稱 範圍 級別 備註
PageContext 頁面範圍 最小,只能在當前頁面用 因範圍太小,開發中用的很少
ServletRequest 請求範圍 一次請求或當期請求轉發用 當請求轉發之後,再次轉發時請求域丟失
HttpSession 會話範圍 多次請求資料共享時使用 多次請求共享資料,但不同的客戶端不能共享
ServletContext 應用範圍 最大,整個應用都可以使用 儘量少用,如果對資料有修改需要做同步處理

2.2.4 JSP最佳實戰-MVC模型

Servlet:擅長處理業務邏輯,不擅長輸出顯示介面。在web開發中多用於控制程式邏輯(流程)。所以我們稱之為:控制器。

JSP:擅長顯示介面,不擅長處理程式邏輯。在web開發中多用於展示動態介面。所以我們稱之為:檢視。

例如:

M:model ,通常用於封裝資料,封裝的是資料模型。

V:view ,通常用於展示資料。動態展示用jsp頁面,靜態資料展示用html。

C:controller ,通常用於處理請求和響應。一般指的是Servlet。

3 綜合案例-學生管理系統升級

3.1 登入功能實現

3.1.1 建立一個web專案,在 web 目錄下建立一個 index.jsp。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>學生管理系統首頁</title>
</head>
<body>
    <%--
        獲取會話域中的資料
        如果獲取到了則顯示新增和檢視功能的超連結
        如果沒獲取到則顯示登入功能的超連結
    --%>
    <% Object username = session.getAttribute("username");
        if(username == null) {
    %>
        <a href="/stu/login.jsp">請登入</a>
    <%} else {%>
        <a href="/stu/addStudent.jsp">新增學生</a>
        <a href="/stu/listStudentServlet">檢視學生</a>
    <%}%>
</body>
</html>

3.1.2 在 web 目錄下建立一個 login.jsp。實現登入頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>學生登入</title>
</head>
<body>
    <form action="/stu/loginStudentServlet" method="get" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密碼:<input type="password" name="password"> <br>
        <button type="submit">登入</button>
    </form>
</body>
</html>

3.1.3 建立 LoginStudentServlet,獲取使用者名稱和密碼

package com.itheima.servlet;

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

/*
    學生登入
 */
@WebServlet("/loginStudentServlet")
public class LoginStudentServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.獲取使用者名稱和密碼
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        //2.判斷使用者名稱
        if(username == null || "".equals(username)) {
            //2.1使用者名稱為空 重定向到登入頁面
            resp.sendRedirect("/stu/login.jsp");
            return;
        }

        //2.2使用者名稱不為空 將使用者名稱存入會話域中
        req.getSession().setAttribute("username",username);

        //3.重定向到首頁index.jsp
        resp.sendRedirect("/stu/index.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

3.2新增功能實現

3.2.1 在 web 目錄下建立一個 addStudent.jsp,實現新增學生的表單項

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>新增學生</title>
</head>
<body>
<form action="/stu/addStudentServlet" method="get" autocomplete="off">
    學生姓名:<input type="text" name="username"> <br>
    學生年齡:<input type="number" name="age"> <br>
    學生成績:<input type="number" name="score"> <br>
    <button type="submit">儲存</button>
</form>
</body>
</html>

3.2.2 建立 AddStudentServlet,獲取學生資訊並儲存到檔案中

package com.itheima.servlet;

import com.itheima.bean.Student;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/*
    實現新增功能
 */
@WebServlet("/addStudentServlet")
public class AddStudentServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.獲取表單中的資料
        String username = req.getParameter("username");
        String age = req.getParameter("age");
        String score = req.getParameter("score");

        //2.建立學生物件並賦值
        Student stu = new Student();
        stu.setUsername(username);
        stu.setAge(Integer.parseInt(age));
        stu.setScore(Integer.parseInt(score));

        //3.將學生物件的資料儲存到d:\\stu.txt檔案中
        BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\stu.txt",true));
        bw.write(stu.getUsername() + "," + stu.getAge() + "," + stu.getScore());
        bw.newLine();
        bw.close();

        //4.通過定時重新整理功能響應給瀏覽器
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("新增成功。2秒後自動跳轉到首頁...");
        resp.setHeader("Refresh","2;URL=/stu/index.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

3.3 檢視學生功能

3.3.1 建立 ListStudentServlet,讀取檔案中的學生資訊到集合中

1、將集合新增到會話域中

2、重定向到 listStudent.jsp 頁面上
package com.itheima.servlet;

import com.itheima.bean.Student;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

/*
    實現檢視功能
 */
@WebServlet("/listStudentServlet")
public class ListStudentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.建立字元輸入流物件,關聯讀取的檔案
        BufferedReader br = new BufferedReader(new FileReader("d:\\stu.txt"));

        //2.建立集合物件,用於儲存Student物件
        ArrayList<Student> list = new ArrayList<>();

        //3.迴圈讀取檔案中的資料,將資料封裝到Student物件中。再把多個學生物件新增到集合中
        String line;
        while((line = br.readLine()) != null) {
            //張三,23,95
            Student stu = new Student();
            String[] arr = line.split(",");
            stu.setUsername(arr[0]);
            stu.setAge(Integer.parseInt(arr[1]));
            stu.setScore(Integer.parseInt(arr[2]));
            list.add(stu);
        }

        //4.將集合物件存入會話域中
        req.getSession().setAttribute("students",list);

        //5.重定向到學生列表頁面
        resp.sendRedirect("/stu/listStudent.jsp");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

3.3.2 在 web 目錄下建立一個 listStudent.jsp

<%@ page import="com.itheima.bean.Student" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>檢視學生</title>
</head>
<body>
    <table width="600px" border="1px">
        <tr>
            <th>學生姓名</th>
            <th>學生年齡</th>
            <th>學生成績</th>
        </tr>
        <% ArrayList<Student> students = (ArrayList<Student>) session.getAttribute("students");
            for(Student stu : students) {
        %>
            <tr align="center">
                <td><%=stu.getUsername()%></td>
                <td><%=stu.getAge()%></td>
                <td><%=stu.getScore()%></td>
            </tr>
        <%}%>
    </table>
</body>
</html>