zoukankan      html  css  js  c++  java
  • 过滤器原理及使用

     

    过滤器

      Servlet过滤器可以对Servlet、JSP和HTML文件过滤。

      过滤器在实际开发中用得较多,是属于较重点的内容。

      主要是处理session信息,登陆请求。也可以启动框架内部的某些。

    Servlet过滤器的概念

      Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。

      Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用。

      Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request Header和Request内容。

      在Servlet被调用之后检查Response对象,修改Response Header和Response内容。

      Servlet过滤器负责过滤的Web组件可以是Servlet、JSP或HTML文件

    Servlet过滤器的过滤过程

     

      过滤器的处理过程是一个链式的过程(FilterChain),即多个过滤器组成一个链,依次处理,最后交给过滤器之后的资源。

      其中链式过滤过程中也可以直接给出响应,即返回,而不是向后传递。

     

    Filter接口

      所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。

      这个接口含有3个过滤器类必须实现的方法:

      init(FilterConfig):这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。

      在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数。

      比如web.xml中声明:

    复制代码
        <filter>
            <filter-name>MyFilter1</filter-name>
            <filter-class>com.mengdd.filter.MyFilter1</filter-class>
            <init-param>
                <param-name>hello</param-name>
                <param-value>world</param-value>
            </init-param>
            <init-param>
                <param-name>name</param-name>
                <param-value>zhang</param-value>
            </init-param>
        </filter>
    复制代码

      在MyFilter1中:

    复制代码
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
            String paramValue1 = filterConfig.getInitParameter("hello");
            String paramValue2 = filterConfig.getInitParameter("name");
    
            ServletContext context = filterConfig.getServletContext();
        }
    复制代码

      注意:一旦一个过滤器启动失败,会导致整个Web应用启动失败。

      doFilter(ServletRequest, ServletResponse, FilterChain):这个方法完成实际的过滤操作。

      当客户请求访问与过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法

      FilterChain参数用于访问后续过滤器。

      在这个方法中调用chain.doFilter()方法,用于调用过滤器链中后续过滤器的doFilter()方法,假如没有后续过滤器,那么就把客户请求传给相应的Web组件。

      如果在这个方法中没有调用chain.doFilter()方法,客户请求不会到达所访问的Web组件。

     

      destroy():Servlet容器在销毁过滤器实例前调用该方法,在这个方法中可以释放Servlet过滤器占用的资源。

    过滤器的例子

      比如用户登录之后,将信息传入session中,之后的其他页面入口可能需要 检测是否存在session,以避免直接在地址栏输入地址访问页面而造成的session中没有用户信息的情况,如果在每个Servlet或JSP前面都 要判断session中是否有相应属性,会有很多的代码重复,用过滤器可以很好地解决这个问题,如果不含登录信息,即转向到用户登录页面。

    复制代码
    package com.mengdd.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class LoginFilter implements Filter {
    
        @Override
        public void destroy() {
    
            // 由Web容器调用
            // 在这里进行资源释放
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            System.out.println("doFilter invoked!");
    
            HttpServletRequest req = (HttpServletRequest) request;
            HttpSession session = req.getSession();// 获取请求的session,如果没有,会创建一个新的session
    
            // 对不需要进行过滤的请求进行事先筛选操作
            String requestURI = req.getRequestURI();
            if (requestURI.endsWith("login.jsp")
                    || requestURI.endsWith("LoginServlet")) {
                chain.doFilter(request, response);
                return;
            }
    
            if (null == session.getAttribute("username")) {
    
                // session中没有用户名属性,说明是新的session,之前没有登录
                // 用过滤器完成了整个Web应用中未登录情况的处理
                ((HttpServletResponse) response).sendRedirect("login.jsp");
    
                // 这里注意,由于本filter配置的<url-pattern>/*</url-pattern>是针对所有地址的
                // 所以请求发送到login.jsp页面也会需要先经过此过滤器,造成重定向的递归重复调用
                // 所以需要对请求的URI进行判断
            }
            else {
                // 按照过滤链继续往下走
                chain.doFilter(request, response);
            }
    
        }
    
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            System.out.println("Filter init");
            // 过滤器是非常特殊的一个Servlet,它会在容器启动的时候得到初始化
            // 过滤器的启动失败会导致Web应用启动失败
    
        }
    
    }
    复制代码

      过滤器的配置和Servlet的配置相似,只不过URL配置的是要过滤请求的URL:

    复制代码
        <!-- filter一般配置在所有的Servlet上面 -->
        <filter>
            <filter-name>LoginFilter</filter-name>
            <filter-class>com.mengdd.filter.LoginFilter</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>LoginFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <!-- /*表示所有地址,即所有请求都会被送到这个过滤器 -->
    复制代码

      可以做很多练习例子,比如可以创建一个NoteFilter过滤器,它可以拒绝列在黑名单上的客户访问留言簿。(黑名单通过过滤器参数设置)。  

      也可以利用Filter进行一些关键词修改替换的工作。

     

    串联过滤器的例子

      几点说明:

      1.串联过滤器的顺序是按照在web.xml中的配置顺序为准的。

    复制代码
        <filter>
            <filter-name>MyFilter1</filter-name>
            <filter-class>com.mengdd.filter.MyFilter1</filter-class>
            <init-param>
                <param-name>hello</param-name>
                <param-value>world</param-value>
            </init-param>
            <init-param>
                <param-name>name</param-name>
                <param-value>zhang</param-value>
            </init-param>
        </filter>
        <filter>
            <filter-name>MyFilter2</filter-name>
            <filter-class>com.mengdd.filter.MyFilter2</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>MyFilter1</filter-name>
            <url-pattern>/InfoServlet</url-pattern>
        </filter-mapping>
        <filter-mapping>
            <filter-name>MyFilter2</filter-name>
            <url-pattern>/InfoServlet</url-pattern>
        </filter-mapping>
    复制代码

      2.在Servlet过滤器中能访问application范围内的共享数 据:先调用FilterConfig的getServletContext()方法获得ServletContext,再调用 ServletContext的getAttribute()方法来获得application范围内的共享数据。

    复制代码
    package com.mengdd.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter1 implements Filter {
    
        @Override
        public void destroy() {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
    
            System.out.println("MyFilter1 --> doFilter invoked!");
            System.out.println("MyFilter1 --> before chain.doFilter()");
            chain.doFilter(request, response);
            System.out.println("MyFilter1 --> after chain.doFilter()");
    
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
            String paramValue1 = filterConfig.getInitParameter("hello");
            String paramValue2 = filterConfig.getInitParameter("name");
    
            ServletContext context = filterConfig.getServletContext();
        }
    
    }
    复制代码
    复制代码
    package com.mengdd.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter2 implements Filter{
    
        @Override
        public void destroy() {
            
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            
            System.out.println("MyFilter2 --> doFilter invoked!");
            System.out.println("MyFilter2 --> before chain.doFilter()");
            chain.doFilter(request, response);
            System.out.println("MyFilter2 --> after chain.doFilter()"); 
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            
        }
    
    }
    复制代码

    参考资料

      圣思园张龙老师Java Web视频教程。

  • 相关阅读:
    在C#代码中应用Log4Net(二)典型的使用方式
    在C#代码中应用Log4Net(一)简单使用Log4Net
    Windows Azure Active Directory (2) Windows Azure AD基础
    Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)
    Windows Azure Active Directory (1) 前言
    Azure China (6) SAP 应用在华登陆 Windows Azure 公有云
    Microsoft Azure News(3) Azure新的基本实例上线 (Basic Virtual Machine)
    Microsoft Azure News(2) 在Microsoft Azure上运行SAP应用程序
    Microsoft Azure News(1) 新的数据中心Japan East, Japan West and Brazil South
    Windows Azure HandBook (2) Azure China提供的服务
  • 原文地址:https://www.cnblogs.com/liu-Gray/p/4897284.html
Copyright © 2011-2022 走看看