主要監(jiān)聽的三個域?qū)ο鬄椋篠ervletRequest域、HttpSession域 和ServletContext域。本文通過幾個簡單的例子介紹一下監(jiān)聽器的用法。

前言
監(jiān)聽器(Listener)就是監(jiān)聽對象的創(chuàng)建、銷毀等狀態(tài)的變化以及定義一些事件發(fā)生后接下來要進行的動作。主要監(jiān)聽的三個域?qū)ο鬄椋篠ervletRequest域、HttpSession域 和ServletContext域。本文通過幾個簡單的例子介紹一下監(jiān)聽器的用法。
ServletContextListener監(jiān)聽 Servlet上下文
監(jiān)聽 Servlet 上下文對象可以在系統(tǒng)啟動的時候初始化一些數(shù)據(jù),方便在使用的時候直接調(diào)用。監(jiān)聽器實現(xiàn)代碼如下:
@Component
public class MyServletContextListener implements ServletContextListener {
@Override //在 ServletContext 對象創(chuàng)建之后馬上調(diào)用,做初始化
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("name","九天銀河聊編程");
System.out.println("ServletContext 對象被創(chuàng)建了");
}
@Override // 在 ServletContext 對象銷毀之后調(diào)用
public void contextDestroyed(ServletContextEvent event) {
System.out.println("ServletContext 對象被銷毀了");
}
}
@GetMapping("/getServletContext")
public String getServletContext(HttpServletRequest request) {
ServletContext servletContext = request.getServletContext();
Object name = servletContext.getAttribute("name");
return String.valueOf(name);
}
執(zhí)行效果如下:

HttpSessionListener獲取在線用戶數(shù)量
@Component
public class MyHttpSessionListener implements HttpSessionListener {
public static Integer count = 0;
@Override
public void sessionCreated(HttpSessionEvent event) {
count++;
ServletContext application = event.getSession().getServletContext();
application.setAttribute("UserCount", count);
System.out.println("有人上線了,現(xiàn)在在線人數(shù)為:" + count + "人");
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
count--;
ServletContext application = event.getSession().getServletContext();
application.setAttribute("UserCount", count);
System.out.println("有人下線了,現(xiàn)在在線人數(shù)為:" + count + "人");
}
}
@GetMapping("/online")
public String getOnlinePersoncount(HttpServletRequest request) {
Integer userCount = (Integer) request.getServletContext().getAttribute("UserCount");
return (userCount == null ? "0" : userCount + "");
}
@GetMapping("/login")
public String logined(HttpSession session) {
//相同的session,如果sessionid一致,只會被監(jiān)聽一次。
session.setAttribute("username", "九天銀河聊編程");
return "success";
}
@GetMapping("/logout")
public String logout(HttpSession session) {
session.invalidate();//將session設(shè)置為失效
return "success";
}
執(zhí)行 127.0.0.1:8090/login,控制臺顯示:

執(zhí)行 127.0.0.1:8090/online,返回。

執(zhí)行 127.0.0.1:8090/logout,控制臺顯示。

ServletRequestListener統(tǒng)計網(wǎng)站訪問次數(shù)
@Component
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent){
Object countObject = servletRequestEvent.getServletContext().getAttribute("count");
System.out.println("歷史訪問次數(shù):" + countObject);
Integer count = 0;
if (countObject != null)
count = Integer.valueOf(countObject.toString());
count++;
servletRequestEvent.getServletContext().setAttribute("count", count);
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent){
System.out.println("當前訪問次數(shù):" + servletRequestEvent.getServletContext().getAttribute("count"));
}
}
隨便執(zhí)行一個接口請求,控制臺打印如下:

再次執(zhí)行:

自定義監(jiān)聽方式
定義監(jiān)聽事件
ublic class ListenerEvent extends ApplicationEvent {
String name = null;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public ListenerEvent(Object source, String value){
super(source);
name = value;
}
}
定義監(jiān)聽器
@Component
public class MySpringBootListener implements ApplicationListener<ListenerEvent> {
@Override
public void onApplicationEvent(ListenerEvent listenerEvent){
String eventInfo = listenerEvent.getName();
System.out.println(eventInfo);
}
}
發(fā)布事件
@RestController
public class ListenerController {
@Resource
private ApplicationContext applicationContext;
@GetMapping("/listener")
public String listener() {
ListenerEvent event =new ListenerEvent(this,"九天銀河聊編程");
applicationContext.publishEvent(event);
return "";
}
}
執(zhí)行 127.0.0.1:8090/listener,控制臺顯示。

監(jiān)聽器說明
在目前的Servlet API中提供的web事件監(jiān)聽器接口有以下幾個:
ServletContextListener -- 監(jiān)聽servletContext對象的創(chuàng)建以及銷毀
contextInitialized(ServletContextEvent event) -- 創(chuàng)建時執(zhí)行
contextDestroyed(ServletContextEvent event) -- 銷毀時執(zhí)行
HttpSessionListener -- 監(jiān)聽session對象的創(chuàng)建以及銷毀
sessionCreated(HttpSessionEvent event) -- 創(chuàng)建時執(zhí)行
sessionDestroyed(HttpSessionEvent event) -- 銷毀時執(zhí)行
ServletRequestListener -- 監(jiān)聽request對象的創(chuàng)建以及銷毀
requestInitialized(ServletRequestEvent event) -- 創(chuàng)建時執(zhí)行
requestDestroyed(ServletRequestEvent event) -- 銷毀時執(zhí)行
ServletContextAttributeListener -- 監(jiān)聽servletContext對象中屬性的改變
attributeAdded(ServletContextAttributeEvent event) -- 添加屬性時執(zhí)行
attributeReplaced(ServletContextAttributeEvent event) -- 修改屬性時執(zhí)行
attributeRemoved(ServletContextAttributeEvent event) -- 刪除屬性時執(zhí)行
HttpSessionAttributeListener --監(jiān)聽session對象中屬性的改變
attributeAdded(HttpSessionBindingEvent event) -- 添加屬性時執(zhí)行
attributeReplaced(HttpSessionBindingEvent event) -- 修改屬性時執(zhí)行
attributeRemoved(HttpSessionBindingEvent event) -- 刪除屬性時執(zhí)行
ServletRequestAttributeListener --監(jiān)聽request對象中屬性的改變
attributeAdded(ServletRequestAttributeEvent event) -- 添加屬性時執(zhí)行
attributeReplaced(ServletRequestAttributeEvent event) -- 修改屬性時執(zhí)行
attributeRemoved(ServletRequestAttributeEvent event) -- 刪除屬性時執(zhí)行
生命周期
request
指一個URL請求,當發(fā)送一個請求時被創(chuàng)建,當一個響應(yīng)返回時,即被銷毀。
session
? 當一個客戶端訪問一個WEB應(yīng)用時創(chuàng)建,標記一個用戶與服務(wù)器之間的多次請求。session失效有以下幾個情況:
- session 過期,即用戶長時間不訪問服務(wù)器造成過期
- 用戶退出系統(tǒng),即執(zhí)行session 的 invalidate 方法,清理session
- 當前 web 應(yīng)用被卸載(session 未被持久化)
application
? 貫穿于當前的 WEB 應(yīng)用的生命周期,當前 WEB 應(yīng)用被加載時創(chuàng)建 application 對象,當前 WEB 應(yīng)用被卸載時銷毀 application 對象。