目錄
JSP
JSP簡介:
JSP頁面
JSP運行原理
JSP腳本元素
JAVA程序片
局部變量?
全局變量和方法的聲明
全局變量
方法的聲明
?程序片執行特點
synchronized關鍵字
表達式
JSP指令標記
page指令
include指令
JSP動作標記
?JSP動作元素include和include指令的區別
param動作標記
forward動作標記
?JSP四個主要的內置對象
?request內置對象
※ URL地址重寫
表單
表單操作
GET 方式
POST 方式
GET 和 POST 的區別
response對象
☆頁面跳轉
session對象
?取得Session Id
處理數據
☆“登陸及注銷”模塊
JSP
JSP簡介:
基于B/S模式的網絡程序核心就是設計服務器端的web應用程序。
JSP(Java Server Pages)是基于Java 語言的一種Web應用開發技術,利用這一技術可以建立安全、跨平臺、易維護的動態頁面應用程序。
利用JSP技術,可以實現動態頁面與靜態頁面的分離,便于擴展和維護。
JSP頁面
一個jsp頁面包含:普通的HTML標記符和使用”<%”和” %>”標記符加入的java程序片。
JSP頁面按照文本文件保存,擴展名是.jsp。
JSP運行原理
服務器上的jsp頁面被第一次請求執行時,jsp引擎首先將jsp頁面文件轉換成一個java文件,并編譯這個java文件生成字節碼文件,然后執行字節碼文件響應客戶的請求。
當該jsp頁面再次被請求執行時,JSP引擎將直接執行字節碼文件來響應客戶請求。
如果對jsp頁面進行了修改、保存,服務器將生成新的字節碼文件。
JSP腳本元素
JAVA程序片
在“<%” 和“%>”標記符號間插入Java程序片
Java程序片是指在JSP頁面中使用的Java代碼片段,它們被包圍在<%
和%>
標簽內。這些代碼片段會在服務器端執行,并生成動態內容。程序片可以包含變量聲明、表達式和控制語句
<%
int count = 0;
for (int i = 0; i < 5; i++) {count++;out.println("Hello, World! " + count);
}
%>
在這個例子中,我們聲明了一個整型變量
count
,并在循環中遞增并打印出來。
局部變量?
程序片中聲明的變量稱為JSP頁面的局部變量
局部變量是在方法或程序片中聲明的變量,它的作用域只限于該方法或程序片。一旦方法或程序片結束,局部變量就會被釋放。在JSP中,程序片內的變量就是局部變量,因為它們的作用域僅限于該程序片。
線程安全性:由于JSP頁面可能會并發地被多個線程訪問,因此必須考慮線程安全問題。如果多個線程同時訪問同一個程序片,那么局部變量可能會引發競爭條件。例如,假設兩個線程同時訪問上面的例子,它們都嘗試增加count
的值,但結果可能是不確定的,因為它們可能互相覆蓋對方的結果。
分別在不同的線程中執行:JSP頁面可能會被多個線程并發訪問,這意味著程序片中的代碼可能會在不同的線程中執行。這可能導致一些問題,尤其是涉及到共享資源時。為了避免這些問題,應該避免在程序片中使用全局變量或共享狀態,而是盡可能使用局部變量。
全局變量和方法的聲明
全局變量
在“<%!” 和“%>”標記符號間聲明變量。
在JSP頁面中,成員變量是那些在整個頁面范圍內有效的變量。它們可以在頁面的不同部分被引用,無論<%!
和%>
標記的位置在哪里。
<%
! int counter = 0;
%>
在這個例子中,
counter
就是一個成員變量,它在整個JSP頁面中都是可用的。
變量的有效范圍:成員變量的作用域是整個JSP頁面,這意味著它們可以在頁面的任何地方被訪問。相比之下,局部變量的作用域僅限于它們所在的程序片。
<%
int localCounter = 0;%><%
localCounter++; // 這里無法訪問到 localCounter,因為它是一個局部變量
%>
任何一個用戶對JSP頁面成員變量操作的結果,都會影響到其他用戶。
方法的聲明
在“<%!” 和“%>”標記符號間聲明方法。
在JSP頁面中,可以通過<%!
和%>
標記來聲明方法。這些方法可以在頁面的其他部分被調用
<%
! public String getGreeting() {return "Hello, World!";
}
%>
方法的有效性:聲明的方法在JSP頁面的任何地方都可以被調用,只要它們位于<%!
和%>
標記之間
<%
String greeting = getGreeting();
out.println(greeting);
%>
在這個例子中,我們調用了
getGreeting()
方法并將結果賦給greeting
變量,然后將其打印出來
?方法內的變量:方法內的變量是局部變量,它們的作用域僅限于方法本身。
<%
! public void printMessage() {String message = "Hello, World!";out.println(message);
}
%>
在這個例子中,
message
變量僅在printMessage
方法內有效。一旦方法執行完畢,message
變量就被銷毀
?程序片執行特點
操作JSP頁面的成員變量:成員變量是各線程共享的變量,任何一個線程對JSP頁面成員變量操作的結果,都會影響到其他線程;
調用JSP頁面的方法:調用的方法必須是JSP頁面的方法;
聲明操作局部變量:運行在不同線程中的Java程序片的局部變量互不干擾。
PS:可將操作成員變量的方法用synchronized修飾
synchronized關鍵字
synchronized
關鍵字用于控制多線程并發訪問共享資源的同步。當一個線程正在執行某個被synchronized
修飾的方法或代碼塊時,其他線程必須等待該線程釋放鎖后才能繼續執行。這有助于防止數據不一致性和競態條件等問題。
使用synchronized修飾方法
要使用synchronized
關鍵字,只需在其前面加上即可
public class MyClass {private int count;public synchronized void incrementCount() {count++;}
}
在這個例子中,
incrementCount
方法被synchronized
修飾,意味著同一時間只有一個線程能執行此方法。
?JSP頁面中的synchronized
在JSP頁面中,也可以使用synchronized
關鍵字來保護成員變量
<%
! int counter = 0;
public synchronized void incrementCounter() {counter++;
}
%>
表達式
在“<%=” 和“%>”標記符號間插入表達式。
在JSP頁面中,表達式允許你將Java表達式插入到輸出流中。表達式由<%= %>
標簽包圍,其值會被轉換為字符串并寫入到響應中。
<%= someVariable %>
在這個例子中,
someVariable
是一個Java變量,它的值將在服務器端計算,并作為字符串輸出到客戶端瀏覽器。
字符串化:無論表達式的結果是什么類型,都會自動轉換成字符串。這意味著如果你有一個整數或布爾值,它們將分別被轉換為對應的字符串形式。
<%= 42 %> <!-- 輸出:42 -->
<%= true %> <!-- 輸出:"true" -->
該表達式必須要能求值;
不可以插入語句;
“<%=”是一個完整的符號,“<%”和“=”之間不要有空格;
JSP指令標記
page指令
用來定義或設置整個JSP頁面的一些屬性和屬性值。
<%@ page contentType="text/html;charset=UTF-8" import="java.util.*" language="java" session="false" buffer="none" autoFlush="true" isThreadSafe="false" pageEncoding="UTF-8" %>
設置了多個屬性:
contentType
: 指定生成的HTTP響應的MIME類型和編碼。import
: 導入所需的Java包。language
: 指定腳本語言,默認為Java。session
: 是否啟用會話支持。buffer
: 設置緩沖區大小和策略。autoFlush
: 如果緩沖區已滿是否自動刷新。isThreadSafe
: 是否啟用線程安全性。pageEncoding
: JSP文件本身的編碼。
contentType、import、language、session、buffer、autoFlush、isThreadSafe、pageEncoding
可以用一個page指令指定多個屬性的值,也可以使用多個page指令分別為每個屬性指定值。
page指令的作用對整個頁面有效,與其書寫位置無關
多個屬性
你可以用一個page
指令指定多個屬性,或者使用多個page
指令分別為每個屬性指定值
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page language="java" %>
<%@ page session="false" %>
<%@ page buffer="none" %>
<%@ page autoFlush="true" %>
<%@ page isThreadSafe="false" %>
<%@ page pageEncoding="UTF-8" %>
include指令
include標記的作用是在JSP頁面上出現該指令的位置處靜態嵌入一個文件;
語法格式:
<%@ include file= "文件的URL" %>
注意:被嵌入的文件必須是可訪問和可使用的。嵌入文件后,必須保證新合并成的JSP頁面符合JSP語法規則,能夠成為一個JSP頁面。
示例
假設我們有一個header.jspf
文件,包含了網站的頭部信息:
<header><h1>Welcome to our site!</h1>
</header>
然后,在我們的主頁home.jsp
中,我們可以這樣使用include指令來包含這個文件
<%@ include file="header.jspf" %>
<body>...
</body>
這樣,每次渲染
home.jsp
時,header.jspf
的內容就會被靜態地插入到home.jsp
的相應位置。
JSP動作標記
用來在JSP頁面中動態包含一個文件,包含頁面程序與被包含的文件是彼此獨立的,互不影響。
格式
<jsp:include page= "文件的URL" />
或
<jsp:include page= “文件的URL”>子標記
</jsp:include>
第一種格式是簡化的版本,沒有子標記;第二種格式可以包含一些子標記,比如
flush
和includeParameter
等。
?JSP動作元素include和include指令的區別
處理方式和處理時間上是不同的。
指令標記是在編譯階段就處理所需的文件,被處理的文件在邏輯上和語法上依賴于當前JSP頁面,優點是執行速度快。
動作標記是在JSP頁面運行時才處理文件,被處理的文件在邏輯上和語法上獨立于當前JSP頁面,優點是可以使用param子標記來傳參數
param動作標記
JSP動作標記<jsp:param>
以“名字-值”的形式為其他標記提供附加信息。它不能單獨使用,必須作為<jsp:include>
或<jsp:forward>
標記的子標記來使用。
格式
<jsp:param name= "屬性名字" value= "屬性的值" />
使用場景
和<jsp:include>
標記一起使用時,<jsp:param>
將param的值傳遞到include
指令要加載的文件中去。例如:
<jsp:include page= "文件的URL"><jsp:param name= "name" value= "value"/>
</jsp:include>
forward動作標記
這個動作標記用于在服務器端將請求從當前頁面重定向到另一個頁面。
- 簡單的
<jsp:forward>
標記,不包含任何子標記:<jsp:forward page="要轉向的頁面" />
- 帶有
<jsp:param>
子標記的<jsp:forward>
標記,可以傳遞參數給目標頁面:<jsp:forward page="要轉向的頁面"><jsp:param name="paramName1" value="paramValue1" /><jsp:param name="paramName2" value="paramValue2" /> </jsp:forward>
page
屬性指定了要跳轉的目標頁面的URL。<jsp:param>
子標記用于向目標頁面傳遞參數,每個<jsp:param>
都有一個name
和一個value
屬性,分別表示參數名和參數值。
?簡單的示例,展示了如何使用<jsp:forward>
動作標記來實現頁面跳轉:
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>首頁 - 頁面跳轉示例</title>
</head>
<body><h1>歡迎來到首頁!</h1><form action="forward.jsp" method="post"><input type="submit" value="點擊跳轉到目標頁面"></form>
</body>
</html>
forward.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>目標頁面 - 頁面跳轉示例</title>
</head>
<body><%// 獲取傳遞過來的參數String param1 = request.getParameter("param1");String param2 = request.getParameter("param2");%><h1>歡迎來到目標頁面!</h1><p>參數1: <%= param1 %> </p><p>參數2: <%= param2 %> </p>
</body>
</html>
在這個示例中,用戶首先訪問
index.jsp
頁面,然后點擊提交按鈕觸發POST請求,該請求被轉發到forward.jsp
頁面。在forward.jsp
頁面中,我們可以通過request.getParameter()
方法獲取傳遞過來的參數并顯示出來。
?補充:超鏈接 <a>
標簽是可以傳遞參數的。通常情況下,我們在超鏈接的 href
屬性中指定目標 URL,并且可以在 URL 中添加查詢字符串來傳遞參數。
<a href="http://example.com/page?param1=value1¶m2=value2">點擊這里傳遞參數</a>
當用戶點擊這個超鏈接時,瀏覽器會導航到 "http://example.com/page" 并且攜帶兩個參數:
param1
和param2
。這些參數會在目標頁面通過GET
請求的方式發送給服務器。
?JSP四個主要的內置對象
在 JSP(JavaServer Pages)中,提供了四種不同的范圍來保存屬性(對象),這使得開發者能夠控制一個設置的對象能夠在多少個頁面中保存并繼續使用。這四種屬性范圍分別是:
- PageContext(page)范圍:只在一個頁面中保存屬性,跳轉之后無效。
- Request(request)范圍:只在一次請求中保存,服務器跳轉后依然有效。
- Session(session)范圍:在一次會話范圍內,無論何種跳轉都可以使用,有一定的存活周期。
? ? ? ?
- Application(application)范圍:在整個服務器上保存,所有用戶都可以使用。
?request內置對象
request
內置對象是最常用的一個對象之一,它代表客戶端發送的 HTTP 請求信息。
request
對象是由容器(如 Tomcat)自動創建的,它是 javax.servlet.http.HttpServletRequest
接口的實例化對象,主要用于接收客戶端發送來的請求信息,包括請求參數、頭信息等。HttpServletRequest
是 Servlet API
提供的一個接口,繼承自 ServletRequest
接口。
常見的 request
內置對象的方法及其用途:
- 獲取請求參數:
String getParameter(String name)
?—— 返回與指定名稱關聯的請求參數的值。- 獲取所有請求參數:
Map<String, String[]> getParameterMap()
?—— 返回一個 Map,其中鍵是參數名,值是參數值數組。- 獲取請求頭信息:
String getHeader(String name)
?—— 返回與指定名稱關聯的請求頭的值。- 獲取請求方式:
String getMethod()
?—— 返回請求的類型(如 GET、POST 等)。- 獲取請求路徑:
String getRequestURI()
?—— 返回請求的 URI。- 獲取請求的上下文路徑:
String getContextPath()
?—— 返回應用程序的上下文路徑。- 獲取請求的本地地址:
String getLocalAddr()
?—— 返回客戶端的 IP 地址。- 獲取請求的本地端口號:
int getLocalPort()
?—— 返回客戶端的端口號。
?簡單的 JSP 示例,展示了如何使用 request
對象獲取請求
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>request內置對象示例</title>
</head>
<body><form action="request_example.jsp" method="post">用戶名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br><input type="submit" value="提交"></form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>request內置對象示例結果</title>
</head>
<body><%@ page import="java.util.Map.Entry" %><%-- 使用EL表達式 --%><%out.println("<p>用戶名:" + request.getParameter("username") + "</p>");out.println("<p>密碼:" + request.getParameter("password") + "</p>");// 使用腳本元素for (Entry<String, String[]> entry : request.getParameterMap().entrySet()) {out.println("<p>" + entry.getKey() + ": ");for (String value : entry.getValue()) {out.println(value + " ");}out.println("</p>");}%>
</body>
</html>
我們創建了一個表單,包含了兩個輸入字段:用戶名和密碼。當用戶提交表單時,請求會被發送到
request_example.jsp
頁面。在request_example.jsp
頁面中,我們可以使用request
對象的getParameter()
方法來獲取表單中的參數值,并打印出來。
當使用 request
對象從客戶端接收漢字字符時,可能會遇到亂碼問題。這是因為在傳輸過程中,數據編碼格式不同導致的。要解決這個問題,我們需要設置正確的字符編碼。具體來說,你需要在讀取請求參數之前調用 request.setCharacterEncoding()
方法,設置合適的字符集。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>亂碼解決示例</title>
</head>
<body><form action="charset_example.jsp" method="post">姓名:<input type="text" name="name"><br><input type="submit" value="提交"></form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>亂碼解決結果</title>
</head>
<body><%@ page import="java.util.Map.Entry" %><%-- 使用腳本元素 --%><%request.setCharacterEncoding("GB2312"); // 設置字符編碼String name = request.getParameter("name");out.println("<p>姓名:" + name + "</p>");%>
</body>
</html>
※ URL地址重寫
URL 地址重寫是一種通過 URL 來傳遞參數的方法,而不是使用表單或 POST 請求。這種方法可以用來傳遞簡單的參數,比如查詢字符串。在 JSP 或者其他 Web 開發框架中,你可以直接在 URL 后面添加參數,然后在目標頁面獲取這些參數
地址重寫的格式如下:
????? 動態頁面地址?參數名稱1=參數內容1&參數名稱2=參數2&…所有參數與之前的地址之間用“?”分離,然后按照“參數名稱=參數內容” 的格式傳遞參數,多個參數之間用“&”分離。
?假設你有一個動態頁面 dynamic_page.jsp
,并且你想向其傳遞兩個參數:name
和 age
。你可以像這樣構造 URL
http://yourwebsite.com/dynamic_page.jsp?name=John&age=30
在這個 URL 中,
?
符號后面是參數部分,name
和age
是參數名稱,而John
和30
分別是對應的參數值。多個參數之間由&
符號分隔
?在 dynamic_page.jsp
頁面中,你可以使用 request
對象的 getParameter()
方法來獲取這些參數
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>URL 重寫示例</title>
</head>
<body><%@ page import="java.util.Map.Entry" %><%-- 使用腳本元素 --%><%String name = request.getParameter("name");int age = Integer.parseInt(request.getParameter("age"));out.println("<p>姓名:" + name + "</p>");out.println("<p>年齡:" + age + "</p>");%>
</body>
</html>
在這個示例中,我們假設
age
參數是一個整數。如果你訪問上面提到的 URL,頁面將會顯示傳入的參數值。
表單
表單(Form)是網頁中用于收集用戶輸入信息的重要組成部分。在Web開發中,表單允許用戶輸入數據,然后將這些數據發送給服務器進行處理。HTML表單由各種表單控件組成,包括輸入字段(如文本框、密碼框)、按鈕、下拉列表、復選框、單選按鈕等。以下是一些關于HTML表單的關鍵概念和代碼示例:
表單標簽(<form>
):表單的結構通常由<form>
標簽開始,</form>
標簽結束。<form>
標簽有一些重要的屬性,包括:
action
:定義處理表單數據的服務器端程序的URL。method
:定義如何將表單數據發送到服務器,通常是GET
或POST
。enctype
:定義表單數據的編碼方式,主要在上傳文件時使用。
輸入控件(Input Controls):輸入控件用于捕獲用戶的輸入。常見的輸入控件有:
<input type="text">
:文本輸入框。<input type="password">
:密碼輸入框。<input type="radio">
:單選按鈕。<input type="checkbox">
:復選框。<select>
:下拉列表。<textarea>
:多行文本輸入框。
按鈕(Buttons):按鈕用于觸發表單的提交或重置操作:
<input type="submit">
:提交按鈕。<input type="reset">
:重置按鈕,清空表單數據。<button>
:通用按鈕,可以綁定JavaScript事件。
基本的HTML表單示例:
<!DOCTYPE html>
<html>
<head>
<title>簡單表單示例</title>
</head>
<body><form action="/submit_form" method="post">姓名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br>性別:<input type="radio" name="gender" value="male">男<input type="radio" name="gender" value="female">女<br>愛好:<input type="checkbox" name="hobbies" value="reading">閱讀<input type="checkbox" name="hobbies" value="music">音樂<input type="checkbox" name="hobbies" value="sports">運動<br>描述:<textarea name="description" rows="4" cols="50"></textarea><br><input type="submit" value="提交">
</form></body>
</html>
表單操作
<form>
標簽用于創建表單,其中最重要的屬性之一是 method
屬性,它決定了表單數據如何被發送到服務器。有兩種主要的提交方式:GET
和 POST
。
GET 方式
GET
提交方式會在 URL 后面附加一個問號(?
),接著是鍵值對的形式,多個鍵值對之間用 &
分隔。這種提交方式適用于小型數據量的請求,而且在地址欄中可以看到所有提交的內容。
<form action="submit.php" method="get">姓名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br><input type="submit" value="提交">
</form>
當你提交此表單時,瀏覽器將在 URL 后面附加類似這樣的內容
http://yourwebsite.com/submit.php?username=John&password=123456
POST 方式
POST
提交方式不會在地址欄顯示提交的內容,而是將數據作為 HTTP 請求體的一部分發送到服務器。這種方式更適合大型數據量的請求,特別是包含敏感信息的場景。
<form action="submit.php" method="post">姓名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br><input type="submit" value="提交">
</form>
在這種情況下,提交后 URL 不會發生變化,但服務器可以通過
$_POST['username']
和$_POST['password']
獲取相應的值。
GET 和 POST 的區別
- 數據可見性:GET 提交的內容會顯示在地址欄,而 POST 不會。
- 數據大小限制:GET 請求在地址欄上顯示的信息長度有限制(約 4~5KB),而 POST 可以提交更多的內容,如大文本和圖片數據。
- 安全性:POST 更加安全,因為它不會在地址欄顯示敏感信息。
- 緩存:GET 請求可以被緩存,而 POST 請求不能。
- 書簽:GET 請求可以保存為書簽,而 POST 請求不可以。
JSP 中的處理
在 JSP 中,你可以使用 request.getParameter()
方法來獲取表單數據。以下是一個簡單的示例,展示如何處理 GET 和 POST 請求
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>表單操作示例</title>
</head>
<body><%@ page import="java.util.Map.Entry" %><%-- 使用腳本元素 --%><%if ("POST".equals(request.getMethod())) {String username = request.getParameter("username");String password = request.getParameter("password");out.println("<p>姓名:" + username + "</p>");out.println("<p>密碼:" + password + "</p>");} else if ("GET".equals(request.getMethod())) {String username = request.getParameter("username");String password = request.getParameter("password");out.println("<p>姓名:" + username + "</p>");out.println("<p>密碼:" + password + "</p>");}%>
</body>
</html>
response對象
response
對象是 Java Servlet 技術中的一個重要對象,它代表了服務器對客戶端的響應。response
對象的主要作用是將服務器處理后的結果返回給客戶端。response
對象屬于 javax.servlet.http.HttpServletResponse
接口的實例,該接口繼承自 javax.servlet.ServletResponse
接口。
HttpServletResponse
接口定義了一些常用的方法
public interface HttpServletResponse extends ServletResponse {void addCookie(Cookie cookie);void sendRedirect(String location) throws IOException;void setHeader(String name, String value);void setDateHeader(String name, long date);void setContentType(String type);void setStatus(int sc);
}
public void addCookie(Cookie cookie)方法用于向客戶端發送 Cookie。
Cookie cookie = new Cookie("key", "value");
response.addCookie(cookie);
public void setHeader(String name,String value)方法用于設置響應頭,例如設置 Content-Type。
response.setContentType("text/html;charset=utf-8");
public void sendRedirect(String location) throws IOException方法用于重定向到另一個頁面。
response.sendRedirect("/new_location");
☆頁面跳轉
JSP中,我們可以通過兩種方式實現頁面跳轉:
一種是使用頭信息的方式完成跳轉
<%response.setHeader("Refresh", "2;URL=yourPage.jsp");
%>
我們在服務器端設置了一個響應頭"Refresh",其值為"2;URL=yourPage.jsp"。這意味著在兩秒后,瀏覽器將自動跳轉到yourPage.jsp頁面。?
另一種則是通過response對象的sendRedirect()方法直接完成頁面的跳轉(屬于客戶端跳轉)
<%response.sendRedirect("yourPage.jsp");
%>
我們調用了response對象的sendRedirect()方法,傳入了要跳轉的目標頁面地址。這個方法會向客戶端發送一個302臨時重定向響應,告訴客戶端需要跳轉到新的位置。
注意的是:這兩種跳轉方式有所不同。使用頭信息的方式屬于服務器端跳轉,而使用sendRedirect()方法則屬于客戶端跳轉。服務器端跳轉時,瀏覽器不會看到實際的URL變化,因為所有的處理都在服務器端完成;而在客戶端跳轉時,瀏覽器可以看到URL的變化,因為它實際上是重新發起了一個新的HTTP請求。
此外,客戶端跳轉的一個缺點是它可能會導致數據丟失。例如,在表單提交之后再進行客戶端跳轉,那么用戶輸入的數據將會丟失。因此,在某些情況下,可能更傾向于使用服務器端跳轉。
session對象
session對象是Java Web開發中的一個重要概念,主要用于管理用戶的會話狀態。在Web應用中,每個用戶訪問網站時都會產生一個唯一的session對象,用于存儲和獲取該用戶的相關信息。
在開發中,session對象最常見的用途就是完成用戶的登錄、注銷等常見功能。當用戶成功登錄后,我們可以把用戶的一些基本信息存放到session中,如用戶名、角色等。這樣,在后續的頁面訪問過程中,就可以通過檢查session中的這些信息來判斷當前用戶是否已經登錄以及他的權限等級等。
簡單的示例,演示了如何創建并使用session對象
import javax.servlet.http.HttpSession;// 在Servlet類中獲取session對象
HttpSession session = request.getSession();// 創建一個新的屬性并賦值給session
String username = "John Doe";
session.setAttribute("username", username);// 獲取之前設置的屬性
String retrievedUsername = (String) session.getAttribute("username");// 輸出結果
System.out.println("Retrieved username from session: " + retrievedUsername);
首先從HttpServletRequest對象中獲取到了一個session對象。然后,我們將字符串"John Doe"保存到了session對象中,鍵為"username"。最后,我們又從session中取出了之前設置的屬性,并打印出來。
?取得Session Id
ession是一種用來跟蹤用戶狀態的技術。當一個用戶連接到服務器之后,服務器會為其分配一個唯一的Session Id,這個Id通常是一串隨機生成的字符串。服務器依靠這些不同的Session Id來區分每一個不同的用戶。
Session Id通常是通過cookie存儲在客戶端的,每次客戶端發起請求的時候,都會帶上這個Session Id,服務器通過解析這個Id來識別用戶的身份。
如何獲取Session Id
import javax.servlet.http.HttpSession;public class SessionIdExample {public void getSessionId(HttpSession session) {String sessionId = session.getId();System.out.println("Session Id is: " + sessionId);}
}
首先從HttpServletRequest對象中獲取到了一個session對象,然后調用getId()方法獲取Session Id,并將其打印出來。
注意:?
Session Id是由服務器自動生成的,開發者不能手動修改。而且,一旦Session被創建,它的Id就不會改變,除非Session過期或者被顯式地銷毀。
另外,雖然Session Id是通過cookie傳遞的,但是如果你的應用需要支持那些不支持cookie的瀏覽器,你也可以選擇通過URL重寫的方式來傳遞Session Id。這種方式下,服務器會在URL后面添加一個參數,用來攜帶Session Id。
處理數據
session對象提供了兩個主要的方法來處理數據:setAttribute(String key, Object obj) 和 getAttribute(String key)。
1.setAttribute(String key, Object obj): 這個方法用于將指定的對象obj添加到session對象中,并為添加的對象指定一個索引關鍵字key。如果添加的兩個對象的關鍵字相同,則先前添加的對象會被清除。這是一個非常有用的功能,因為我們經常需要在用戶會話期間存儲一些數據,比如用戶ID、購物車信息等等
HttpSession session = request.getSession();
session.setAttribute("userId", 123); // 將用戶ID存儲在session中
2.getAttribute(String key): 這個方法用于獲取session對象含有的關鍵字是key的對象。由于任何對象都可以添加到session對象中,因此用該方法取回對象時,應強制轉化為原來的類型。
HttpSession session = request.getSession();
int userId = (Integer) session.getAttribute("userId"); // 取出用戶ID
注意,當我們使用getAttributes()方法取出對象時,我們需要進行類型轉換,這是因為getAttribute()返回的是Object類型的對象,所以我們需要將其轉換為我們期望的類型。
☆“登陸及注銷”模塊
?session對象常常被用來實現用戶登陸及注銷的功能。具體來說,當用戶成功登陸后,我們會將一些關鍵信息(如用戶名、用戶ID等)存儲在session中,以便在后續的請求中驗證用戶身份。同時,我們還可以提供一個注銷功能,讓用戶能夠結束自己的會話。
實現:
? 當用戶登陸成功之后,設置一個 session 范圍的屬性,之后在其他需要驗證的頁面中判斷是否存在此 session 范圍的屬性 :
1 、 如果存在 ,則表示已經是正常登陸過的合法用戶, 2 、 如果不存在 ,則給出提示,并跳轉回登陸頁提示用戶重新登陸,用戶登陸之后可以進行注銷的操作。
- 登陸頁login.jsp
<form action="LoginServlet" method="post">用戶名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br><input type="submit" value="登陸"> </form>
- LoginServlet.java
import javax.servlet.http.HttpSession; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;@WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");if (checkUser(username, password)) { // 檢查用戶是否存在HttpSession session = request.getSession();session.setAttribute("currentUser", username); // 存儲用戶信息到sessionresponse.sendRedirect("welcome.jsp"); // 跳轉到歡迎頁面} else {request.getRequestDispatcher("login.jsp").forward(request, response); // 如果用戶不存在,繼續停留在登陸頁面}}private boolean checkUser(String username, String password) {// 假設這里是對數據庫的查詢,判斷用戶是否存在return true;} }
?????????3.welcome.jsp
<%@ page import="javax.servlet.http.HttpSession" %>
<%HttpSession session = request.getSession();String currentUser = (String) session.getAttribute("currentUser");if (currentUser == null) {response.sendRedirect("login.jsp"); // 如果session中沒有用戶信息,表示未登陸,跳轉到登陸頁面}
%>
<h1>歡迎 <%= currentUser %>!</h1>
<a href="LogoutServlet">注銷</a>
? ? ? ? ?4.LogoutServlet.java
import javax.servlet.http.HttpSession;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {HttpSession session = request.getSession();session.invalidate(); // 注銷sessionresponse.sendRedirect("login.jsp"); // 跳轉到登陸頁面}
}