zoukankan      html  css  js  c++  java
  • filter(过滤器)和listener(监听器)

    Filter

    简介

    Filter也称之为过滤器,是Servlet2.3新增的一个特性,主要用于过滤url请求,通过FIlter我们可以实现URL请求资源权限验证,用户登录检测等功能。

    Filter是一个接口,实现一个Filter只需要重写init、doFilter、destroy方法即可,其中过滤逻辑都在doFilter方法中实现。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

    Filter的工作原理

    Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:

    • 调用目标资源之前,让一段代码执行。
    • 是否调用目标资源(也就是是否让用户访问web资源)
    • 调用目标资源之后,让一段代码执行。

    web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

    Filter的使用

    通常,我们使用filter过滤器一般是用来进行一些统一的操作,比如登录验证,对拼接了用户输入的请求进行过滤等。

    定义步骤:

    • 定义一个类,视线接口Filter
    • 重写方法
    • 配置拦截路径

    针对于配置拦截路径的方法有两种,第一种就是之前经常使用的在代码前面加上注解进行配置,第二钟就是在web.xml中进行配置。

    注解配置拦截路径

    package Fileter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    
    
    @WebFilter("/*")
    public class Demo01 implements Filter{
        public void destroy(){
            System.out.println("filter销毁");
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            System.out.println("调用servlet之前执行一段代码");
            chain.doFilter(request,response);
            System.out.println("调用servlet之后执行的一段代码");
        }
    
        public void init(FilterConfig config) throws ServletException{
    
        }
    }
    

    web.xml配置拦截路径

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <filter>
            <filter-name>Demo01</filter-name>  //声明名字
            <filter-class>Fileter.Demo01</filter-class> //指定filter过滤器
        </filter>
        
        <filter-mapping>
            <filter-name>Demo01</filter-name>
            <url-pattern>/*</url-pattern> //声明拦截对象  
        </filter-mapping>
    </web-app>
    

    在刚才的代码演示里面,可以看到filter类需要重写三个方法,分别是:

    • init:在服务器启动后,会创建Filter对象,然后调用init方法,只执行一次,用于加载资源
    • doFilter:请求的时候执行的代码主体,如果我们需要让过滤器完成什么功能,就可以将代码写在其中,该方法会在每一次请求被拦截的时候执行,可执行多次
    • destroy:在服务器关闭后,Filter对象被销毁,如果服务器是正常关闭的,就会执行destroy方法,只执行一次,用来释放资源。

    除了之前演示的那种之外,拦截器还能拦截以下三种类型的请求。

    1. 具体资源路径:/test.jsp 如果这么定义,就会拦截指定的资源,也就是在用户访问这个页面的时候,过滤器才会执行。
    2. 目录拦截: /test/* 如果这么定义,就会拦截任意对指定文件夹发起的请求,也就是在用户访问这个目录下文件的时候,过滤器才会执行。
    3. 后缀名拦截: *.jsp 如果这么定义,就会拦截后缀名是.jsp的文件发起的请求,也就是在用户访问指定后悔名的时候,过滤器才会执行。

    定义拦截方式

    注解里面定义拦截路径,默认是REQUEST方式,也就是浏览器直接访问,使用转发或者是其他请求方式一样是会被拦截器给拦截的。

    如果我们希望转发访问资源不被拦截器拦截,可以在注解中配置dispatcherTypes属性的值。

    dispathcherTypes有五种属性:

    • REQUEST:浏览器直接请求资源(默认值)
    • FORWARD:转发访问资源
    • INCLUDE:包含访问资源
    • ERROR:错误跳转资源
    • ASYNC:异步访问资源

    注解方式定义拦截方式

    package Fileter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    
    
    @WebFilter(value = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})// 定义浏览器请求和转发拦截器执行
    public class Demo01 implements Filter{
        public void destroy(){
            System.out.println("filter销毁");
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            System.out.println("调用servlet之前执行一段代码");
            chain.doFilter(request,response);
            System.out.println("调用servlet之后执行的一段代码");
        }
    
        public void init(FilterConfig config) throws ServletException{
    
        }
    }
    

    web.xml配置定义拦截方式

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <filter>
            <filter-name>Demo01</filter-name>
            <filter-class>Fileter.Demo01</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>Demo01</filter-name>
            <url-pattern>/*</url-pattern>
            
            <dispatcher>REQUEST</dispatcher>
        </filter-mapping>
        
    </web-app>
    

    Filter链

    在一个web应用中,可以开发编写多个Filter,这些个Filter组合起来称之为Filter链。web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter, 如果有,则调用第二个filter,如果没有,则调用目标资源。

    Listener

    简介

    监听器用于监听web应用中某些对象、信息的创建、销毁、增加、修改、删除等动作的发生,然后做出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。

    分类

    按照监听的对象划分

    • ServletContext对象监听器
    • HttpSession对象监听器
    • ServletRequest对象监听器

    按监听的事件划分

    • 对象自身的创建和销毁的监听器
    • 对象中属性的创建和消除的监听器
    • session中的某个对象的状态彼岸花的监听器

    监听器的例子:用监听器统计网站在线人数

    原理:每当有一个访问连接到服务器时,服务器就会创建一个session来管理会话。那么我们就可以通过统计session的数量来获得当前在线人数。

    事件监听机制:

    • 事件:一件事情
    • 事件源:事件发生的地方
    • 监听器:一个对象
    • 注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生某个事件后,执行监听器代码

    监听器实现

    要实现监听器,我们首先需要实现ServletContextListener接口,该接口没有定义好的实现类,需要我们自己去定义。

    ServletContextListener方法

    • void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁之前会调用该方法
    • void contextInitialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法

    使用

    1. 配置web.xml

       <context-param>
              <param-name>configLocation</param-name>
              <param-value>/WEB-INF/config.xml</param-value>
          </context-param>
      
    2. 代码

      package Listener;
      
      import javax.servlet.ServletContext;
      import javax.servlet.ServletContextEvent;
      import javax.servlet.ServletContextListener;
      import javax.servlet.annotation.WebListener;
      import java.io.FileInputStream;
      import java.io.FileNotFoundException;
      
      @WebListener
      public class Demo01 implements ServletContextListener {
          @Override
          public void contextInitialized(ServletContextEvent servletContextEvent){
              ServletContext servletContext = servletContextEvent.getServletContext();
              String contextConfig = servletContext.getInitParameter("configLocation"); //获取configLocation参数
              String realPath = servletContext.getRealPath(contextConfig);//获取路径
              try {
                  FileInputStream fis = new FileInputStream(realPath);//读取文件
                  System.out.println(fis);
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              }
          }
      
          @Override
          public void contextDestroyed(ServletContextEvent servletContextEvent){
              System.out.println("listener被销毁了");
          }
      }
      

  • 相关阅读:
    CodeForces 660D Number of Parallelograms
    【POJ 1082】 Calendar Game
    【POJ 2352】 Stars
    【POJ 2481】 Cows
    【POJ 1733】 Parity Game
    【NOI 2002】 银河英雄传说
    【NOI 2015】 程序自动分析
    【POJ 1704】 Georgia and Bob
    【HDU 2176】 取(m堆)石子游戏
    【SDOI 2016】 排列计数
  • 原文地址:https://www.cnblogs.com/Xiaoming0/p/14147535.html
Copyright © 2011-2022 走看看