1. 監(jiān)聽器Listener
監(jiān)聽器就是監(jiān)聽某個(gè)對象的狀態(tài)變化的組件。監(jiān)聽器的相關(guān)概念事件源:
- 被監(jiān)聽的對象(三個(gè)域?qū)ο髍equest , session , servletContext(Application) )
- 監(jiān)聽器:監(jiān)聽事件源對象悍赢, 事件源對象的狀態(tài)的變化都會觸發(fā)監(jiān)聽器决瞳。
- 注冊監(jiān)聽器:將監(jiān)聽器與事件源進(jìn)行綁定。
- 響應(yīng)行為:監(jiān)聽器監(jiān)聽到事件源的狀態(tài)變化時(shí)左权,所涉及的功能代碼(程序員編寫代碼)
按照被監(jiān)聽的對象劃分: ServletRequest(Request)域皮胡; HttpSession域(Session會話域);ServletContext(Application應(yīng)用程序域)域赏迟。按照監(jiān)聽的內(nèi)容分:監(jiān)聽域?qū)ο蟮膭?chuàng)建與銷毀的屡贺;監(jiān)聽域?qū)ο蟮膶傩宰兓摹?/p>
三大域?qū)ο蟮膭?chuàng)建與銷毀的監(jiān)聽器
ServletContextListener(監(jiān)聽Application應(yīng)用程序域)
監(jiān)聽ServletContext域的創(chuàng)建與銷毀的監(jiān)聽器,Servlet域的生命周期:在服務(wù)器啟動創(chuàng)建,服務(wù)器關(guān)閉時(shí)銷毀甩栈;監(jiān)聽器的編寫步驟:
- 編寫一個(gè)監(jiān)聽器類去實(shí)現(xiàn)監(jiān)聽器接口
- 覆蓋監(jiān)聽器的方法(重寫)
ServletContextListener監(jiān)聽器的主要作用:
初始化的工作:初始化對象泻仙;初始化數(shù)據(jù)。
HttpSessionListener(監(jiān)聽Session會話域)
監(jiān)聽Httpsession域的創(chuàng)建與銷毀的監(jiān)聽器量没。HttpSession對象的生命周期 :第一次調(diào)用request.getSession時(shí)創(chuàng)建玉转;銷毀有以下幾種情況(服務(wù)器關(guān)閉、session過期允蜈、 手動銷毀)
ServletRequestListener(監(jiān)聽Requset請求域)
監(jiān)聽ServletRequest域創(chuàng)建與銷毀的監(jiān)聽器冤吨。ServletRequest的生命周期 :每一次請求都會創(chuàng)建request ,請求結(jié)束則銷毀饶套。
監(jiān)聽三大域?qū)ο髮傩宰兓挠驅(qū)ο蟮耐ㄓ梅椒?/strong>
- 觸發(fā)添加屬性的監(jiān)聽器的方法
setAttribute(name,value)- 觸發(fā)修改屬性的監(jiān)聽器的方法
removeAttribute(name):觸發(fā)刪除屬性的監(jiān)聽器的方法
2. 與session中的綁定的對象相關(guān)的監(jiān)聽器(對象感知監(jiān)聽器)
(1)即將要被綁定到session中的對象有幾種狀態(tài)
綁定狀態(tài):就是一個(gè)對象被放到session域中
解綁狀態(tài):就是這個(gè)對象從session域中移除了
鈍化狀態(tài):是將session內(nèi)存中的對象持久化(序列化)到磁盤
活化狀態(tài):就是將磁盤上的對象再次恢復(fù)到session內(nèi)存中
綁定與解綁的監(jiān)聽器HttpSessionBindingListener(接口)
活化與鈍化監(jiān)聽器(一定要是一個(gè)對象-java類)
META-INF與context文件名一定要一致
注:一個(gè)普通的Javabean類只要實(shí)現(xiàn)了Serializable(接口)漩蟆,就可以實(shí)現(xiàn)活化和鈍化;而如果既實(shí)現(xiàn)了Serializable(序列化妓蛮,接口)又實(shí)現(xiàn)了HttpSessionActivationListener(接口)怠李,那么這個(gè)java類不但可以實(shí)現(xiàn)活化和鈍化,而且還可以知道什么時(shí)候被活化和鈍化
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- maxIdleSwap:session中的對象多長時(shí)間不使用就鈍化,單位分鐘-->
<!-- directory:鈍化后的對象的文件寫到磁盤的那個(gè)目錄下 配置鈍化的對象文件在 work/catalina/localhost/鈍化文件-->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="Javawebtest123"/>
</Manager>
</Context>
鈍化文件的路徑
C:\Users\liutianyu.IntelliJIdea2019.3\system\tomcat\Tomcat_8_0_21_ListenerDemo\work\Catalina\localhost\ListenerDemo_war_exploded\自定義的文件名
3. 監(jiān)聽器應(yīng)用舉例 --- 統(tǒng)計(jì)網(wǎng)站在線人數(shù)
主頁面 index.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="login.jsp">登錄</a>
<a href="ShowUser.do">顯示在線用戶</a>
</body>
</html>
登錄頁面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<center>
<h3>用戶登錄</h3>
</center>
<form action="${pageContext.request.contextPath}/LoginServlet" method="post">
<table border="1" width="550px" cellpadding="0" cellspacing="0" align="center">
<tr>
<td height="35" align="center">用戶名</td>
<td>
<input type="text" name="username">
</td>
</tr>
<tr>
<td height="35" align="center">密碼</td>
<td>
<input type="password" name="password">
</td>
</tr>
<tr>
<td height="35" colspan="2" align="center">
<input type="submit" value="登錄">
</td>
</tr>
</table>
</form>
</body>
</html>
查看當(dāng)前在線用戶界面 showuser.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="logout.do">登出</a>
<hr>
<p>當(dāng)前在線用戶</p>
<ul>
<c:forEach items="${users}" var="user">
<li>${user.value}</li>
</c:forEach>
</ul>
</body>
</html>
User.java 類
package com.lty.domain;
public class User {
private String username;
private String id;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
單列模式工具類 OnlineUserMap.java
package com.lty.db;
import com.lty.domain.User;
import java.util.HashMap;
import java.util.Map;
public class OnlineUserMap {
// 單列模式 --- 唯一的一個(gè)對象,不允許外部在使用該類創(chuàng)建對象
private static OnlineUserMap onlineUserMap = new OnlineUserMap();
private Map<String ,String> stringMap = new HashMap<>();
private OnlineUserMap(){
}
public static OnlineUserMap getInstance(){
return onlineUserMap;
}
public Map<String, String> getStringMap() {
return stringMap;
}
public void setStringMap(Map<String, String> stringMap) {
this.stringMap = stringMap;
}
}
監(jiān)聽器
package com.lty.listener;
import com.lty.db.OnlineUserMap;
import com.lty.domain.User;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.util.HashMap;
import java.util.Map;
@WebListener()
public class OnlineListener implements
HttpSessionListener, HttpSessionAttributeListener {
// Public constructor is required by servlet spec
public OnlineListener() {
}
// -------------------------------------------------------
// HttpSessionListener implementation
// -------------------------------------------------------
public void sessionCreated(HttpSessionEvent se) {
/* Session is created. */
}
public void sessionDestroyed(HttpSessionEvent se) {
/* Session is destroyed. */
// 將當(dāng)前用戶從Map中刪除
OnlineUserMap onlineUserMap = OnlineUserMap.getInstance();
System.out.println("sessionDestroyed:" + onlineUserMap.getStringMap().get(se.getSession().getId()));
onlineUserMap.getStringMap().remove(se.getSession().getId());
}
// -------------------------------------------------------
// HttpSessionAttributeListener implementation
// -------------------------------------------------------
public void attributeAdded(HttpSessionBindingEvent sbe) {
/* This method is called when an attribute
is added to a session.
*/
String attr_name = sbe.getName();
String attr_value = (String)sbe.getValue();
System.out.println(attr_name);
System.out.println(attr_value);
System.out.println(sbe.getSession().getId());
OnlineUserMap onlineUserMap = OnlineUserMap.getInstance();
onlineUserMap.getStringMap().put(sbe.getSession().getId(),attr_value);
}
public void attributeRemoved(HttpSessionBindingEvent sbe) {
/* This method is called when an attribute
is removed from a session.
*/
}
public void attributeReplaced(HttpSessionBindingEvent sbe) {
/* This method is invoked when an attribute
is replaced in a session.
*/
}
}
servlet
登錄servlet(session的不激活時(shí)間:10s自動銷毀)
package com.lty.servlet;
import com.lty.db.OnlineUserMap;
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(name = "LoginServlet" , urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
request.getSession().setAttribute("username",username);
request.getSession().setMaxInactiveInterval(10);
request.setAttribute("users", OnlineUserMap.getInstance().getStringMap());
request.getRequestDispatcher("showuser.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
登出servlet
package com.lty.servlet;
import com.lty.db.OnlineUserMap;
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(name = "LogoutServlet" , urlPatterns = "/logout.do")
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
request.setAttribute("users", OnlineUserMap.getInstance().getStringMap());
request.getRequestDispatcher("showuser.jsp").forward(request,response);
}
}
查看在線用戶
package com.lty.servlet;
import com.lty.db.OnlineUserMap;
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(name = "ShowServlet" , urlPatterns = "/ShowUser.do")
public class ShowServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("users", OnlineUserMap.getInstance().getStringMap());
request.getRequestDispatcher("showuser.jsp").forward(request,response);
}
}