JAVA學習筆記—JAVA WEB(二)JAVA WEB核心(下)

qq_40850871發表於2020-12-16

4. EL和JSTL核心技術

4.1 EL表示式

4.1.1 基本概念

EL(Expression Language)表示式提供了在JSP中簡化表示式的方法,可以方便地訪問各種資料並輸出。

4.1.2 主要功能

依次訪問pageContext、request、session和application作用域物件儲存的資料。
獲取請求引數值。
訪問Bean物件的屬性。
訪問集合中的資料。
輸出簡單的運算結果。

4.1.3 訪問內建物件的資料

(1)訪問方式
<%=request.getAttribute(“ varName”)%>
用EL實現: ${ varName }
(2)執行流程

image-20201215202014149

4.1.4 訪問請求引數的資料

在EL之前使用下列方式訪問請求引數的資料
request.getParameter(name);
request.getParameterValues(name);
在EL中使用下列方式訪問請求引數的資料
param:接收的引數只有一個值。
paramValues:接受的引數有多個值。

<!-- 獲取指定引數的數值 -->
${param.name}
<!-- 獲取指定引數中指定下標的數值 -->
${paramValues.hobby[0]}
<body>
<%
    request.setCharacterEncoding("utf-8");
%>
<%-- 使用JSP語法中的原始方式獲取請求引數值 --%>
<%--<%= "姓名是:" + request.getParameter("name") %><br/>
<%= "愛好是:" + Arrays.toString(request.getParameterValues("hobby")) %><br/>--%>

<%-- 使用EL表示式中的方式獲取請求引數值 --%>
姓名是:${param.name}<br/>
愛好是:${paramValues.hobby[0]}<br/>

</body>

4.1.5 訪問Bean物件的屬性

(1)訪問方式
方式一: $ { 物件名 . 屬性名 },例如:${user.name}
方式二: $ { 物件名 [“屬性名”] },例如:${user[“name”]}
(2)主要區別
當要存取的屬性名中包含一些特殊字元,如: . 或 ,等並非字母或數字的符號,就一定要使用 [ ]而不是.的方式
使用[]的方式可以動態取值,具體方式如下:

<%
request.setAttribute(“prop”,“age”);
%>
<!-- 相當於表示式中寫一個變數 -->
${ user[prop] }
<body>
<%-- 使用JSP語法規則中的原始方式實現物件的建立和設定以及輸出 --%>
<%
    Person person = new Person();
    person.setName("zhangfei");
    person.setAge(30);
    pageContext.setAttribute("person", person);

    pageContext.setAttribute("var1", "name");
    pageContext.setAttribute("var2", "age");
%>

<%--<%= "獲取到的姓名為:" + person.getName() %><br/>
<%= "獲取到的年齡為:" + person.getAge()  %><br/>--%>
<%-- 使用EL表示式實現屬性的獲取和列印 --%>
<%--獲取到的姓名是:${person.name}<br/>
獲取到的年齡是:${person.age}<br/>--%>
<%-- 另外一種寫法 --%>
<%--${person["name"]}<br/>
${person["age"]}<br/>--%>
<%-- 測試一下動態取值的效果 --%>
動態取值的結果為:${person[var1]}
</body>

4.1.6 訪問集合中的資料

<!-- student為ArrayList型別的物件 -->
${student[0].name}
<body>
<%
    // 準備一個List集合並新增資料內容
    List<String> list = new LinkedList<>();
    list.add("two");
    list.add("one");
    list.add("three");
    // 將整個集合放入指定的內建物件中
    pageContext.setAttribute("list", list);

    // 準備一個Map集合並新增資料
    Map<String, Integer> map = new HashMap<>();
    map.put("one", 1);
    map.put("two", 2);
    map.put("th.ree", 3);
    // 將整個集合放入指定的內建物件中
    pageContext.setAttribute("map", map);
%>

<%-- 使用EL表示式實現集合中資料內容的獲取 --%>
集合中下標為0的元素是:${list[0]}<br/>    <%-- two --%>
集合中下標為1的元素是:${list[1]}<br/>    <%-- one --%>
集合中下標為2的元素是:${list[2]}<br/>    <%-- three --%>
<hr/>
<%-- 使用EL表示式實現Map集合中資料內容的獲取 不支援下標 --%>
整個Map集合中的元素有:${map}<br/>
獲取帶有特殊字元key對應的數值為:${map["th.ree"]}<br/>   <%-- 3 --%>
</body>

4.1.7 常用的內建物件

類別識別符號描述
JSPpageContextPageContext 處理當前頁面
作用域pageScope同頁面作用域屬性名稱和值有關的Map類
requestScope同請求作用域屬性的名稱和值有關的Map類
sessionScope同會話作用域屬性的名稱和值有關的Map類
applicationScope同應用程式作用域屬性的名稱和值有關的Map類
請求引數param根據名稱儲存請求引數的值的Map類
paramValues把請求引數的所有值作為一個String陣列來儲存的Map類
請求頭header根據名稱儲存請求頭主要值的Map類
headerValues把請求頭的所有值作為一個String陣列來儲存的Map類
Cookiecookie根據名稱儲存請求附帶的cookie的Map類
初始化引數initParam根據名稱儲存Web應用程式上下文初始化引數的Map類
<body>
<%
    /*pageContext.setAttribute("name1", "pageContext物件中的屬性值:zhangfei");
    request.setAttribute("name2", "request物件中的屬性值:guanyu");
    session.setAttribute("name3", "session物件中的屬性值:liubei");
    application.setAttribute("name4", "session物件中的屬性值:zhaoyun");*/
    //pageContext.setAttribute("name", "pageContext物件中的屬性值:zhangfei");
    //request.setAttribute("name", "request物件中的屬性值:guanyu");
    //session.setAttribute("name", "session物件中的屬性值:liubei");
    application.setAttribute("name", "session物件中的屬性值:zhaoyun");
%>

<%-- 使用JSP中原始方式獲取資料和列印 --%>
<%--<%= "name1的數值為:" + pageContext.getAttribute("name1") %><br/>   &lt;%&ndash; zhangfei &ndash;%&gt;
<%= "name2的數值為:" + request.getAttribute("name2") %><br/>       &lt;%&ndash; guanyu &ndash;%&gt;
<%= "name3的數值為:" + session.getAttribute("name3") %><br/>       &lt;%&ndash; liubei &ndash;%&gt;
<%= "name4的數值為:" + application.getAttribute("name4") %><br/>   &lt;%&ndash; zhaoyun &ndash;%&gt;--%>
<%-- 使用EL表示式實現獲取資料和列印 --%>
<%--<h1>name1的數值為:${name1}</h1><br/>
name2的數值為:${name2}<br/>
name3的數值為:${name3}<br/>
name4的數值為:${name4}<br/>--%>
<h1>name的數值為:${name}</h1><br/>

</body>

4.1.8 常用的運算子

(1)常用的算術運算子

算術運算子說 明範 例運算結果
+${1+2}3
${2-1}1
*${2*3}6
/ 或 div 16 / 5 或 {16/5}或 16/5{16div5}3.2
% 或 mod取餘KaTeX parse error: Expected '}', got 'EOF' at end of input: {16%5}或{16mod5}1

(2)常用的關係運算子

關係運算子說 明範 例運算結果
==或eq等於 1 = = 2 或 {1==2}或 1==2{1 eq 2}false
!= 或ne不等於 2 ! = 1 或 {2!=1}或 2!=1{1 ne 2}true
< 或lt小於 2 < 3 或 {2<3}或 2<3{2 lt 3 }true
> 或 gt大於 16 > 5 或 {16>5}或 16>5{16 gt 5}true
<= 或 le小於等於 16 < = 5 或 {16<=5}或 16<=5{16 le 5}false
>= 或 ge大於等於 16 > = 5 或 {16>=5}或 16>=5{16 ge 5}true

(3)常用的邏輯運算子

邏輯運算子說 明範 例運算結果
&& 或 and與運算KaTeX parse error: Expected '}', got '&' at position 6: {true&̲&true}或{true and true}true
|| 或or或運算 t r u e ∥ ∥ f a l s e 或 {true\|\|false}或 truefalse{true or false}true
! 或not非運算 ! t r u e 或 {!true}或 !true{not true }false

(4)條件運算子

${條件表示式? 語句1 : 語句2}

(5)驗證運算子

${empty 表示式}
返回布林值判斷表示式是否為"空"值,null值、無元素的集合或陣列、長度為零的String被認為是空值。

4.2 JSTL標籤

4.2.1 基本概念

JSTL( JSP Standard Tag Library ) 被稱為JSP標準標籤庫。
開發人員可以利用這些標籤取代JSP頁面上的Java程式碼,從而提高程式的可讀性,降低程式的維護難度。

4.2.2 使用方式

下載JSTL的jar包並新增到專案中,下載地址為:https://tomcat.apache.org/download-taglibs.cgi

在JSP頁面中使用taglib指定引入jstl標籤庫,方式為:

<!-- prefix屬性用於指定庫字首 -->
<!-- uri屬性用於指定庫的標識 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

4.2.3 常用核心標籤

(1)輸出標籤

<c:out>  </c:out> 用來將指定內容輸出的標籤

(2)設定標籤

<c:set></c:set> 用來設定屬性範圍值的標籤
<body>
<%-- 表示設定一個名字為name的屬性,對應的數值為zhangfei,有效範圍為:page --%>
<%-- pageContext.setAttibute("name", "zhangfei") --%>
<c:set var="name" value="zhangfei" scope="page"></c:set>
<%-- 使用out標籤列印出來 --%>
<c:out value="${name}"></c:out>
<hr/>

<%-- 設定一個物件的屬性值並列印出來 --%>
<jsp:useBean id="person" class="com.lagou.demo01.Person" scope="page"></jsp:useBean>
<c:set property="name" value="guanyu" target="${person}"></c:set>
<c:set property="age" value="35" target="${person}"></c:set>
<c:out value="${person.name}"></c:out>
<c:out value="${person.age}"></c:out>

</body>

(3)刪除標籤

<c:remove></c:remove> 用來刪除指定資料的標籤
<body>
<%-- 設定一個屬性值並列印 --%>
<c:set var="name" value="liubei" scope="page"></c:set>
<c:out value="${name}"></c:out>
<hr/>

<%-- 刪除這個屬性值後再次列印 --%>
<c:remove var="name" scope="page"></c:remove>
<c:out value="${name}" default="無名"></c:out>

</body>

(4)單條件判斷標籤

<c:if test =“EL條件表示式”>
滿足條件執行
</c:if >
<body>
<%-- 設定一個變數以及對應的數值 --%>
<c:set var="age" value="17" scope="page"></c:set>
<c:out value="${age}"></c:out>
<hr/>

<%-- 判斷該年齡是否成年,若成年則提示已經成年了 --%>
<c:if test="${age >= 18}">
    <c:out value="已經成年了!"></c:out>
</c:if>

</body>

(5)多條件判斷標籤

<c:choose >
<c:when test =“EL表示式”>
滿足條件執行
</c:when>
… <c:otherwise>
不滿足上述when條件時執行
</c:otherwise>
</c:choose >
<body>
<%-- 設定一個變數代表考試的成績並指定數值 --%>
<c:set var="score" value="59" scope="page"></c:set>
<c:out value="${score}"></c:out>
<hr/>

<%-- 進行多條件判斷和處理 --%>
<c:choose>
    <c:when test="${score > 60}">
        <c:out value="成績不錯,繼續加油哦!"></c:out>
    </c:when>
    <c:when test="${score == 60}">
        <c:out value="60分萬歲,多一份浪費!"></c:out>
    </c:when>
    <c:otherwise>
        <c:out value="革命尚未成功,同志仍需努力!"></c:out>
    </c:otherwise>
</c:choose>
</body>

(6)迴圈標籤

<c:forEach var=“迴圈變數” items=“集合”>
…
</c:forEach>
<body>
<%
    // 準備一個陣列並初始化
    String[] sArr = {"11", "22", "33", "44", "55"};
    pageContext.setAttribute("sArr", sArr);
%>

<%-- 使用迴圈標籤遍歷陣列中的所有元素 --%>
<c:forEach var="ts" items="${sArr}">
    <c:out value="${ts}"></c:out>
</c:forEach>
<hr/>

<%-- 跳躍性遍歷 間隔為2  也就是跳過一個遍歷一個 --%>
<c:forEach var="ts" items="${sArr}" step="2">
    <c:out value="${ts}"></c:out>
</c:forEach>
<hr/>

<%-- 指定起始和結尾位置 從下標1開始到3結束,包含1和3--%>
<c:forEach var="ts" items="${sArr}" begin="1" end="3">
    <c:out value="${ts}"></c:out>
</c:forEach>

</body>

4.2.4 常用函式標籤

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<body>
<%
    pageContext.setAttribute("var", "Hello World!");
%>
原始字串為:${var}<br/>    <%-- HelloWorld --%>
判斷該字串是否包含指定字串的結果為:${fn:contains(var, "Hello")}<br/>   <%-- true --%>
將字串中所有字元轉換為大寫的結果為:${fn:toUpperCase(var)}<br/>           <%-- HELLO WORLD!--%>
將字串中所有字元轉換為小寫的結果為:${fn:toLowerCase(var)}<br/>           <%-- hello world!--%>
</body>

4.2.5 常用格式化標籤

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

4.2.6 自定義標籤

如果上面幾個標籤不能滿足需求,程式設計師也可以自定義標籤,步驟如下:
編寫標籤類繼承SimpleTagSupport類或TagSupport類並重寫doTag方法或doStartTag方法。

public class HelloTag extends SimpleTagSupport {
    private String name;
    public String getName() {
    	return name;
    } 
    public void setName(String name) {
    	this.name = name;
    } 
    @Override
    public void doTag() throws JspException, IOException {
    	JspWriter out = this.getJspContext().getOut();
    	out.println("自定義標籤的引數為:" + name);
    }
}

定義標籤庫檔案(tld標籤庫檔案)並配置標籤說明檔案到到WEB-INF下:

<tag>
    <name>helloTag</name>
    <tag-class>com.lagou.demo02.HelloTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
    <name>name</name>
    <required>true</required>
    </attribute>
</tag>

在JSP中新增taglib指令引入標籤庫使用:

<%@ taglib prefix="hello" uri="http://lagou.com" %>
<%@ taglib prefix="my" uri="http://lagou.com" %>
<%--
  Created by IntelliJ IDEA.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>實現自定義標籤的使用</title>
</head>
<body>
<my:hello name="zhangfei"/>
</body>
</html>

5. Filter+Listener核心技術

5.1 Filter過濾器

5.1.1 基本概念

Filter本意為”過濾“的含義,是JavaWeb的三大元件之一,三大元件為:Servlet、Filter、Listener。
過濾器是向 Web 應用程式的請求和響應處理新增功能的 Web 服務元件。
過濾器相當於瀏覽器與Web資源之間的一道過濾網,在訪問資源之前通過一系列的過濾器對請求
進行修改、判斷以及攔截等,也可以對響應進行修改、判斷以及攔截等。

5.1.2 工作方式

image-20201215203708274

5.1.3 使用方式

自定義類實現Filter介面並重寫doFilter方法。

public class LoginFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException,ServletException {
    //TODO 處理邏輯,必須呼叫下面的方法
    chain.doFilter(request,response);
    }
}

在web.xml檔案中配置過濾器。

<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.lagou.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

5.1.4 Filter介面

(1)基本概念

javax.servlet.Filter介面主要用於描述過濾器物件,可以對資源的請求和資源的響應操作進行篩選操作。
(2)常用的方法

方法宣告功能介紹
void init(FilterConfig filterConfig)實現過濾器的初始化 操作
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)執行過濾操作的功能
void destroy()實現過濾器的銷燬操作
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 1.實現對使用者訪問主頁面的過濾操作,也就是隻有使用者登入後才能訪問主頁面,否則一律攔截
        // 判斷session中是否已有使用者名稱資訊,若沒有則進行攔截,否則放行
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object userName = session.getAttribute("userName");
        // 獲取Servlet的請求路徑
        String servletPath = httpServletRequest.getServletPath();
        // 若沒有登入,則回到登入頁面
        if (null == userName && !servletPath.contains("login")) {
            servletRequest.getRequestDispatcher("login.jsp").forward(servletRequest, servletResponse);
        } else {
            // 若已經登入,則放行
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}


@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.接收前端頁面輸入的使用者名稱和密碼資訊並列印
        String userName = request.getParameter("userName");
        System.out.println("接收到的使用者名稱為:" + userName);
        String password = request.getParameter("password");
        System.out.println("接收到的密碼為:" + password);
        // 2.使用固定的使用者名稱和密碼資訊來進行登入的校驗
        if ("admin".equals(userName) && "123456".equals(password)) {
            System.out.println("登入成功,歡迎使用!");
            // 儲存使用者名稱資訊
            request.getSession().setAttribute("userName", userName);
            response.sendRedirect("main.jsp");
        } else {
            System.out.println("使用者名稱或密碼錯誤,請重新輸入!");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

5.1.5 FilterConfig介面

(1)基本概念
javax.servlet.FilterConfig介面主要用於描述過濾器的配置資訊。
(2)常用方法

方法宣告功能介紹
String getFilterName()獲取過濾器的名字
String getInitParameter(String name)獲取指定的初始化引數資訊
Enumeration getInitParameterNames()獲取所有的初始化操作名稱
ServletContext getServletContext()獲取ServletContext物件
public class LifeFilter implements Filter {
    public LifeFilter() {
        System.out.println("構造方法執行!");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化操作正在火熱進行中...");
        System.out.println("獲取到的過濾器名稱為:" + filterConfig.getFilterName());
        String userName = filterConfig.getInitParameter("userName");
        System.out.println("獲取到指定初始化引數的數值為:" + userName);  // admin
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            // userName password
            System.out.println("獲取到的初始化引數名為:" + initParameterNames.nextElement());
        }
        ServletContext servletContext = filterConfig.getServletContext();
        System.out.println("獲取到的上下文物件是:" + servletContext);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("阻攔一切不合理的訪問哦!");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("銷燬操作執行完畢了!");
    }
}

5.1.6 多個過濾器的使用

如果有多個過濾器都滿足過濾的條件,則容器依據對映的先後順序來呼叫各個過濾器。

image-20201215204105975

public class AFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("這是第一道防線!");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("第一道防線返回!");
    }

    @Override
    public void destroy() {

    }
}


public class BFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("這是第二道防線!");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("第二道防線返回!");
    }

    @Override
    public void destroy() {

    }
}

5.1.7 過濾器優點

實現程式碼的“可插拔性”,即增加或減少某個功能模組,不會影響程式的正常執行。
可以將多個相同處理邏輯的模組集中寫在過濾器裡面,可實現重複利用、也方便程式碼的維護。

5.2 Listener監聽器

5.2.1 基本概念

Servlet規範中定義的一種特殊的元件,用來監聽Servlet容器產生的事件並進行相應的處理。

容器產生的事件分類如下:
生命週期相關的事件。
屬性狀態相關的事件。
存值狀態相關的事件。
底層原理是採用介面回撥的方式實現。

5.2.2 基本分類

監聽器型別功能介紹
javax.servlet.ServletRequestListener監聽request作用域的建立和銷燬
javax.servlet.ServletRequestAttributeListener監聽request作用域的屬性狀態變化
javax.servlet.http.HttpSessionListener監聽session作用域的建立和銷燬
javax.servlet.http.HttpSessionAttributeListener監聽session作用域的屬性狀態變化
javax.servlet.ServletContextListener監聽application作用域的建立和銷燬
javax.servlet.ServletContextAttributeListener監聽application作用域的屬性狀態變化
javax.servlet.http.HttpSessionBindingListener監聽物件與session的繫結和解除
javax.servlet.http.HttpSessionActivationListener監聽session數值的鈍化和活化

5.2.3 監聽器詳解

(1)ServletRequestListener監聽器
在ServletRequest建立和關閉時都會通知ServletRequestListener監聽器。
常用方法如下:

方法宣告功能介紹
void requestInitialized(ServletRequestEvent sre)實現ServletRequest物件的初始化
void requestDestroyed(ServletRequestEvent sre)實現ServletRequest物件的銷燬
public class MyRequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("請求銷燬了...");
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("建立請求...");
    }
}

(2)ServletRequestAttributeListener監聽器
向ServletRequest新增、刪除或者替換一個屬性的時候,將會通知
ServletRequestAttributeListener監聽器。
常用方法如下:

方法宣告功能介紹
void attributeAdded(ServletRequestAttributeEvent srae)增加屬性時觸發
void attributeReplaced(ServletRequestAttributeEvent srae)修改屬性時觸發
void attributeRemoved(ServletRequestAttributeEvent srae)刪除屬性時觸發
public class MyRequestAttributeListener implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("增加了屬性" + servletRequestAttributeEvent.getName());
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("屬性" + servletRequestAttributeEvent.getName() + "被刪除了" );
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("修改屬性" + servletRequestAttributeEvent.getName());
    }
}

(3)HttpSessionListener監聽器
當一個HttpSession剛被建立或者失效(invalidate)的時候,將會通知HttpSessionListener監聽器。
常用方法如下:

方法宣告功能介紹
void sessionCreated(HttpSessionEvent se)當一個HttpSession物件被建立時會呼叫這個方法
void sessionDestroyed(HttpSessionEvent se)當一個HttpSession超時或者呼叫HttpSession的 invalidate()方法讓它銷燬時,將會呼叫這個方法
public class MySessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("建立了session...");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("session銷燬!");
    }
}

(4)HttpSessionAttributeListener監聽器
HttpSession中新增、刪除或者替換一個屬性的時候,將會通知HttpSessionAttributeListener監聽器。
常用方法如下:

方法宣告功能介紹
void attributeAdded(HttpSessionBindingEvent se)當往會話中加入一個屬性的時候會呼叫這個 方法
void attributeRemoved(HttpSessionBindingEvent se)當從會話中刪除一個屬性的時候會呼叫這個 方法
void attributeReplaced(HttpSessionBindingEvent se)當改變會話中的屬性的時候會呼叫這個方法
public class MySessionAttributeListener implements HttpSessionAttributeListener {
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("增加了屬性" + httpSessionBindingEvent.getName());
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("屬性" + httpSessionBindingEvent.getName() + "被刪除!");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("修改屬性" + httpSessionBindingEvent.getName());
    }
}

(5)ServletContextListener監聽器
在ServletContext建立和關閉時都會通知ServletContextListener監聽器。
常用方法如下:

方法宣告功能介紹
void contextInitialized(ServletContextEvent sce)當ServletContext建立的時候,將會呼叫這個方法
void contextDestroyed(ServletContextEvent sce)當ServletContext銷燬的時候(例如關閉應用伺服器 或者重新載入應用),將會呼叫這個方法
public class MyContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext物件建立了...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("銷燬ServletContext物件...");
    }
}

(6)ServletContextAttributeListener監聽器
向ServletContext新增、刪除或者替換一個屬性的時候,將會通知ServletContextAttributesListener監聽器
常用方法如下:

方法宣告功能介紹
void attributeAdded(ServletContextAttributeEvent scae)往ServletContext中加入一個屬性的時 候觸發
void attributeRemoved(ServletContextAttributeEvent scae)從ServletContext中刪除一個屬性的時 候觸發
void attributeReplaced(ServletContextAttributeEvent scae)改變ServletContext中屬性的時候觸發
public class MyContextAttributeListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("增加了屬性" + servletContextAttributeEvent.getName());
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("屬性" + servletContextAttributeEvent.getName() + "被刪除!");
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("修改屬性" + servletContextAttributeEvent.getName());
    }
}

(7)HttpSessionBindingListener監聽器
HttpSession中繫結和解除繫結時,將會通知HttpSessionListener監聽器。
常用方法如下:

方法宣告功能介紹
void valueBound(HttpSessionBindingEvent event)有物件繫結時呼叫該方法
void valueUnbound(HttpSessionBindingEvent event)有物件解除繫結時呼叫該方法

(8)HttpSessionActivationListener監聽器
當有session數值的鈍化和活化操作時,將會通知HttpSessionActivationListener監聽器。
常用方法如下:

方法宣告功能介紹
void sessionWillPassivate(HttpSessionEvent se)有鈍化操作時呼叫該方法
void sessionDidActivate(HttpSessionEvent se)有活化操作時呼叫該方法

配置context.xml檔案的方式如下:

<Manager className="org.apache.catalina.session.PersistentManager"
    saveOnRestart="true">
    <!-- 配置檔案存放的路徑資訊,可以自由指定 -->
    <Store className="org.apache.catalina.session.FileStore"
    directory="C:\session"/>
</Manager>

5.2.4 實戰案例

自定義類實現監聽器介面並重寫相關的方法。

public class OnlineUser implements HttpSessionListener,ServletContextListener {
    ServletContext ctx = null;
    // 初始化ServletContext
    public void contextInitialized(ServletContextEvent e) {
    ctx = e.getServletContext();
    } 
    // 銷燬ServletContext
    public void contextDestroyed(ServletContextEvent e) {
    //將ServletContext設定成null;
    }
    // 當新建立一個HttpSession物件時
    public void sessionCreated(HttpSessionEvent e) {
    //將當前的線上人數加上1,並且儲存到ServletContext(application)中
    } 
    // 當一個HttpSession被銷燬時(過期或者呼叫了invalidate()方法)
    public void sessionDestroyed(HttpSessionEvent e) {
    //將當前人數減去1,並且儲存到ServletContext(application)中
    }
}

在web.xml中配置監聽器

<listener>
	<listener-class> com.lagou.listener.OnlineUser </listener-class>
</listener>
public class OnlineUser implements HttpSessionListener, ServletContextListener {
    // 宣告一個ServletContex型別的引用負責作為全域性物件來記錄當前線上使用者的數量,通過屬性記錄
    private ServletContext servletContext = null;

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        servletContext = servletContextEvent.getServletContext();
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        servletContext = null;
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("有新使用者上線了...");
        Object count = servletContext.getAttribute("count");
        // 若當前使用者為第一個使用者,則將全域性物件中的屬性值設定為1即可
        if (null == count) {
            servletContext.setAttribute("count", 1);
        }
        // 若當前使用者不是第一個使用者,則將全域性物件中原有的資料取出來加1後再設定進去
        else {
            Integer integer = (Integer)count;
            integer++;
            servletContext.setAttribute("count", integer);
        }
        System.out.println("當前線上使用者數量為:" + servletContext.getAttribute("count"));
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("有使用者已下線...");
    }
}

相關文章