web监听器:
1.servler规范中定义的一种特殊类
2.用于监听ServlerContext,HttpSession,ServlerRequest等域对象的创建于销毁时事件
3.用于监听域对象的属性发生修改的事件
4.可以在事件发生前,发生后做一些必要的处理
web监听器的用途:
1.系统在线人数和在线用户
2.系统启动时加载初始化信息
3.统计网站访问量,每次请求通过监听器的request来获得
4.跟spring结合
web监听器的创建
1.创建一个实现监听器接口的类
2.配置web.xml进行注册
监听器的启动顺序
按照注册的顺序加载监听器,假如注册了监听器,过滤器,servler,他们的启动顺序如下:监听器>过滤器>servlet
监听器的分类
A.按监听的对象划分:
1.用于监听应用程序环境对象(ServletContext)的事件监听器
2.用于监听用户会话对象(HttpSession)的事件监听器
3.用于监听请求消息对象(ServletRequest)的事件监听器
对应的三个监听器:
ServletContextListener(监听ServletContext对象)
HttpSessionListener(监听HttpSession)
ServletRequestListener(监听ServletRequest)
B.按监听事件划分:
1.监听域对象自身的创建和销毁的事件监听器
2.监听域对象的属性的增加和删除的事件监听器
3.监听绑定到HttpSession域中的某个对象的状态的事件监听器
对应的三个监听器:
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
三个接口中都定义了属性的AttributeAdd,AttributeReplaced,AttributeRemoved
Servler3.0使用
类上添加@WebListener,然后实现以上6个接口之一
Springboot 创建监听器的步骤:以创建ServletContextListener 为例
方式一:
1.新建MyServlerContextListener,实现ServletContextListener,在监听器类上添加注解@WebListener,并且重写两个方法
a.contextInitialized初始化监听器
b.contextDestroyed销毁监听器
package com.example.guoq.CommonUtils;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyServlerContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println(">>>>>>>>>>ServletContextListener init>>>>>>>>>>>>");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println(">>>>>>>>>>ServletContextListener destroyed>>>>>>>>>>>>>>>>>>>>>>");
}
}
2.在springboot启动类上加注解@ServletComponentScan,开启对Servlet的注解扫描
package com.example.guoq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.启动springboot程序的时候会打印 ServletContextListener init
方式二
1.与方式一相同
2.新建ListenerConfig类,添加注解@Configuration,
package com.example.guoq.config;
import com.example.guoq.CommonUtils.MyServlerContextListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ListenerConfig {
@Bean
public MyServlerContextListener init(){
return new MyServlerContextListener();
}
}
3.springboot启动类无需添加任何注解,启动,打印ServletContextListener init。
=======================================
案例:统计网站在线人数
先上代码
1.创建登录用户对象,用于统计在线登录人数和统计登录ip,时间
package com.example.guoq.entity;
public class User {
private String sessionid;
private String ip;
private String firstTime;
public String getSessionid() {
return sessionid;
}
public void setSessionid(String sessionid) {
this.sessionid = sessionid;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getFirstTime() {
return firstTime;
}
public void setFirstTime(String firstTime) {
this.firstTime = firstTime;
}
}
2.创建类MyServletRequestListener实现ServletRequestListener ,在类上添加注解@WebListener,该类在初始化的时候创建用户列表,该用户包括属性sessionId,ip,firstime等
package com.example.guoq.sandaqi;
import com.example.guoq.entity.User;
import com.example.guoq.util.SessionUtil;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MyServletRequestListener implements ServletRequestListener {
List
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println(">>>>>>>>ServletRequestListner init>>>>>>");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println(">>>>>>>>ServletRequestListner destroyed>>>>>>");
userList=(List)sre.getServletContext().getAttribute("userList");
if(userList==null){
userList=new ArrayList<>();
}
HttpServletRequest servletRequest = (HttpServletRequest) sre.getServletRequest();
HttpSession session = servletRequest.getSession();
String sessionId=session.getId();
if(SessionUtil.getUserBySessionId(userList,sessionId)==null){
//如果不存在就添加到userList中
User user=new User();
user.setSessionid(sessionId);
user.setIp(servletRequest.getRemoteAddr());
user.setFirstTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
userList.add(user);
}
sre.getServletContext().setAttribute("userList",userList);
}
}
3.创建类MyHttpSessinListener 实现HttpSessionListener ,类上添加注解@WebListener,
在销毁的时候,从在线用户列表中移除该sessionid的用户对象。
package com.example.guoq.sandaqi;
import com.example.guoq.entity.User;
import com.example.guoq.util.SessionUtil;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.List;
@WebListener
public class MyHttpSessinListener implements HttpSessionListener {
private int count=0;
@Override
public void sessionCreated(HttpSessionEvent se) {
count++;
System.out.println(">>>>>HttpSessionListner init>>>>>>>>");
System.out.println(">>>>>session id>>>>>>>>"+se.getSession().getId());
se.getSession().getServletContext().setAttribute("count",count);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
count--;
System.out.println(">>>>>HttpSessionListner destroyed>>>>>>>");
se.getSession().getServletContext().setAttribute("count",count);
List
userList=(List) se.getSession().getServletContext().getAttribute("userList");
//通过sessionid拿到用户
User user= (User) SessionUtil.getUserBySessionId(userList,se.getSession().getId());
if(user!=null){
userList.remove(user);
}
}
}
4.SessionUtil工具类
package com.example.guoq.util;
import com.example.guoq.entity.User;
import java.util.List;
public class SessionUtil {
public static Object getUserBySessionId(List
for (int i = 0; i User user=userList.get(i); if(user.getSessionid().equals(sessionId)){ return user; } } return null; } } 5.新建controller中的方法,测试代码 @RequestMapping("/sessionCount") public String sessionCount(HttpServletRequest request){ HttpSession session = request.getSession(); System.out.println("controller session id "+session.getId()); Object count = session.getServletContext().getAttribute("count"); List StringBuilder sb=new StringBuilder(); if(userList!=null){ for (int i = 0; i User user=userList.get(i); sb.append(user.getSessionid()); sb.append("---------"); sb.append(user.getIp()); sb.append("---------"); sb.append(user.getFirstTime()); sb.append("\n"); } } return "在线人数:"+count+"\n"+sb.toString(); } 6.打开浏览器看效果(仅测试,忽略样式) 谷歌浏览器显示如下图 再打开uc浏览器,如下图 最后打开ie浏览器,如下图