过滤器,顾名思义就是对事物进行过滤的。Web中的过滤器,就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等。
Filter可以在Servlet这个目标程序执行之前添加代码,也可以在目标Servlet执行之后添加代码,之前之后都可以添加过滤规则。一般情况下,都是在过滤器当中编写公共代码。所以通过过滤器可以实现代码重用的功能。
如果同一个资源或同一组资源中应用了多个过滤器,则调用顺序显得比较重要,这时候就需要配置web.xml文件来控制其先后顺序。
destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。
ps:Filter的生命周期 和Servlet的声明周期基本一样,唯一区别就是Servlet对象默认情况下,在服务器启动的时候是不会新建对象的。而Filter对象默认情况下,在服务器启动的时候会新建对象。
ps:Filter的优先级,天生的就比Servlet优先级高。
目标Servlet是否执行,取决于两个条件:
第一:在过滤器当中是否编写了:chain.doFilter(request, response); 代码。
第二:用户发送的请求路径是否和Servlet的请求路径一致。
先编写一个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 是 Web 的三大组件之一,另外两大是Servlet(控制器)、Filter(过滤器)。
Listener 可以 监听 JavaWeb 中的三大域对象:HttpServletRequest、HttpSession、ServletContext (创建和销毁),一旦被监视的对象发生相应的变化,应该采取相应的操作。
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对象被销毁了。");
- }
- }
此时启动服务器,控制台显示如下:
关闭服务器,控制台显示如下: