Filter过滤器和Listener监听器

2023.10.26

Filter过滤器

        过滤器,顾名思义就是对事物进行过滤的。Web中的过滤器,就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等。

        Filter可以在Servlet这个目标程序执行之前添加代码,也可以在目标Servlet执行之后添加代码,之前之后都可以添加过滤规则。一般情况下,都是在过滤器当中编写公共代码。所以通过过滤器可以实现代码重用的功能。

        如果同一个资源或同一组资源中应用了多个过滤器,则调用顺序显得比较重要,这时候就需要配置web.xml文件来控制其先后顺序。

如何实现一个过滤器?

  • 编写一个Java类实现一个接口:jarkata.servlet.Filter。并且实现这个接口当中所有的方法。
    • init方法:在Filter对象第一次被创建之后调用,并且只调用一次。
    • doFilter方法:只要用户发送一次请求,则执行一次。发送N次请求,则执行N次。在这个方法中编写过滤规则。
    • destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。

  • 在web.xml文件中对Filter进行配置。这个配置和Servlet很像。也可以使用注解@WebFilter

ps:Filter的生命周期 和Servlet的声明周期基本一样,唯一区别就是Servlet对象默认情况下,在服务器启动的时候是不会新建对象的。而Filter对象默认情况下,在服务器启动的时候会新建对象。

ps:Filter的优先级,天生的就比Servlet优先级高。

  • 目标Servlet是否执行,取决于两个条件:

    • 第一:在过滤器当中是否编写了:chain.doFilter(request, response); 代码。

    • 第二:用户发送的请求路径是否和Servlet的请求路径一致。

Filter过滤器使用案例:

先编写一个filter类实现Filter接口:

package filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;

import java.io.IOException;

@WebFilter("*.do")
public class filter1 implements Filter {

    public filter1() {
        System.out.println("无参构造执行了");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法执行了");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter方法执行了");
        // 执行下一个过滤器,如果下一个不是过滤器了,则执行目标程序Servlet。
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("doFilter方法执行结束");
    }

    @Override
    public void destroy() {
        System.out.println("destroy方法执行了");
    }
}

        chain.doFilter(request, response); 这行代码的作用: 执行下一个过滤器,如果下面没有过滤器了,执行最终的Servlet。

编写两个servlet类:

Aservlet:

package filter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/a.do")
public class Aservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Aservlet的doget方法执行了。");
    }
}

Bservlet:

package filter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/b.do")
public class Bservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Bservlet的doget方法执行了");
    }
}

注意两个servlet对应的路径必须以“.do”结尾,因为之前过滤器设定的路径是“ *.do ”。

然后在浏览器输入:http://localhost:8080/servlet09/a.do

控制台输出如下:

 

 然后在浏览器输入:http://localhost:8080/servlet09/b.do

控制台输出如下:

        如果有多个过滤器的情况:

①如果你是用注解进行配置的:过滤器执行顺序是根据Filter的类名来的。 比如:FilterA和FilterB,先执行FilterA。Filter1和Filter2,先执行Filter1。

②在web.xml文件中进行配置的时候,Filter的执行顺序是:从上至下依次执行。


Listener监听器

        Listener 是 Web 的三大组件之一,另外两大是Servlet(控制器)、Filter(过滤器)。

        Listener 可以 监听 JavaWeb 中的三大域对象:HttpServletRequest、HttpSession、ServletContext (创建和销毁),一旦被监视的对象发生相应的变化,应该采取相应的操作。

Servlet规范中提供了哪些监听器?

  • jakarta.servlet包下:

    • ServletContextListener(在context对象创建和销毁时调用,下同)

    • ServletContextAttributeListener(在context域的数据被修改时调用,下同)

    • ServletRequestListener

    • ServletRequestAttributeListener

  • jakarta.servlet.http包下:

    • HttpSessionListener

    • HttpSessionAttributeListener

      • 该监听器需要使用@WebListener注解进行标注。

      • 该监听器监听的是什么?是session域中数据的变化。只要数据变化,则执行相应的方法。主要监测点在session域对象上。

    • HttpSessionBindingListener

      • 该监听器不需要使用@WebListener进行标注。

      • 假设User类实现了该监听器,那么User对象在被放入session的时候触发bind事件,User对象从session中删除的时候,触发unbind事件。

      • 假设Customer类没有实现该监听器,那么Customer对象放入session或者从session删除的时候,不会触发bind和unbind事件。

    • HttpSessionIdListener(不常用)

      • session的id发生改变的时候,监听器中的唯一一个方法就会被调用。

    • HttpSessionActivationListener(不常用)

      • 监听session对象的钝化和活化的。

      • 钝化:session对象从内存存储到硬盘文件。

      • 活化:从硬盘文件把session恢复到内存。

实现一个监听器的步骤:

        以ServletContextListener为例,先编写一个类实现ServletContextListener接口,并且实现里面的方法。在web.xml文件中对ServletContextListener进行配置,或者使用注解@WebListener。这里直接使用注解,代码如下:

package listener;

import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;

// ServletContextListener监听器主要监听的是:ServletContext对象的状态。
@WebListener
public class MyServletContextListener implements ServletContextListener {

    /**
     * 监听器中的方法不需要程序员手动调用。是发生某个特殊事件之后被服务器调用。
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) { // 服务器启动时间点,想在这个时候执行一段代码,写就行了。
        // 这个方法是在ServletContext对象被创建的时候调用。
        System.out.println("ServletContext对象创建了。");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) { // 服务器关闭时间点。
        // 现在这个特殊的时刻写代码,你写就是了。它会被服务器自动调用。
        // 这个方法是在ServletContext对象被销毁的时候调用。
        System.out.println("ServletContext对象被销毁了。");
    }
}

此时启动服务器,控制台显示如下:

关闭服务器,控制台显示如下:

        

        

        

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值