监听器Listener
介绍
Listener是JavaEE的规范,就是接口
监听器的作用是,监听某种变化(一般就是对象创建/销毁, 属性变化), 触发对应方法完成相应的任务
ServletContextListener监听器(最常用)
作用:
监听ServletContext创建或销毁(当我们Web应用启动时,就会创建ServletContext), 即生命周期监听
应用场景:
(1)加载初始化的配置文件;比如spring的配置文件
(2)任务调度(配合定时器Timer/TimerTask)
相关方法:
void contextInitialized(ServletContextEvent sce) 创建Servletcontext时触发
void contextDestroyed(ServletContextEvent sce) 销毁Servletcontext时触发
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
//当一个类实现了ServletContextListener,该类就是一个监听器
//该类可以监听的事件由该类实现的监听接口决定,比如实现ServletContextListener,则该类就可以监听ServletContext对象的创建和销毁
//HspServletContext就是一个监听者
//当web应用启动时,就会产生ServletContextEvent事件,会调用监听器的对应事件处理方法contextInitialized,同时会传递事件对象
//程序员可以通过servletContextEvent事件对象,来获取需要的信息,然后再进行业务处理
public class HspServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//获取到servletContext对象
ServletContext servletContext = servletContextEvent.getServletContext();
System.out.println("HspServletContextListener监听到" + servletContext + "被创建");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
System.out.println("HspServletContextListener监听到" + servletContext + "被销毁");
}
}
配置xml
<listener>
<listener-class>HspServletContextListener</listener-class>
</listener>
ServletContextAttributeListener监听器(最常用)
作用:
监听ServletContext属性变化
相关方法:
void attributeAdded(ServletContextAttributeEventevent) 添加属性时调用
void attributeReplaced(ServletContextAttributeEventevent) 替换属性时调用
void attributeRemoved(ServletContextAttributeEventevent) 移除属性时调用
public class HspServletContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("监听到添加属性" + servletContextAttributeEvent.getName() + "=" + servletContextAttributeEvent.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("监听到修改属性" + servletContextAttributeEvent.getName() + "=" + servletContextAttributeEvent.getValue());
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("监听到删除属性" + servletContextAttributeEvent.getName() + "=" + servletContextAttributeEvent.getValue());
}
}
/*
监听到添加属性name=abc
监听到修改属性name=abc => 还是显示原来的value
监听到删除属性name=ddd
Hi处理完毕
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("name","abc");
servletContext.setAttribute("name","ddd");
servletContext.removeAttribute("name");
System.out.println("Hi处理完毕");
}
HttpSessionListener监听器(常用)
作用:
监听Session创建或销毁,即生命周期监听,可以用于监控用户上线,离线
相关方法:
void sessionCreated(HttpSessionEvent se) 创建session时调用
void sessionDestroyed(HttpSessionEvent se) 销毁session时调用
public class HspHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
//当session创建时,设置生命周期
session.setMaxInactiveInterval(10);
System.out.println("监听到session创建= " + session.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
System.out.println("监听到session销毁= " + session.getId());
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
}
HttpSessionAttributeListener监听器
作用:
监听Session属性的变化
相关方法:
void attributeAdded(ServletRequestAttributeEvent srae) 添加属性时
void attributeReplaced(ServletRequestAttributeEvent srae) 替换属性时
void attributeRemoved(ServletRequestAttributeEvent srae) 移除属性时
public class HspHttpSessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
//HttpSession session = httpSessionBindingEvent.getSession();
System.out.println("监听到session添加属性" + httpSessionBindingEvent.getName() + "=" +httpSessionBindingEvent.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("监听到session删除属性" + httpSessionBindingEvent.getName());
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("监听到session修改属性" + httpSessionBindingEvent.getName() + "=" +httpSessionBindingEvent.getValue());
}
}
/*
监听到session添加属性age=10
监听到session修改属性age=10
监听到session删除属性age
处理完毕
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("age",10);
session.setAttribute("age",20);
session.removeAttribute("age");
System.out.println("处理完毕");
}
ServletRequestListener监听器(常用)
作用:
监听Request创建或销毁,即Request生命周期监听
可以用来监控,某个IP访问我们网站的频率,日志记录,访问资源的情况
相关方法:
void requestInitialized(ServletRequestEvent sre) 创建request时
void requestDestroyed(ServletRequestEvent sre) 销毁request时
public class HspRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("监听到request对象被销毁");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("监听到request对象创建");
ServletRequest servletRequest = servletRequestEvent.getServletRequest();
System.out.println("记录访问日志...");
System.out.println("访问IP=" + servletRequest.getRemoteAddr());
System.out.println("访问的资源=" + ((HttpServletRequest)servletRequest).getRequestURL());
}
}
ServletRequestAttributeListener监听器
作用:
监听Request属性变化
相关方法:
void attributeAdded(ServletRequestAttributeEvent srae) 添加属性时
void attributeReplaced(ServletRequestAttributeEvent srae) 替换属性时
void attributeRemoved(ServletRequestAttributeEvent srae) 移除属性时
过滤器Filter
介绍
Filter 过滤器是 JavaEE 的规范,是接口
Filter 过滤器作用是:拦截请求,过滤响应
应用场景:权限检查、日记操作、事务管理
为什么需要过滤器
基本原理
在web.xml中,filter一般写在其他servlet的前面
应用
web.xml
<filter>
<filter-name>ManageFilter</filter-name>
<filter-class>ManageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ManageFilter</filter-name>
<!--
/manage/* 第一个/解析成http://ip:port/工程路径
当请求的资源url满足该条件时,就会调用该filter
-->
<url-pattern>/manage/*</url-pattern>
</filter-mapping>
登录
public class logincheck extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
if("123456".equals(pwd)) {
request.getSession().setAttribute("username",username);
//请求转发不会经过 过滤器
request.getRequestDispatcher("/manage/admin.jsp").forward(request,response);
} else {
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
}
admin.jsp
浏览器第一次请求结束,发送第二次请求<img>,会调用dofilter()
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hi</title>
<base href="<%=request.getContextPath()%>/manage/">
</head>
<body>
<h1>admin目录下的 hi.jsp</h1>
<h1>后台管理</h1>
<a href="#">用户列表</a>||<a href="#">添加用户</a>||<a href="#">删除用户</a>
<hr/>
<img src="abc.png" height="400px"/>
</body>
</html>
过滤器
public class ManageFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//当Tomcat创建Filter后,就会调用该方法,进行初始化
System.out.println("init被调用");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//到每次调用该filter时,doFilter就会被调用
//如果这里,没有调用继续请求的方法,则就停止
//如果继续访问目标资源-> 等价于放行
//老师说明:在调用过滤器前,servletRequest对象=request已经被创建并封装
//所以:我们这里就可以通过servletRequest获取很多信息, 比如访问url , session
//比如访问的参数 ... 就可以做事务管理,数据获取,日志管理等
//获取到session
//可以继续使用 httpServletRequest 方法.
System.out.println("doFiter被调用");
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
HttpSession session = httpServletRequest.getSession();
Object username = session.getAttribute("username");
if(username != null) {
//filterChain.doFilter(servletRequest, servletResponse)
//1. 继续访问目标资源url
//2. servletRequest 和 servletResponse 对象会传递给目标资源/文件
//3. 一定要理解filter传递的两个对象,再后面的servlet/jsp 是同一个对象(指的是在一次http请求)
System.out.println("servletRequest=" + servletRequest);
System.out.println("日志信息==");
System.out.println("访问的用户名=" + username.toString());
System.out.println("访问的url=" + httpServletRequest.getRequestURL());
System.out.println("访问的IP=" + httpServletRequest.getRemoteAddr());
filterChain.doFilter(servletRequest, servletResponse);
} else {
//说明没有登录过,回到登录页面
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
//当filter被销毁时,会调用该方法
System.out.println("destroy被调用");
}
}
过滤器url-pattern
Filter生命周期
- 1. filter在web项目启动时, 由tomcat 来创建filter实例, 只会创建一个,换个浏览器也是同一个
- 2. 会调用filter默认的无参构造器, 同时会调用 init方法, 只会调用一次
- 3. 在创建filter实例时,同时会创建一个FilterConfig对象,并通过init方法传入
- 4. 通过FilterConfig对象,程序员可以获取该filter的相关配置信息
- 5. 当一个http请求和该filter的的url-patter匹配时,就会调用doFilter方法
- 6. 在调用doFilter方法时,tomcat会同时创建ServletRequest 和 ServletResponse 和 FilterChain对象, 并通过doFilter传入.
- 7. 如果后面的请求目标资源(jsp,servlet..) 会使用到request,和 response,那么会继续传递
FilterConfig
<filter>
<filter-name>HspFilterConfig</filter-name>
<filter-class>com.hspedu.filter.HspFilterConfig</filter-class>
<!--这里就是给该filter配置的参数-有程序员根据业务逻辑来设置-->
<init-param>
<param-name>ip</param-name>
<param-value>127.0</param-value>
</init-param>
<init-param>
<param-name>port</param-name>
<param-value>8888</param-value>
</init-param>
<init-param>
<param-name>email</param-name>
<param-value>hsp@sohu.com</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HspFilterConfig</filter-name>
<url-pattern>/abc/*</url-pattern>
</filter-mapping>
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("HspFilterConfig init() 被调用..");
//通过filterConfig 获取相关的参数
String filterName = filterConfig.getFilterName();
ip = filterConfig.getInitParameter("ip");
ServletContext servletContext = filterConfig.getServletContext();
//可以获取到该filter所有的配置参数名
Enumeration<String> initParameterNames =
filterConfig.getInitParameterNames();
//遍历枚举
while (initParameterNames.hasMoreElements()) {
System.out.println("名字=" + initParameterNames.nextElement());
}
System.out.println("filterName= " + filterName);
System.out.println("ip= " + ip);
System.out.println("servletContext= " + servletContext);
}
FilterChain过滤器链
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("AFilter---> 线程id=" +
Thread.currentThread().getId());
System.out.println("AFilter doFilter 的前置代码...");
System.out.println("执行 AFilter doFilter()");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("AFilter doFilter 的后置代码...");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("BFilter---> 线程id=" +
Thread.currentThread().getId());
System.out.println("BFilter doFilter 的前置代码...");
System.out.println("执行 BFilter doFilter()");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("BFilter doFilter 的后置代码...");
}
执行顺序取决于web.xml的配置顺序