適用學習 對象 : java的 初學者 僅供參考-----------
開發 工具 idea ---- jdk8 ------ javaEE7 服務器tomcat 8.5
涉及javaWeb 基礎 : session request response
有圖 有碼
分析 需求
:使用jsp來實現的 驗證碼 的 實現 : login.jsp ------ LoginServlet -----
login.jsp -----------
form table 表單 : tr —td
======& jsp的預覽 要在 服務器 裏 運行 :
--------- action 的請求的 是 :
servlet :---------- LoginSrevlet ---------
設置請求request的 編碼 :
所有的 request 的參數:
獲取驗證碼 ??
將 用戶用戶的 信息
5 判斷 用戶
信息的 封裝到user 對象 裏
session
判斷 用戶 的 獲取 程序 生成驗證碼 : 與 用戶輸入 是否 保持一致
先判斷 驗證碼 在 判斷 用戶 :減少 的 數據庫 的訪問次數的 壓力
if 一致 :
if 用戶名與密碼
正確就 的登錄成功
else
1: 給提示
2: 重定向到登錄頁面 ========= 重定向
這裏 轉發到Session 裏 也是可以 的
----- 門都 沒有進 就得重來 了-------
else 不一致 :
1: 提示驗證 錯誤的 信息
2: 轉發 跳轉到 登錄頁面 裏 ========= 轉發
錯誤信息 只在jsp 裏共享-----v 一次request 裏 無需其他人知道
只是 起碼都登錄 了 驗證碼的錯誤
- 涉及
一個轉發與 重定向 是的 區別 :
關於request 與的 使用與否
request 域裏就會 用轉發 其他的就是 重定向
使用 中 路徑與否:
轉發---相對路徑 重定向---絕對路徑
---- 關於域對象的 使用場景 :
用戶名 與登錄 會 經常的使用 存在 Session 裏 ------
具體實施 : 將原來 一邊寫好 驗證碼的 servlet、 粘貼過來 :
據需要在 的改進 : 使用個的是StringBuild =====
生成 驗證碼 在Session域 裏 域 ------ 操作方法 Attribute
防止空指針異常 ---=========
驗證碼忽略大小寫 -------
-
注意 :
form 表單 提交到servlet 裏
先判斷 :驗證碼錯誤就少判斷一次數據庫
也許: 可能看不出來的 ------ null 值得判斷 :sjp 裏直接的就進行的 三元判斷式 ******* 用一次就是失效 : 前面一點獲取就 後面就會 removeAttribute() 是的 使用
============ 編碼的實施 ===============
-
創建前端頁面 :
--- from 表單的額 action 到指定的 servlet 裏 method= post ---table 表格 裏 tr -- td 裏input Type與name 的屬性的 定義 --- 分別定義的的是 ; ----- ----用戶名 type text ----密碼 type password ---- 驗證碼 type text ----img ----td 的 colspan=2 跨2行 ---- 圖片 : img 的id =“img” src =“指定的servlet” ---- submit -----value:“登錄” td 的 colspan=2 跨2行
-
使用js 來進行 切換 驗證碼 :
Windows 調用 onload 的回調函數 ‘function(){} 裏’
通過id 獲取標籤體 :getElementById(“img”)onlick=function(){
this 調用當前的獲取的標籤體的img
調用src 指定的 方法 裏 拼接time 值參數 的時間戳 ?time”+:
new Date().getTime()
----- 後端的繼續編寫 ---------------
創建servlet 頁面 :
獲取所有請求的參數 :request.getPrimaterMap()
獲取Map --- 操作數據庫 來做 ======
這不用數據庫的操作 ---- 需要你 完善 數據庫的
分別 獲取參數 的:
request.getParameter(“ username ”) 。。password 。。checkCode。。
---- 因爲 是2次請求 : from表單裏面 的 增加 驗證碼 的這次請求
將生成的碼值 儲存 到 Session 裏 ------- 然後 在 loginServlet 裏 對比判斷 即可
CheckCodeServlet 裏 ==========
用StringBuild 的 append( )方法 來咋for 裏 進行拼接 ---
--- 用 toString () 轉爲字符串 :
// 存入session 裏 : ----
request.getSession().setAttribute("",""); 鍵 定義名稱 ,
值 就是---- StringBuild 的值
loginServlet 裏 :========== 繼續
獲取Session的 域裏 儲存的 剛纔的 生成 的 驗證碼 ;
--- request.getSession().getAttribuet("參數名稱") ;
----- 返回一個 object對象 強轉爲 String:
忽略大小寫的 的equalsIgnoreCaes(checkCode)
–### 重定向 範圍 域 基於Session 域 :
setAttribute(“”username)
--### 重定向 到 成功的頁面 : 參數裏 ----獲取 虛擬路徑 的方法 request.getContextPath()+
-----else :
轉發的域 基於request 域裏 ----- setAttribute()設置鍵值對的信息 : 轉發到登錄 頁面 :
轉發:
request.getRequestDispatcher("").forward();
---- 轉發的不寫 虛擬路徑 :
----- – 寫到這裏 就要準備 success.jspde信息 : 是 :
<h1><%=request.getSession().getAttribute("user")%>歡迎你</h1> 這裏的 user 就是 要儲存的 信息
------ 然後 在login.jsp 裏 :----------------------------
-----編寫的的2個div
獲取2次判斷 爲錯誤 的 Attribute 裏的 信息
效果 : 對於的用戶名與 密碼名 的 驗證碼 輸入的錯誤的提示 :
test 測試 : ===============================
要優化的 的是
------ 在login。jsp 裏做到的
1:---- null 的顯示的 優化 : 使用 三元表達式 在login 的 這 裏
三元表達式的 格式 : ?:
----- 2元 以 ? 問號的左右爲 前後條件 條件邏輯
----- 的前置成立 就執行 ?問號後面的: 冒號 爲else 的條件
2: 驗證碼的優化 --------
bug描述 : 瀏覽器裏 當前已經登錄 後 當我們 建點擊瀏覽器裏 後退的 的時候 依然還是可以登錄的
3: 然後要設置的 是: 空指針異常的 判斷 字符串!=null
=============
完整代碼 呈現
前端的代碼的 呈現 —============
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script>
window.onload=function () {
document.getElementById("img").onclick=function () {
this.src="/fhw/image01?time="+new Date().getTime();
}
}
</script>
<style>
div{
color:firebrick;
}
</style>
</head>
<body>
<form action="/fhw/loginServlet" method="post">
<table>
<tr>
<td>用戶名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密碼</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>驗證碼</td>
<td><input type="text" name="checkCode"></td>
</tr>
<tr>
<td colspan="2"><img id="img" src="/fhw/image01"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登錄"></td>
</tr>
</table>
</form>
<%-- 直接用CSS 獲取標籤 給紅色是的指示 --%>
驗證碼的servlet ===================
package com.fhw.web.yanzhengma;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//response.setContentType("text/html;charset=utf-8");
/* 已知在前端裏 請求到 的 參數在request 域 裏 在數據庫 裏直接的 所有的請求 當前不用數據庫的 就直接 進行的 */
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
// 去 CheckCode 使用 改進獲取 生成的 驗證碼 數據存儲 到Session裏 ===
// 然後在 當前 Session 裏獲取 到 驗證碼 進行判斷
HttpSession session = request.getSession();
String checkCoder_session = (String) session.getAttribute("check_code");
session.removeAttribute("check_code");// 每次都是一個 新的
// session 與的裏獲取生成的 驗證碼 equals 客戶端裏請求request 域 比較
if (checkCoder_session!=null && checkCoder_session.equalsIgnoreCase(checkCode)){
// 空指針異常的 判斷 && 忽略 大小寫,的比較
// 驗證碼正確
// 判斷用戶的 和密碼 是否一致 : else :重定向 到
if ("fhw".equals(username)&&"123".equals(password)){//需要UserDao 到數據庫 裏
// 登錄成功 : 重定向 :
session.setAttribute("user",username);
response.sendRedirect(request.getContextPath()+"/successLogin.jsp");
}else{//登錄失敗
request.setAttribute("login_error","用戶或密碼名錯誤");
//轉發到頁面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}else{// --------登錄頁面
request.setAttribute("cc_error","驗證碼錯誤");
//轉發到頁面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
this.doPost(request, response);
}
}
登錄的loginservlet ===========
package com.fhw.web.yanzhengma;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//response.setContentType("text/html;charset=utf-8");
/* 已知在前端裏 請求到 的 參數在request 域 裏 在數據庫 裏直接的 所有的請求 當前不用數據庫的 就直接 進行的 */
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
// 去 CheckCode 使用 改進獲取 生成的 驗證碼 數據存儲 到Session裏 ===
// 然後在 當前 Session 裏獲取 到 驗證碼 進行判斷
HttpSession session = request.getSession();
String checkCoder_session = (String) session.getAttribute("check_code");
session.removeAttribute("check_code");// 每次都是一個 新的
// session 與的裏獲取生成的 驗證碼 equals 客戶端裏請求request 域 比較
if (checkCoder_session!=null && checkCoder_session.equalsIgnoreCase(checkCode)){
// 空指針異常的 判斷 && 忽略 大小寫,的比較
// 驗證碼正確
// 判斷用戶的 和密碼 是否一致 : else :重定向 到
if ("fhw".equals(username)&&"123".equals(password)){//需要UserDao 到數據庫 裏
// 登錄成功 : 重定向 :
session.setAttribute("user",username);
response.sendRedirect(request.getContextPath()+"/successLogin.jsp");
}else{//登錄失敗
request.setAttribute("login_error","用戶或密碼名錯誤");
//轉發到頁面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}else{// --------登錄頁面
request.setAttribute("cc_error","驗證碼錯誤");
//轉發到頁面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
this.doPost(request, response);
}
}
success 成功 前端頁面 :
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1><%=request.getSession().getAttribute("user")%>歡迎你</h1>
</body>
</html>
============== 總結的提問 : ??? 用Session ==============
生成驗證碼 放到Session 域 裏 的 原因 :
每次請求是可以 共享
request 域 i是 : 客戶端每次輸入的 請求:--- 在request 裏 用 parameter ()
?用Attribute 也可以嗎 ??????
請求request 參數裏的額 驗證碼: 客戶端 === 再 對比 ===
Session 域 服務器 裏的servlet 類生成 的驗證碼:
========= 形成驗證的
=============Attribute 與 parameter 的區別 =========
------ Attribute(服務端 屬性 : 4個域 中 的信息)
------ parameter(客戶端 參數:get方法:URL post 請求是request請求體)
來源:
parameter參數()-----客戶端(瀏覽器)由用戶提供的,若是GET方法是從
URL中 提供的,若是POST方法是從請求體(request body)中提供的;
Attribute-屬性----服務器端 組件(JSP或者Servlet)利用requst.setAttribute() 設置的
操作:
parameter參數--------值---只能讀取不能修改,get讀取用request.getParameter();
Attribute屬性------值---既可以讀取亦可以修改,讀取可以使用request.setAttribute(),設置可使用request.getAttribute()
數據:
parameter參數--------String類型看待,並且客戶端的參數值只能是簡單類型的值,不能是複雜類型,比如對象。
Attribute 屬性--------值可以是任意一個Object類型。
共同點
二者的值都被封裝在request對象中。
============
request 是在 客戶端嗎
:============
不是 : request 是 服務器 創建 實現 HttpServlet 的HttpservletRequest類 -- 肯定在 服務端 裏
用來 在servlet 頁面 ==編寫程序 獲取客戶端 請求 的參數 :
----- 而 response 同樣也是這樣的
客戶端 裏Cookie 的都是怎樣的 :==========
有Cookie 信息 java web 裏 在servlet 頁面裏 創建的 Cookie
操作Cookie getName setValie Cookie 鍵,值 setMaxAge()裏通過毫秒值的 正數 : 負數 一次性(Cookie的默認, 零0 就是刪除
Cookie只能 侷限: 存儲 字符串, 大小有限 ,信息不安全,
cookie 就是 客戶端的 請求 ;-------人機交流的基本就是 字符串 來進行的
寫到cookie 在 到Session 的 :
Session 就是 基於Cookie 來的id 來創建 在服務端 的
細緻的: 初次請求有了Cookie信息 : 請求 到了 服務端裏 服務器會根據 請求裏的
cookie id 創建Session 建立本次會話
第一次請求 與 響應就 建立了 本次回話 的初始化
【基於】cookie與Session組成立 web的 會話 :
本次 會話 灰有許多 的請求 與響應(交流) : 每次 有求必應
==