JAVAweb之过滤器,监听器

发布于:2025-02-26 ⋅ 阅读:(17) ⋅ 点赞:(0)

过滤器

认识

Java web三大组件之一,与Servlet相似。过滤器是用来拦截请求的,而非处理请求。

当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,才会接着执行用户请求的Servlet(或者接着执行其它的Filter)。

过滤器需要实现Filter接口,其源码如下:

public interface Filter {
    void init(FilterConfig var1) throws ServletException;

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    void destroy();
}

生命周期

  • void init(FilterConfig var1):在服务器启动时会创建Filter实例,并且每个类型的Filter只有一个实例。创建完实例后,会马上执行init()方法完成初始化工作,且这个方法只会执行一次。
  • doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户访问“目标资源时”(index.jsp)时执行。如果需要放行,则执行FilterChain var3的doFilter(ServletRequest,ServletResponse)方法;如果不需要放心,则不调用该方法,目标资源则无法访问。
  • destroy():服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。

FilterConfig

Filter接口中的init()方法的参数类型为FilterConfig类型,它的功能与ServletConfig相似,与web.xml文件中的配置信息对应。下面是FilterConfig的功能介绍:

  • ServletContext getServletContext():获取ServletContext的方法;

  • String getFilterName():获取Filter的配置名称;与元素对应;

  • String getInitParameter(String name):获取Filter的初始化配置,与元素对应;

  • Enumeration getInitParameterNames():获取所有初始化参数的名称。

<filter>
    <filter-name>FliterOne</filter-name>
    <filter-class>com.luxiya.konghua.FliterOne</filter-class>
    <init-param>
        <param-name>name</param-name>
        <param-value>luxiya</param-value>
    </init-param>
    <init-param>
        <param-name>age</param-name>
        <param-value>18</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>FliterOne</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

public class FliterOne implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器一初始化");
        String filterName = filterConfig.getFilterName();
        System.out.println("过滤器名称:" + filterName);
        String name = filterConfig.getInitParameter("name");
        System.out.println("过滤器参数名称:" + name);
        Enumeration<String> names = filterConfig.getInitParameterNames();
        while (names.hasMoreElements()){
            String name = names.nextElement();
            String value = filterConfig.getInitParameter(name);
            System.out.println("元素:" + name + "  过滤器值:" + value);
        }
    }
    
----------------结果-----------------    
过滤器一初始化
过滤器名称:FliterOne
过滤器参数名称:luxiya
元素:name  过滤器值:luxiya
元素:age  过滤器值:18

FilterChain

doFilter()方法的参数中有一个类型为FilterChain的参数,它只有一个方法:doFilter(ServletRequest,ServletResponse)。

一个目标资源上,可能部署了多个过滤器,如果当前过滤器是最后一个过滤器,那么调用chain.doFilter()方法表示执行目标资源,而不是最后一个过滤器,那么chain.doFilter()表示执行下一个过滤器的doFilter()方法。

过滤器执行顺序

  • web.xml:一个目标资源可以指定多个过滤器,过滤器的执行顺序是在web.xml文件中的部署顺序。

  • 注释:

    在 Servlet 3.0 及以上版本中,可以使用 @WebFilter 注解来配置过滤器。此时,过滤器的执行顺序由 @Order 注解或 @Priority 注解来决定。

    @Order 注解的值越小,优先级越高,过滤器会先执行;@Priority 注解的值越小,优先级也越高,过滤器先执行。

应用场景

  • 执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;

  • 通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;

  • 在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理

代码

---------------------过滤器一-------------------
public class FliterOne implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器一初始化");
        String filterName = filterConfig.getFilterName();
        System.out.println("过滤器名称:" + filterName);
        String root = filterConfig.getInitParameter("name");
        System.out.println("过滤器根路径:" + root);
        Enumeration<String> names = filterConfig.getInitParameterNames();
        while (names.hasMoreElements()){
            String name = names.nextElement();
            String value = filterConfig.getInitParameter(name);
            System.out.println("元素:" + name + "  过滤器值:" + value);
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");


        System.out.println("过滤器一检测中");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("过滤器一检测后");

    }

    @Override
    public void destroy() {
        System.out.println("过滤器一销毁");
    }
}
---------------------过滤器二-------------------
public class FilterTwo implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器二检测中");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("过滤器二检测后");
    }

    @Override
    public void destroy() {

    }
}
---------------------web.xml-------------------
    <filter>
        <filter-name>FliterOne</filter-name>
        <filter-class>com.luxiya.konghua.FliterOne</filter-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>luxiya</param-value>
        </init-param>
        <init-param>
            <param-name>age</param-name>
            <param-value>18</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FliterOne</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>FilterTwo</filter-name>
        <filter-class>com.luxiya.konghua.FilterTwo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterTwo</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ---------------------结果-------------------
过滤器一初始化
过滤器名称:FliterOne
过滤器根路径:luxiya
元素:name  过滤器值:luxiya
元素:age  过滤器值:18

过滤器一检测中
过滤器二检测中

Hello Servlet,我执行了HelloServlet

过滤器二检测后
过滤器一检测后

监听器

认识

在JavaWeb被监听的事件源为:ServletContext、HttpSession、ServletRequest,即三大域对象。

  • 监听域对象“创建”与“销毁”的监听器;

  • 监听域对象“操作域属性”的监听器;

  • 监听HttpSession的监听器。

ServletContextListener

ServletContextListener:Tomcat启动和关闭时调用下面两个方法:

  • public void contextInitialized(ServletContextEvent evt):ServletContext对象被创建后调用;

  • public void contextDestroyed(ServletContextEvent evt):ServletContext对象被销毁前调用;

HttpSessionListener

HttpSessionListener:开始会话和结束会话时调用下面两个方法

  • public void sessionCreated(HttpSessionEvent evt):HttpSession对象被创建后调用;

  • public void sessionDestroyed(HttpSessionEvent evt):HttpSession对象被销毁前调用;

ServletRequestListener

ServletRequestListener:开始请求和结束请求时调用下面两个方法

  • public void requestInitiallized(ServletRequestEvent evt):ServletRequest对象被创建后调用;

  • public void requestDestroyed(ServletRequestEvent evt):ServletRequest对象被销毁前调用。

代码

public class Listener implements ServletContextListener, HttpSessionListener, ServletRequestListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("监听器初始化---ServletContext对象被创建后调用");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("监听器销毁---ServletContext对象被销毁后调用");
    }

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("监听器销毁---ServletRequest对象被销毁后调用");
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("监听器初始化---ServletRequest对象被创建后调用");
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("监听器初始化---HttpSession对象被创建后调用");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("监听器销毁---HttpSession对象被销毁后调用");
    }
}
-------------------结果----------------
监听器初始化---ServletContext对象被创建后调用
过滤器一初始化
过滤器名称:FliterOne
过滤器根路径:luxiya
元素:name  过滤器值:luxiya
元素:age  过滤器值:18
[2025-02-25 08:31:10,220] Artifact fliter_listener:war exploded: Artifact is deployed successfully
[2025-02-25 08:31:10,220] Artifact fliter_listener:war exploded: Deploy took 226 milliseconds
监听器初始化---ServletRequest对象被创建后调用
过滤器一检测中
过滤器二检测中
监听器初始化---HttpSession对象被创建后调用(第一次请求才有)
Hello Servlet,我执行了HelloServlet
过滤器二检测后
过滤器一检测后
监听器销毁---ServletRequest对象被销毁后调用

统计网站人数例子

//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {

    //创建session监听: 看你的一举一动
    //一旦创建Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }

    //销毁session监听
    //一旦销毁Session就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }


    /*
    Session销毁:
    1. 手动销毁  getSession().invalidate();
    2. 自动销毁
     */
}