JAVAweb之过滤器,监听器

news/2025/2/26 6:14:17

文章目录

  • 过滤器
    • 认识
    • 生命周期
    • FilterConfig
    • FilterChain
    • 过滤器执行顺序
    • 应用场景
    • 代码
  • 监听器
    • 认识
    • ServletContextListener
    • HttpSessionListener
    • ServletRequestListener
    • 代码

过滤器

认识

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. 自动销毁
     */
}

http://www.niftyadmin.cn/n/5868161.html

相关文章

python绑定udp时使用127.0.0.1作为ip,无法sendto,报错Invalid argument

在 Python 中使用 UDP 套接字进行通信时&#xff0c;绑定127.0.0.1作为 IP 地址后无法使用sendto方法发送数据&#xff0c;可能由多种原因导致 这里是其中一个原因&#xff1a; 127.0.0.1 是本地回环地址&#xff0c;只能用于本机内部的进程间通信&#xff0c; 如果你绑定到 …

《OpenCV》—— 背景建模

背景建模是什么&#xff1f; 背景建模的意义&#xff1f; 通过背景建模&#xff0c;我们可以实现很多应用&#xff0c;例如运动检测、目标跟踪 背景建模的方法 帧差法 帧差法的原理 基于 K 近邻的前景分割算法&#xff08;KNN&#xff09; 原理 基于 K 近邻的前景分割算法…

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: #

pytest下放pytest.ini文件就导致报错&#xff1a;ERROR: file or directory not found: # 如下&#xff1a; 项目文件目录如下&#xff1a; pytest.ini文件内容&#xff1a; [pytest] addopts -v -s --alluredir ./allure-results # 自动添加的命令行参数&#xff1a;# -…

【利用conda配置管理Python版本和依赖环境】

1. 创建新的Python环境 # conda create -n [虚拟环境名] python[python指定的版本] # -y直接安装不用询问&#xff0c;没有时&#xff0c;会提示询问等待用户确定才安装 conda create -n pygnu python3.10 -y验证并检查新建的Python环境 conda activate pygun python --versi…

uni-app 开发 App 、 H5 横屏签名(基于lime-signature)

所用插件&#xff1a;lime-signature 使用到 CSS 特性 绝对定位transform 旋转transform-origin transform 原点 复习一下定位元素&#xff08;相对定位、绝对定位、粘性定位&#xff09; 代码# <template><view class"signature-page"><view clas…

Java多线程中的死锁问题

1.什么是死锁 线程在获取资源的时候&#xff0c;由于获取不到&#xff0c;导致线程卡死&#xff08;阻塞&#xff09;&#xff0c;程序就不执行了。 2.发生死锁的情况 1.一个线程获取一把锁 一个线程如果同时获取一把锁两次&#xff0c;如果是可重入锁&#xff0c;就没有问…

Maven 从下载到实战,xml帮助文档

一、Maven 免费下载 1. 官方下载地址 官网推荐&#xff1a;访问 Maven 官网&#xff0c;选择最新稳定版本&#xff08;如 3.8.1 或 3.6.3&#xff09;的 bin.zip 文件179。 国内镜像&#xff1a;若官网下载缓慢&#xff0c;可使用以下网盘资源&#xff08;注意版权风险&#…

Mac 上安装多版本的 JDK 且实现 自由切换

1.可以通过查看以下目录中的内容&#xff0c;确认当前已经安装的 jdk 版本。 cd /Library/Java/JavaVirtualMachines2.命令行查看 jdk 的安装路径 /usr/libexec/java_home -V3.下载要安装的jdk版本&#xff0c;修改环境变量( cat ~/.bash_profile) # 定义JDK 8和JDK 17的安装路…