request
生命周期:
- 創建:客戶端向服務器發送一次請求,服務器就會創建request對象.
- 銷毀:服務器對這次請求作出響應后就會銷毀request對象.
有效:僅在當前請求中有效。
作用:常用於服務器間同一請求不同頁面之間的參數傳遞,常應用於表單的控件值傳遞。
- 獲取表單提交參數:
request.getParameter()
//從login.jsp中獲取用戶名和密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
String imageText = request.getParameter("imageText");
- 傳值到表單:
request.setAttribute()
if(user == null) {
//用戶名和密碼不匹配
request.setAttribute("msg", "用戶名和密碼不匹配!");
return “/jsp/login.jsp”;
}
請求轉發與請求重定向
jsp 或 Servlet 都會用到頁面跳轉,可以用
request.getRequestDispatcher("p3.jsp").forward(request,response);
這種方法稱為轉發,地址欄上的 URL 不會改變;
response.sendRedirect("p3.jsp");
這種方法稱為重定向,地址欄的 URL 會改變;
這樣實現跳轉到 p3.jsp。可是這兩種方法有着本質的不同,requset 是請求,是在服務器端運行的,response 是響應,是在客戶端運行的;
例如:
有 3 個頁面 p1.jsp,p2.jsp,p3.jsp;
p1.jsp 提交給 p2.jsp, p2.jsp 在轉發給 p3.jsp
轉發(forward):
如果在 p2 用轉發發到 p3,由於是瀏覽器請求的是 p2,請求的一些參數被封裝在 request 中,發給服務器,服務器用request.getRequestDispatcher("p3.jsp").forward(request,response);
轉到 p3,服務器把 p3 發給瀏覽器,瀏覽器不知道被偷梁換柱了,所以 URL 沒變,URL 還是 p2.jsp;也完全可以用request.getParameter("name");
得到 p1.jsp 中的表單控件的值,因為在這里用了 forward() 把 request 傳了下去注意:轉發是在服務器中進行請求轉發,由於是同一個請求轉發,所以 URL 並沒有改變,請求域也是相同的。
重定向(redirect):
如用第二種方法,這是瀏覽器主動請求了 p3,所以瀏覽器知道請求的地址,所以 URL 變了,
而又一次請求,產生了另外一個 request,這個和請求 p2 的 request 不同,所以在 p3 中用request.getParameter("name");
得不到 p1.jsp 中的表單控件的值。注意:重定向是在瀏覽器中進行請求重定向,瀏覽器將請求重新定向到一個新的位置,發了一個新的請求,所以是不同的請求,URL 改變了,請求域也並不相同。
總結:
request.getRequestDispatcher("a.jsp").forward(rquest,response);
request 轉發,它可以保存 request 中的數據,頁面調整,但是地址是不調整的response.sendRedirect("b.jsp");
方式是重定向,它的數據是不共享的,也就是說,request 中保存的數據在 b.jsp 頁面中是獲取不到的 這種方式是表單是不能重復提交的,response 跳轉是可以實現跨域的 地址欄也會變化。
session
適用場景:登錄時,存取登錄的用戶信息,達到用戶信息跨頁面共享的效果。
后端:HttpSession session,session.setAttribute("stu", stu)
前端:${session['stu'].name}
生命周期:
創建:服務器端第一次調用
getSession();
(保存在服務器內存中)解釋 session:當訪問服務器某個網頁的時候,會在服務器端的內存里開辟一塊內存,這塊內存就叫做session,而這個內存是跟瀏覽器關聯在一起的。當訪問一個頁面的時候給瀏覽器創建一個獨一無二的號碼,也給同時創建的session賦予同樣的號碼。這個瀏覽器指的是瀏覽器窗口,或者是瀏覽器的子窗口,意思就是,只允許當前這個session對應的瀏覽器訪問,就算是在同一個機器上新啟的瀏覽器也是無法訪問的。而另外一個瀏覽器也需要記錄session的話,就會再啟一個屬於自己的session
- 銷毀:
非正常關閉服務器(正常關閉 session 會序列化,再次啟動服務器 session 會被反序列化);
注意:服務器正常關閉,再啟動,Session 對象會進行鈍化和活化操作。同時如果服務器鈍化的時間在 session 默認銷毀時間之內,則活化后 session 還是存在的。否則 Session 不存在。 如果 JavaBean 數據在 session 鈍化時,沒有實現 Serializable 則當 Session 活化時,會消失。
- session 過期了默認30分鍾;
- 手動調用
session.invalidate();
關閉瀏覽器。
注意:關閉瀏覽器再次訪問會找不到 session 的會話 id 而不是 session 被銷毀了。
備注:session 是服務器端對象,保存在服務器端。並且服務器可以將創建 session 后產生的 sessionid 通過一個 cookie 返回給客戶端,以便下次驗證。(session 底層依賴於 cookie)
有效:用戶打開瀏覽器會話開始,直到關閉瀏覽器會話才會結束。一次會話期間只會創建一個session對象。
注意:只關閉標簽頁的話,session 狀態是還在的。要完全關閉瀏覽器后,重新打開才會啟用新的 session。
session 有自身的生命周期,如一定的時間內不再激活的話就會過期,被服務器注銷。
session 是基於 cookie 的一種會話技術,數據存放存放在服務器端。客戶端在 cookie 攜帶 JSESSIONID(tomcat服務器生成),來訪問服務端,獲取對應 JSESSIONID 的 session 數據。
問題:setAttribute 存放的值,在瀏覽器關閉后,還有沒有?
回答:有!就算客戶端把電腦砸了也還有。
問題:為何關閉瀏覽器后,再次訪問會覺得 session 失效了呢,這里的失效意思是 session 的數據丟失了?
回答:其實,這里 session 數據並沒有丟失,只是關閉瀏覽器后,因為默認的 cookie 生命周期為瀏覽器的內存,即關掉瀏覽器之后 cookie 就失效了,此時 JSESSIONID 也就沒有了。再次訪問后,服務器又生成一個新的 JSESSIONID,此時 request.getSession() 通過 JSESSIONID 獲取到的 session 就不是之前的 session了。
作用:常用於 web 開發中的登陸驗證界面(當用戶登錄成功后瀏覽器分配其一個 session 鍵值對)。
- 讀取生成的驗證碼信息:
//圖片的驗證碼
String imageMsg = (String) request.getSession().getAttribute("imageMsg");
- 用戶保持登錄狀態:
//登錄成功 保存用戶登錄狀態
request.getSession().setAttribute("user", user);
- 購物車物品保存:
//將cart放入session中
request.getSession().setAttribute("cart", cart);
application
生命周期:
- 創建:服務器啟動的時候,服務器為每個WEB應用創建一個屬於該 web 項目的對象 ServletContext 類。
銷毀:服務器關閉或者項目從服務器中移除的時候。
注意:服務器只會創建一個 ServletContext 對象,所以如果在代碼中,你創建了兩個 application ,其實它們就是同一個,他們的值是互通的。
有效:此信息在整個服務器上被保留。
三大作用域的區別
- request:每一次請求都是一個新的 request 對象,如果在 web 組件之間需要共享同一個請求中的數據,只能使用請求轉發。
- session:每一次會話都是一個新的 session 對象,如果如果需要在一次會話中的多個請求之間需要共享數據,只能使用session。
- application:應用對象,Tomcat啟動到關閉,表示一個應用,在一個應用中有且只有一個 application 對象,作用於整個 Web 應用,可以實現多次會話之間的數據共享。
共同點
設置作用域中的共享數據(保存數據)
作用域對象.setAttribute(String name,Object value);
獲取作用域中的共享數據(獲取數據)
Object value=作用域對象.getAttribute(String name);
刪除作用域中的指定的共享數據(刪除數據)
作用域對象.removeAttribute(String name);
總結
總結:
作用域:request、session、application
使用作用域傳遞數據和存儲數據
使用作用域傳遞數據時,必須掌握作用域對應的生命周期和作用范圍- 生命周期:
- request:只限於一次請求
- session:一次會話(多次請求)
- 開始:用戶向服務器發送請求的時候
- 結束:
- 客戶端:丟失JsessionId值的時候(關閉瀏覽器)
- 服務器端:關閉服務器、超過會話的不活動周期時間
- application:項目的加載到卸載
- 作用范圍:
- requset:所有被請求轉發的Servlet
- session:所有的Servlet
- application:所有的Servlet(換一個瀏覽器演示,跟session作用域區分)
- 如何正確的選擇作用域:
- request:跟當前操作功能相關
- session:跟用戶信息相關
- application:跟項目全局信息相關----》京東配送地址
如何正確的選擇作用域不正確,會出現什么情況?
內存浪費
記錄一系列狀態
session 服務端 開會 會話(服務器與客戶端之間的會話,將會話信息存在服務器)
cookie 客戶端 餅干(與 session 類似,只不過將信息存在客戶端)
request 請求域共享
JSP 四大作用域
jsp 九大內置對象中有四大域對象
jsp 四大域對象(這是范圍概念,而不是時間概念)(如 請求是指一次請求范圍(包括響應),而不是請求的那個時刻)(就如求婚的范圍=求婚、思考、接收,而不是指求婚那個時刻)
對象類型 | 對象名稱 | 范圍 | 備注 |
---|---|---|---|
PageContext | pageContext | 當前jsp頁面范圍內有效 | JSP的域對象 |
HttpServletRequest | request | 一次請求內有效 | servlet的域對象 |
HttpSession | session | 一次會話范圍內有效 | servlet的域對象 會話(打開瀏覽器訪問服務器,直到關閉瀏覽器) |
ServletContext | application | 整個web工程范圍內都有效 | servlet的域對象 工程(只要web工程不停止,數據都在) |
請求范圍將請求-處理-響應整合在一起了,請求范圍能直接 get、set 值,不然如果分開的話請求 get、set,而響應 get、set,要都在一個域里面,就很復雜。這樣的話就不是在一個域里面了,是在兩個域里了,就很復雜。
一次請求:頁面跳到另一個頁面 整個過程都是一次請求。我解釋的沒有錯,從請求到處理請求都是請求過程(都在請求中),包含響應都是請求過程。
請求過程:請求-處理-響應,都是請求過程。
Request 和 Response 對象起到了服務器與客戶機之間的信息傳遞作用。Request 對象用於接收客戶端瀏覽器提交的數據,而 Response 對象的功能則是將服務器端的數據發送到客戶端瀏覽器。
請求-后台處理-響應
服務器-服務器-瀏覽器
其實,Tomcat 訪問任何的資源都是在訪問 Servlet!當然了,JSP 也不例外!JSP 本身就是一種 Servlet。為什么我說 JSP 本身就是一種 Servlet 呢?其實 JSP 在第一次被訪問的時候會被編譯為 HttpJspPage 類(該類是 HttpServlet 的一個子類)
jsp就是在html里面寫java代碼,servlet就是在java里面寫html代碼…其實jsp經過容器解釋之后就是servlet.只是我們自己寫代碼的時候盡量能讓它們各司其職,jsp更注重前端顯示,servlet更注重模型和業務邏輯。不要寫出萬能的jsp或servlet來即可。
每次只要有請求進入 Tomcat 服務器,Tomcat 服務器就會把請求過來的 HTTP 協議信息解析好封裝到 Request 對象中。然后傳遞到 service 方法(doGet 和 doPost)中給我們使用。我們可以通過 HttpServletRequest 對象,獲取到所有請求的信息。
EL 語法
在 JSP 中訪問模型對象是通過 EL 表達式的語法來表達。所有EL表達式的格式都是以“${}”表示。例如,${userinfo} 代表獲取變量 userinfo 的值。當 EL 表達式中的變量不給定范圍時,則默認在 page 范圍查找,然后依次在 request、session、application 范圍查找。也可以用范圍作為前綴表示屬於哪個范圍的變量,例如:${pageScope.userinfo} 表示訪問 page 范圍中的 userinfo 變量。
工作流程
其實沒有那么復雜,View 頁面視圖中為需要請求的東西設置了占位符,如 ${msg},這樣發送請求;
而我們后台接收到請求后,為這個請求的參數屬性設置值而已,request.setAttribution()。
前后端之間,通過request的set、get來實現數據交流。(model、map、modelmap也行)