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

前言
監(jiān)聽器(Listener)就是監(jiān)聽對(duì)象的創(chuàng)建、銷毀等狀態(tài)的變化以及定義一些事件發(fā)生后接下來要進(jìn)行的動(dòng)作。主要監(jiān)聽的三個(gè)域?qū)ο鬄椋篠ervletRequest域、HttpSession域 和ServletContext域。本文通過幾個(gè)簡(jiǎn)單的例子介紹一下監(jiān)聽器的用法。
ServletContextListener監(jiān)聽 Servlet上下文
監(jiān)聽 Servlet 上下文對(duì)象可以在系統(tǒng)啟動(dòng)的時(shí)候初始化一些數(shù)據(jù),方便在使用的時(shí)候直接調(diào)用。監(jiān)聽器實(shí)現(xiàn)代碼如下:
@Component
public class MyServletContextListener implements ServletContextListener {
@Override //在 ServletContext 對(duì)象創(chuàng)建之后馬上調(diào)用,做初始化
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("name","九天銀河聊編程");
System.out.println("ServletContext 對(duì)象被創(chuàng)建了");
}
@Override // 在 ServletContext 對(duì)象銷毀之后調(diào)用
public void contextDestroyed(ServletContextEvent event) {
System.out.println("ServletContext 對(duì)象被銷毀了");
}
}
@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一致,只會(huì)被監(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,控制臺(tái)顯示:

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

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

ServletRequestListener統(tǒng)計(jì)網(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("當(dāng)前訪問次數(shù):" + servletRequestEvent.getServletContext().getAttribute("count"));
}
}
隨便執(zhí)行一個(gè)接口請(qǐng)求,控制臺(tái)打印如下:

再次執(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,控制臺(tái)顯示。

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