Cookie&Session&Jsp總結

知識點梳理

Cookie&Session&Jsp

1 會話技術

1.1 會話管理概述

1.1.1 會話技術介紹

  • 會話:瀏覽器和伺服器之間的多次請求和響應 (一次對話)

    • 為了實現一些功能,瀏覽器和伺服器之間可能會產生多次的請求和響應

    • 從瀏覽器訪問伺服器開始,到訪問伺服器結束(關閉瀏覽器、到了過期時間)

    • 這期間產生的多次請求和響應加在一起就稱之為瀏覽器和伺服器之間的一次會話

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

  • 會話過程中所產生的一些數據,可以通過會話技術( Cookie 和 Session )保存

     

     

    • 播仔,登陸了黑馬論壇(右上角顯示:用戶名:小播)

    • 然後點擊「Java學科板塊」 , 打開新介面「Java學科板塊」,在這裡發帖 (在這個介面依然保持登陸狀態)

    • 接下來又點擊「」前端學科板塊「,打開新介面」前端學科板塊「,在這裡發帖(在這個介面依然保持登陸狀態)

    • 在一次登陸之後,然後打開很對新介面,依然能夠保持登陸,就是通過會話技術實現的

    • cookie&session到底是幹嘛用的呢?

    • 存儲數據,用戶登錄狀態

    • 因為在網站中,有很多介面都是需要登錄之後才能操作,為了避免重複登錄,我們會在第一次登錄成功之後將用戶的登錄狀態存儲到會話技術中(cookie,session)

1.1.2 會話管理分類

  • Cookie:客戶端會話管理技術

    • 把要共享的數據保存到客戶端。

    • 每次請求時,把會話資訊帶到伺服器端,從而實現多次請求的數據共享!

  • Session:伺服器端會話管理技術

    • 本質也是採用客戶端會話管理技術。

    • 只不過在客戶端保存的是一個特殊標識,而共享的數據保存到了伺服器端的記憶體對象中。

    • 每次請求時,會將特殊標識帶到伺服器端,根據這個標識來找到對應的記憶體空間,從而實現數據共享!

1.2 客戶端會話管理技術 ***

1.2.1 Cookie概述

1)Cookie的介紹

  • Cookie:客戶端會話管理技術

    • 把要共享的數據保存到客戶端(瀏覽器)

    • 每次請求時,瀏覽器會把會話資訊帶到伺服器端,從而實現多次請求的數據共享

  • 作用:可以保存客戶端訪問網站的相關內容,從而保證每次訪問時先從本地快取中獲取,以此提高效率!

  • Cookie API 介紹

     

     

2)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源碼

     

     

  • 添加:HttpServletResponse對象中提供了addCookie()方法

     

     

  • 獲取:HttpServletRequest對象中提供了getCookies()方法

     

     

  • 補充:為啥是響應對象添加cookie,而獲取對象是請求對象?

    • 因為,cookie是通過伺服器端程式碼將數據保存在瀏覽器,所以伺服器讓瀏覽器做一件事情,肯定是通過響應

    • 而在瀏覽器存儲的數據,要想告訴伺服器都有什麼,那肯定是通過請求

1.2.2 Cookie的使用

  • 需求說明

    • 通過 Cookie 記錄最後訪問時間,並在瀏覽器上顯示出來

  • 最終目的

    • 掌握 Cookie 的基本使用,從創建到保存到客戶端,再到從伺服器端獲取

  • 實現步驟

    1. 通過響應對象寫出一個提示資訊

    2. 創建 Cookie 對象,指定 name 和 value

    3. 設置 Cookie 最大存活時間

    4. 通過響應對象將 Cookie 對象添加到客戶端

    5. 通過請求對象獲取 Cookie 對象

    6. 將 Cookie 對象中的訪問時間寫出、

  • 案例:新建項目cookie_demo,配置虛擬目錄/cookie,新建類com.itheima.servlet.ServletDemo01

    package com.itheima.servlet;

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;

    /*
       Cookie的使用
    */
    @WebServlet("/servletDemo01")
    public class ServletDemo01 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           resp.setContentType("text/html;charset=UTF-8");
           
           //1.通過響應對象寫出提示資訊
           PrintWriter pw = resp.getWriter();
           pw.write("歡迎訪問本網站,您的最後訪問時間為:<br>");

           //2.創建Cookie對象,用於記錄最後訪問時間
           Cookie cookie = new Cookie("time",System.currentTimeMillis()+"");

           //3.設置最大存活時間(單位s)
           cookie.setMaxAge(3600);

           //4.將cookie對象添加到客戶端
           resp.addCookie(cookie);

           //5.獲取cookie
           Cookie[] arr = req.getCookies();
           for(Cookie c : arr) {
               if("time".equals(c.getName())) {
                   //6.獲取cookie對象中的value,進行寫出
                   String value = c.getValue();
                   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                   pw.write(sdf.format(new Date(Long.parseLong(value))));
              }
          }
      }

       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req,resp);
      }
    }
    • 注意:這裡我們為了節省時間,所以在一個Servlet中設置之後,立馬又獲取了

    • 其實可以在一個Servlet中設置,另一個Servlet中獲取

  • 訪問

     

     

    • 在headers中看到的Data是07:23,這個是xx 時間,我們是東八區的,所以+8小時

    • 然後set-cookie中可以看到,設置的cookie是time=xxx

    • Max-age是1小時

    • Expires過期時間是08:23

  • cookie文件

    • cookie是保存在瀏覽器中的,那瀏覽器將cookie資訊保存到快取文件中了

     

     

    • itcast@localhost/cookie/

    • 本機用戶名@本網站ip地址/cookie/

1.2.3 Cookie的使用細節

1) 細節介紹

  • 數量限制

    • 每個網站最多只能有 20 個 Cookie,且大小不能超過 4KB。所有網站的 Cookie 總數不能超過 300 個。

  • 名稱限制

    • Cookie 的名稱只能包含 ASCCI 碼錶中的字母、數字字元。不能包含逗號、分號、空格,不能以 $ 開頭。

    • Cookie 的值不支援中文。

  • 存活時間限制 setMaxAge() 方法接收數字

    • 負整數:當前會話有效,瀏覽器關閉則清除。

    • 0:立即清除。

    • 正整數:以秒為單位設置存活時間。

  • 訪問路徑限制

    • 默認路徑:取自第一次訪問的資源路徑前綴。只要以這個路徑開頭就能訪問到

    • 設置路徑:setPath() 方法設置指定路徑

2) 存活時間案例 ***

  • 在上個案例中修改程式碼

    //3.設置最大存活時間
    //cookie.setMaxAge(3600);
    cookie.setMaxAge(0);    // 立即清除
  • 訪問

     

     

3) 訪問路徑限制案例

  • 新建ServletDemo02:設置cookie

    package com.itheima.servlet;

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

    /*
       Cookie的路徑限制
       取自第一次訪問的資源路徑前綴
       只要以這個前綴為開頭(包括子級路徑)。獲取到
       反之獲取不到
    */
    @WebServlet("/servlet/servletDemo02")
    public class ServletDemo02 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //創建Cookie並添加
           Cookie cookie = new Cookie("username","zhangsan");
           cookie.setMaxAge(3600);
           resp.addCookie(cookie);
      }

       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req,resp);
      }
    }
  • 新建ServletDemo03:獲取cookie

    package com.itheima.servlet;

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

    /*
       Cookie的路徑限制
    */
    @WebServlet("/servlet/servletDemo03")
    public class ServletDemo03 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //獲取Cookie
           Cookie[] arr = req.getCookies();
           for(Cookie c : arr) {
               if("username".equals(c.getName())) {
                   String value = c.getValue();
                   resp.getWriter().write(value);
              }
          }
      }

       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req,resp);
      }
    }
  • 新建ServletDemo04:獲取cookie

    package com.itheima.servlet;

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

    /*
       Cookie的路徑限制
    */
    @WebServlet("/servlet/aaa/servletDemo04")
    public class ServletDemo04 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //獲取Cookie
           Cookie[] arr = req.getCookies();
           for(Cookie c : arr) {
               if("username".equals(c.getName())) {
                   String value = c.getValue();
                   resp.getWriter().write(value);
              }
          }
      }

       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req,resp);
      }
    }
  • 新建ServletDemo05:獲取cookie

    package com.itheima.servlet;

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

    /*
       Cookie的路徑限制
    */
    @WebServlet("/bbb/servletDemo05")
    public class ServletDemo05 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //獲取Cookie
           Cookie[] arr = req.getCookies();
           for(Cookie c : arr) {
               if("username".equals(c.getName())) {
                   String value = c.getValue();
                   resp.getWriter().write(value);
              }
          }
      }

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

     

     

  • 總結:Cookie的路徑限制

    • 取自第一次訪問的資源路徑前綴

    • 只要以這個前綴為開頭(包括子級路徑)就可以獲取到

    • 反之獲取不到

1.3 服務端會話管理概述 ***

1.3.1 HttpSession概述

1)HttpSession介紹

  • HttpSession:伺服器端會話管理技術

    • 本質也是採用客戶端會話管理技術

    • 只不過在客戶端保存的是一個特殊標識,而共享的數據保存到了伺服器端的記憶體對象中

    • 每次請求時,會將特殊標識帶到伺服器端,根據這個標識來找到對應的記憶體空間,從而實現數據共享

    • 是 Servlet 規範中四大域對象之一的會話域對象

    • 作用:可以實現數據共享

    • 為了防止在 一次會話中,讓用戶多次登錄(用戶登錄狀態)

  • 域對象API

     

     

  • 補充:

    • HttpSession,它雖然是服務端會話管理技術的對象,但它本質仍是一個Cookie

    • 是一個由伺服器自動創建的特殊的Cookie,Cookie的名稱就是JSESSIONID,Cookie的值是伺服器分配的一個唯一的標識

    • 當我們使用HttpSession時,瀏覽器在沒有禁用Cookie的情況下,都會把這個Cookie帶到伺服器端,然後根據唯一標識去查找對應的HttpSession對象,找到了,我們就可以直接使用了

2)HttpSession的常用方法

 

 

3)HttpSession的獲取

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

 

 

  • 這兩個方法的區別:

 

 

1.3.2 HttpSession的使用

  • 需求說明

    • 通過第一個 Servlet 設置共享數據用戶名,並在第二個 Servlet 獲取到

  • 最終目的

    • 掌握 HttpSession 的基本使用,如何獲取和使用

  • 實現步驟

    1. 在第一個 Servlet 中獲取請求的用戶名

    2. 獲取 HttpSession 對象

    3. 將用戶名設置到共享數據中

    4. 在第二個 Servlet 中獲取 HttpSession 對象

    5. 獲取共享數據用戶名

    6. 將獲取到用戶名響應給客戶端瀏覽器

  • 案例:

    • 新建項目session_demo,虛擬目錄/session

    • 新建com.itheima.servlet.ServletDemo01:設置共享數據

    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 javax.servlet.http.HttpSession;
    import java.io.IOException;

    /*
       Session的基本使用
    */
    @WebServlet("/servletDemo01")
    public class ServletDemo01 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //1.獲取請求的用戶名
           String username = req.getParameter("username");

           //2.獲取HttpSession的對象
           HttpSession session = req.getSession();

           //3.將用戶名資訊添加到共享數據中
           session.setAttribute("username",username);
      }

       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req,resp);
      }
    }
  • 新建ServletDemo02:獲取共享數據

    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 javax.servlet.http.HttpSession;
    import java.io.IOException;

    /*
       Session的基本使用
    */
    @WebServlet("/servletDemo02")
    public class ServletDemo02 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //1.獲取HttpSession對象
           HttpSession session = req.getSession();
           System.out.println(session);
           System.out.println(session.getId());

           //2.獲取共享數據
           Object username = session.getAttribute("username");

           //3.將數據響應給瀏覽器
           resp.getWriter().write(username+"");
      }

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

     

     

  • 驗證:demo1和demo2的session是否是同一個對象

    //兩個程式碼中都添加如下log
    System.out.println(session);
    System.out.println(session.getId());
  • 訪問:分別訪問兩個demo,發現一致

     

     

1.3.3 細節 (了解)

1) 唯一標識查看

  • 唯一標識查看(剛剛是列印出來了,其實可以通過Network查看)

     

     

     

     

2) 禁用cookie

  • 瀏覽器禁用 Cookie之後如何使用session?(用戶可以設置瀏覽器來禁止Cookie的使用)

    • 方式一:通過提示資訊告知用戶,大部分網站採用的解決方式。(推薦) ***

    • 方式二:訪問時拼接 jsessionid 標識,通過 encodeURL() 方法重寫地址。(了解)

  • 如何禁用cookie?

     

     

  • 案例:新建ServletDemo03

    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 javax.servlet.http.HttpSession;
    import java.io.IOException;

    /*
       Cookie的禁用
    */
    @WebServlet("/servletDemo03")
    public class ServletDemo03 extends HttpServlet{
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //1.獲取HttpSession對象
           HttpSession session = req.getSession();
           System.out.println(session);
      }

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

     

     

    • 在demo1中,創建了一個session

    • 在demo3中,因為禁用cookie了,sessionid沒有傳遞過來,所以又創建了一個新session

    • 所以倆session不一致

    • 為了能夠看到效果,我們修改一下程式碼

  • 修改

    HttpSession session = req.getSession(false);//改為false,如果沒有找到session也不創建
  • 訪問

     

     

  • 增加解決呢?看下天貓,也是簡單的給出了提升

     

     

  • 我們也增加提示

    if(session == null) {
       resp.setContentType("text/html;charset=UTF-8");
       resp.getWriter().write("為了不影響正常的使用,請不要禁用瀏覽器的Cookie~");
    }
  • 訪問

     

     

    • 彈框是需要用到js,後續才學習

  • 方式二:訪問時拼接 jsessionid 標識,通過 encodeURL() 方法重寫地址

    //修改demo1
    //實現url重寫 相當於在地址欄後面拼接了一個jsessionid(encodeURL自動會給路徑後添加jsessionid)
    resp.getWriter().write("<a href='"+resp.encodeURL("//localhost:8080/session/servletDemo03")+"'>go servletDemo03</a>");
  • 訪問

     

     

  • 方式二不推薦,因為每次跳轉都的做url重新,比較麻煩

3) HttpSession的鈍化和活化

  • 什麼是鈍化和活化

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

    • 活化:相反的狀態

  • 何時鈍化

    • 第一種情況:當訪問量很大時,伺服器會根據 getLastAccessTime 來進行排序,

      對長時間不用,但是還沒到過期時間的 HttpSession 進行序列化。

    • 第二種情況:當伺服器進行重啟的時候,為了保持客戶 HttpSession 中的數據,也要對其進行序列化

  • 注意

    • HttpSession 的序列化由伺服器自動完成,我們無需關心

2 頁面技術

2.1 JSP基礎

2.1.1 JSP介紹***

  • JSP(Java Server Pages):是一種動態網頁技術標準

  • JSP 部署在伺服器上,可以處理客戶端發送的請求,並根據請求內容動態的生成 HTML、XML 或其他格式文檔的 Web 網頁,然後再響應給客戶端

  • JSP 是基於 Java 語言的,它的本質就是 Servlet

  • 所學習的相關資源總結(JavaScript後續學習)

     

     

    • 動態資源:會變化的數據

    • 動態效果:例如介面上的一些特效,彈框

2.1.2 JSP快速入門

  1. 創建一個 web 項目:jsp_demo,虛擬目錄/jsp

  2. 在 web 目錄下創建一個 index.jsp 文件

    • 默認就有一個index.jsp

  3. 在文件中寫一句內容為:這是我的第一個jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
     <head>
       <title>JSP</title>
     </head>
     <body>
       <h1>這是我的第一個jsp</h1>
     </body>
    </html>
  4. 部署並啟動項目

  5. 通過瀏覽器測試

     

     

2.1.3 JSP的執行過程 ***

  • 執行過程圖

 

 

  • 明確JSP就是一個Servlet,是一個特殊的Servlet

  • 其實在第五步,翻譯jsp文件,就是將jsp翻譯成了一個Servlet

2.1.4 JSP的.java文件內容分析

  • 生成的 java 文件目錄

  • C:\Users\itcast.IntelliJIdea2018.3\system\tomcat_ideaproject\work\Catalina\localhost\jsp\org\apache\jsp

 

 

  • JSP 本質就是一個 Servlet

  • 補充:HttpJspBase.class反編譯查看

     

     

     

2.2 JSP應用

2.2.1 JSP語法

  • JSP 注釋

    <%-- 注釋的內容 --%>
  • Java 程式碼塊

    <% Java程式碼 %>
  • JSP 表達式

    <%=表達式%>
  • JSP 聲明

    <%! 聲明變數或方法 %>
  • 案例:新建web/jsp語法.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>jsp語法</title>
    </head>
    <body>
        <%--
            1. 這是注釋
        --%>
    
        <%--
            2.java程式碼塊  ***
            System.out.println("Hello JSP"); 普通輸出語句,輸出在控制台
            out.println("Hello JSP");out是JspWriter對象,輸出在頁面上
        --%>
        <%
            System.out.println("Hello JSP");
            out.println("Hello JSP<br>");
            String str = "hello<br>";
            out.println(str);
        %>
    
        <%--
            3.jsp表達式  *** 語法糖:某種語法的簡寫形式
            <%="Hello"%>  相當於 out.println("Hello");
        --%>
        <%="Hello<br>"%>
    
        <%--
            4.jsp中的聲明(變數或方法)
            如果加!  代表的是聲明的是成員變數(service中的局部變數)
            如果不加!  代表的是聲明的是局部變數  ***
        --%>
        <%! String s = "abc";%>
        <% String s = "def";%>
        <%=s%>
        <%! public void getSum(){}%>
        <%--<% public void getSum2(){}%> 這個是局部方法,相當於是在getSum里再聲明方法,所以不允許--%> 
    </body>
    </html>

2.2.2 JSP指令

1)page指令

  • 語法:<%@ page 屬性名=屬性值 屬性名=屬性值 … %>

 

 

  • language: 告知引擎,腳本使用的是java,默認是java,支援java。不寫也行。

  • 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+/ 自動導入

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

    • 相當於response.setContentType(“text/html;charset=UTF-8”);

  • 案例:新建jsp指令.jsp

    <%--
        1.page指令
    --%>
    <%@ page import="java.util.ArrayList"%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="/error.jsp" %>
    <html>
    <head>
        <title>jsp指令</title>
    </head>
    <body>
        <% int result = 1 / 0; %>
        <% ArrayList list = new ArrayList() %>
    </body>
    </html>
    
  • 新建error.jsp:上述程式碼中1/0是錯誤的語法,所以會跳轉到errorPage指定的error.jsp介面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>自定義錯誤頁面</title>
    </head>
    <body>
        不好意思,出錯了~~~
    </body>
    </html>
    

2)include指令

  • 通過該指令,可以包含其他頁面

  • 語法格式:<%@include file="" %>

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

  • 案例

    <%--
        1.page指令
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="/error.jsp" %>
    
    <%--
        2.include指令
    --%>
    <%@ include file="/include.jsp"%>
    <html>
    <head>
        <title>jsp指令</title>
    </head>
    <body>
        <%--<% int result = 1 / 0; %>--%>
        <%=s%> <%--這裡用的s是include.jsp中的--%>
    </body>
    </html>
    
  • 新建include.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>被包含的頁面</title>
    </head>
    <body>
        <% String s = "Hello"; %>
    </body>
    </html>
  • 訪問

     

     

3)taglib指令 ***

  • 該指令用於引入外部標籤庫,html標籤和jsp標籤不用引入

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

  • 屬性:

    • uri:外部標籤的URI地址

    • prefix:使用標籤時的前綴

  • tag:標籤,lib:library庫,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 Servlet配置對象
exception java.lang.Throwable 異常對象
out javax.servlet.jsp.JspWriter 字元輸出流,相當於printwriter
pageContext javax.servlet.jsp.PageContext 頁面域對象

2)PageContext對象

簡介

  • 是 JSP 獨有的,Servlet 中沒有

  • 是四大域對象之一的頁面域對象,還可以操作其他三個域對象中的屬性(應用域,會話域,請求域)

  • 還可以獲取其他八個隱式對象

  • 生命周期是隨著 JSP 的創建而存在,隨著 JSP 的結束而消失。每個 JSP 頁面都有一個 PageContext對象

常用方法

 

 

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

 

 

3)四大域對象

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

2.2.4 JSP-MVC模型介紹 ***

  • M(Model):模型。用於封裝數據,封裝的是數據模型

  • V(View):視圖。用於顯示數據,動態資源用 JSP 頁面,靜態資源用 HTML 頁面

  • C(Controller):控制器。用於處理請求和響應,例如 Servlet

  • 圖示

     

     

 

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

3.1 案例效果介紹

 

 

 

 

3.2 登陸功能

  1. 創建一個 web 項目:student_manage,虛擬目錄/stu

  2. 在 web 目錄下創建一個 index.jsp(默認就有)

  3. 在頁面中獲取會話域中的用戶名,獲取到了就顯示添加和查看功能的超鏈接,沒獲取到就顯示登錄功能的超鏈接

    <%@ 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>
    
  4. 在 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>
    
  5. 創建 LoginStudentServlet,獲取用戶名和密碼

  6. 如果用戶名為空,則重定向到登錄頁面

  7. 如果不為空,將用戶名添加到會話域中,再重定向到首頁

    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.3 添加功能

  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>
    
  2. 創建 AddStudentServlet,獲取學生資訊並保存到文件中

  3. 通過定時刷新功能 2 秒後跳轉到首頁

    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);
        }
    }
  4. 訪問

     

     

3.4 查看功能

  1. 創建 ListStudentServlet,讀取文件中的學生資訊到集合中

  2. 將集合添加到會話域中

  3. 重定向到 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);
        }
    }
    
  4. 在 web 目錄下創建一個 listStudent.jsp

  5. 定義表格標籤。在表格中獲取會話域的集合數據,將數據顯示在頁面上

    <%@ 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>
    
  6. 訪問:點擊查看學生,進入查看學生介面