【Web】Servlet三大作用域、JSP四大作用域

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 改變了,請求域也並不相同。

總結:

  1. request.getRequestDispatcher("a.jsp").forward(rquest,response); request 轉發,它可以保存 request 中的數據,頁面調整,但是地址是不調整的
  2. response.sendRedirect("b.jsp"); 方式是重定向,它的數據是不共享的,也就是說,request 中保存的數據在 b.jsp 頁面中是獲取不到的 這種方式是表單是不能重複提交的,response 跳轉是可以實現跨域的 地址欄也會變化。

session

生命週期:

  • 創建:服務器端第一次調用 getSession();(保存在服務器內存中)

    解釋 session:當訪問服務器某個網頁的時候,會在服務器端的內存裏開闢一塊內存,這塊內存就叫做session,而這個內存是跟瀏覽器關聯在一起的。當訪問一個頁面的時候給瀏覽器創建一個獨一無二的號碼,也給同時創建的session賦予同樣的號碼。這個瀏覽器指的是瀏覽器窗口,或者是瀏覽器的子窗口,意思就是,只允許當前這個session對應的瀏覽器訪問,就算是在同一個機器上新啓的瀏覽器也是無法訪問的。而另外一個瀏覽器也需要記錄session的話,就會再啓一個屬於自己的session

  • 銷燬:
    1. 非正常關閉服務器(正常關閉 session 會序列化,再次啓動服務器 session 會被反序列化);

      注意:服務器正常關閉,再啓動,Session 對象會進行鈍化和活化操作。同時如果服務器鈍化的時間在 session 默認銷燬時間之內,則活化後 session 還是存在的。否則 Session 不存在。  如果 JavaBean 數據在 session 鈍化時,沒有實現 Serializable 則當 Session 活化時,會消失。

    2. session 過期了默認30分鐘;
    3. 手動調用 session.invalidate();
    4. 關閉瀏覽器。

      注意:關閉瀏覽器再次訪問會找不到 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 應用,可以實現多次會話之間的數據共享。

共同點

  1. 設置作用域中的共享數據(保存數據)
    作用域對象.setAttribute(String name,Object value);

  2. 獲取作用域中的共享數據(獲取數據)
    Object value=作用域對象.getAttribute(String name);

  3. 刪除作用域中的指定的共享數據(刪除數據)
    作用域對象.removeAttribute(String name);

總結

總結:

  1. 作用域:request、session、application
    使用作用域傳遞數據和存儲數據
    使用作用域傳遞數據時,必須掌握作用域對應的生命週期和作用範圍

  2. 生命週期:
    1. request:只限於一次請求
    2. session:一次會話(多次請求)
      • 開始:用戶向服務器發送請求的時候
      • 結束:
        • 客戶端:丟失JsessionId值的時候(關閉瀏覽器)
        • 服務器端:關閉服務器、超過會話的不活動週期時間
    3. application:項目的加載到卸載
  3. 作用範圍:
    1. requset:所有被請求轉發的Servlet
    2. session:所有的Servlet
    3. application:所有的Servlet(換一個瀏覽器演示,跟session作用域區分)
  4. 如何正確的選擇作用域:
    1. request:跟當前操作功能相關
    2. session:跟用戶信息相關
    3. application:跟項目全局信息相關----》京東配送地址
  5. 如何正確的選擇作用域不正確,會出現什麼情況?
    內存浪費

記錄一系列狀態
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也行)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章