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("无参构造执行了");}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("init方法执行了");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("doFilter方法执行了");// 执行下一个过滤器,如果下一个不是过滤器了,则执行目标程序Servlet。filterChain.doFilter(servletRequest,servletResponse);System.out.println("doFilter方法执行结束");}@Overridepublic 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 {@Overrideprotected 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 {@Overrideprotected 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*/@Overridepublic void contextInitialized(ServletContextEvent sce) { // 服务器启动时间点,想在这个时候执行一段代码,写就行了。// 这个方法是在ServletContext对象被创建的时候调用。System.out.println("ServletContext对象创建了。");}@Overridepublic void contextDestroyed(ServletContextEvent sce) { // 服务器关闭时间点。// 现在这个特殊的时刻写代码,你写就是了。它会被服务器自动调用。// 这个方法是在ServletContext对象被销毁的时候调用。System.out.println("ServletContext对象被销毁了。");}
}
此时启动服务器,控制台显示如下:
关闭服务器,控制台显示如下: