监听器Listener + 过滤器Filter

监听器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的配置顺序

注意事项和细节

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值