• 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接口:

    1. package filter;
    2. import jakarta.servlet.*;
    3. import jakarta.servlet.annotation.WebFilter;
    4. import java.io.IOException;
    5. @WebFilter("*.do")
    6. public class filter1 implements Filter {
    7. public filter1() {
    8. System.out.println("无参构造执行了");
    9. }
    10. @Override
    11. public void init(FilterConfig filterConfig) throws ServletException {
    12. System.out.println("init方法执行了");
    13. }
    14. @Override
    15. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    16. System.out.println("doFilter方法执行了");
    17. // 执行下一个过滤器,如果下一个不是过滤器了,则执行目标程序Servlet。
    18. filterChain.doFilter(servletRequest,servletResponse);
    19. System.out.println("doFilter方法执行结束");
    20. }
    21. @Override
    22. public void destroy() {
    23. System.out.println("destroy方法执行了");
    24. }
    25. }

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

    编写两个servlet类:

    Aservlet:

    1. package filter;
    2. import jakarta.servlet.ServletException;
    3. import jakarta.servlet.annotation.WebServlet;
    4. import jakarta.servlet.http.HttpServlet;
    5. import jakarta.servlet.http.HttpServletRequest;
    6. import jakarta.servlet.http.HttpServletResponse;
    7. import java.io.IOException;
    8. @WebServlet("/a.do")
    9. public class Aservlet extends HttpServlet {
    10. @Override
    11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    12. System.out.println("Aservlet的doget方法执行了。");
    13. }
    14. }

    Bservlet:

    1. package filter;
    2. import jakarta.servlet.ServletException;
    3. import jakarta.servlet.annotation.WebServlet;
    4. import jakarta.servlet.http.HttpServlet;
    5. import jakarta.servlet.http.HttpServletRequest;
    6. import jakarta.servlet.http.HttpServletResponse;
    7. import java.io.IOException;
    8. @WebServlet("/b.do")
    9. public class Bservlet extends HttpServlet {
    10. @Override
    11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    12. System.out.println("Bservlet的doget方法执行了");
    13. }
    14. }

    注意两个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。这里直接使用注解,代码如下:

    1. package listener;
    2. import jakarta.servlet.ServletContextEvent;
    3. import jakarta.servlet.ServletContextListener;
    4. import jakarta.servlet.annotation.WebListener;
    5. // ServletContextListener监听器主要监听的是:ServletContext对象的状态。
    6. @WebListener
    7. public class MyServletContextListener implements ServletContextListener {
    8. /**
    9. * 监听器中的方法不需要程序员手动调用。是发生某个特殊事件之后被服务器调用。
    10. * @param sce
    11. */
    12. @Override
    13. public void contextInitialized(ServletContextEvent sce) { // 服务器启动时间点,想在这个时候执行一段代码,写就行了。
    14. // 这个方法是在ServletContext对象被创建的时候调用。
    15. System.out.println("ServletContext对象创建了。");
    16. }
    17. @Override
    18. public void contextDestroyed(ServletContextEvent sce) { // 服务器关闭时间点。
    19. // 现在这个特殊的时刻写代码,你写就是了。它会被服务器自动调用。
    20. // 这个方法是在ServletContext对象被销毁的时候调用。
    21. System.out.println("ServletContext对象被销毁了。");
    22. }
    23. }

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

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

            

            

            

  • 相关阅读:
    自己动手从零写桌面操作系统GrapeOS系列教程——1.1 GrapeOS介绍
    逆向-还原代码之运算符++ (Interl 64)
    操作系统的发展与分类
    WebSocket的原理与优缺点
    unity中的常用属性修饰符
    GBASE 8C——SQL参考6 sql语法(7)
    如何自己开传奇单机架设超详细图文教程
    用例图中include和extend的含义
    pnpm入门教程
    SQL面试题(2)
  • 原文地址:https://blog.csdn.net/m0_61028090/article/details/134060537