zoukankan      html  css  js  c++  java
  • 【学习】Filter

    Filter 介绍:

      它主要用于对用户请求进行预处理,也可以对HttpServletResponse 进行后处理。使用Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给Servlet 进行处理并生成响应,最后Filter 再对服务器响应进行后处理。

      Filter 用处:

      > 在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest 。 

      > 根据需要检查 HttpServletRequest ,也可以修改HttpServletRequest 头和数据。

      > 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。 

      > 根据需要检查 HttpServletResponse ,也可以修改HttpServletResponse头和数据。

      

      Filter 种类:

      > 用户授权的 Filter 

      > 日志 Filter 

      > 负责解码的 Filter 

      > Filter 可负责拦截多个请求或响应 

    创建一个Filter:

      1、创建Filter类

      必须实现javax.servlet.Filter接口,在该接口中定义了如下方法:

      1、void init(FilerConfig config):用于完成Filter的初始化。

      2、void destroy():用于Filter撤销前,完成某些资源的回收。

      3、void doFilter(ServletRequest request,ServletResponse response, FilterChain chain):实现过滤功能,该方法就是对每一个请求及功能增加的额外处理。

      

    package jbelial.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;
    import javax.servlet.http.HttpServletRequest;
    
    public class LogFilter implements Filter {
        
        //FilterConfig用于访问Filter的配置信息
        private FilterConfig config ;
        // 实现销毁
        public void destroy() {
            // TODO Auto-generated method stub
            this.config = null ; 
        }
    
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            // TODO Auto-generated method stub
            //-----------------对用户请求执行预处理-----------------------
            ServletContext context = this.config.getServletContext() ; 
            long before = System.currentTimeMillis() ; 
            System.out.println("开始过滤。。。。");
            //将请求转换成HttpServletRequest 请求。
            HttpServletRequest hrequest = (HttpServletRequest)request ; 
            System.out.println("Filter 已经截获到用户的请求的地址:" +
                    hrequest.getServletPath());
            // Filter 只是链式处理,请求依然放行到目的地址
            chain.doFilter(request, response) ; 
            //---------------对服务器响应执行后处理-----------------------
            long after = System.currentTimeMillis() ; 
            System.out.println("过滤结束。。。。");
            System.out.println("请求被定位到"+hrequest.getRequestURI()+
                    " 所花时间:"+(after - before));
            
        }
        // 实现初始化
        public void init(FilterConfig config) throws ServletException {
            // TODO Auto-generated method stub
            this.config = config ; 
        }
    
    }

      实现该方法就可以实现对用户的请求进行预处理,也可以对服务器响应进行后处理——分界线为是否调用了chain.doFilter(request.response) 。

       上面的请求Filter 仅在日志中记录请求的URL,对所有的请求都执行 chain.doFilter(request,response) 方法,当Filter 对请求过滤后依然将请求发送到目的地址。如果需要检查权限,可以在Filter中根据用户请求 HttpSession,判断用户权限是否足够。如果权限不够,直接调用重定向即可。

      2、配置Filter

       > 配置 Filter 名。

       > 配置 Filter 拦截 URL 模式。

         1、通过Annotation 进行配置

          在Filter 类 中添加:

          @WebFilter(filterName= "log",urlPatterns = {"/*"})

          下面附上@WebFilter 支持的常用属性表

    属性 是否必须 说明
    asyncSupported F 指定该Filter是否支持异步操作模式。
    dispatcherTypes F

    指定该Filter仅对dispatchar模式的请求进行过滤。该属性支持ASYNC、ERROR、FORWARD、

    INCLUDE、REQUST这5个值的任意组合。默认为同时过滤5种模式的请求。

    displayName  F 指定该Filter的显示名  
    filterName      指定该Filter的名字
    initParams F 用于为该Filter配置参数
    servletNames F 该属性值可指定多个Servlet的名称,用于指定该Filter仅对这几个Servlet执行过滤
    urlPatterns F 指定该Filter所拦截的URL

         2、在web.xml 文件中配置:

     <filter>
         <filter-name>log</filter-name>
         <filter-class>jbelial.Filter.LogFilter</filter-class>
     </filter>
     <filter-mapping>
         <filter-name>log</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>

      

       Filter 的 doFilter()方法里面多了一个FilterChain 的参数,通过该参数可以控制是否放行用户请求。在实际项目中, Filter 里 doFilter() 方法里的代码就是从多个Servlet 的service() 方法里面抽取的通用代码,通过使用Filter 可以实现更好的代码复用。

       如下面的代码: 

    @WebFilter(filterName="authority"
        , urlPatterns={"/*"}
        , initParams={
            @WebInitParam(name="encoding", value="GBK"),
            @WebInitParam(name="loginPage", value="/login.jsp"),
            @WebInitParam(name="proLogin", value="/proLogin.jsp")})
    public class AuthorityFilter implements Filter 
    {
        //FilterConfig可用于访问Filter的配置信息
        private FilterConfig config;
        //实现初始化方法
        public void init(FilterConfig config)
        {
            this.config = config; 
        }
        //实现销毁方法
        public void destroy()
        {
            this.config = null; 
        }
        //执行过滤的核心方法
        public void doFilter(ServletRequest request,
            ServletResponse response, FilterChain chain)
            throws IOException,ServletException
        {
            //获取该Filter的配置参数
            String encoding = config.getInitParameter("encoding");
            String loginPage = config.getInitParameter("loginPage");
            String proLogin = config.getInitParameter("proLogin");
            //设置request编码用的字符集
            request.setCharacterEncoding(encoding);
            HttpServletRequest requ = (HttpServletRequest)request;
            HttpSession session = requ.getSession(true);
            //获取客户请求的页面
            String requestPath = requ.getServletPath();
            //如果session范围的user为null,即表明没有登录
            //且用户请求的既不是登录页面,也不是处理登录的页面
            if( session.getAttribute("user") == null
                && !requestPath.endsWith(loginPage)
                && !requestPath.endsWith(proLogin))
            {
                //forward到登录页面
                request.setAttribute("tip" , "您还没有登录");
                request.getRequestDispatcher(loginPage)
                    .forward(request, response);
            }
            //"放行"请求
            else
            {
                chain.doFilter(request, response);
            }
        } 
    }

      如果用户没有登录,那么只能访问/login.jsp和/proLogin.jsp页面。  

      在 web.xml文件中配置该Filter: 

     <filter>
         <filter-name>authority</filter-name>
         <filter-class>jbelial.Filter.Authority</filter-class>
         <init-param>
             <param-name>encoding</param-name>
             <param-value>GBK</param-value>
         </init-param>
              <init-param>
             <param-name>loginPage</param-name>
             <param-value>/login.jsp</param-value>
         </init-param>
              <init-param>
             <param-name>proLogin</param-name>
             <param-value>/proLogin.jsp</param-value>
         </init-param>
     </filter>
     <filter-mapping>
         <filter-name>authority</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
    </web-app>

       

      

  • 相关阅读:
    第二十一天作业
    第二十天:继承
    第二十天作业
    第十六天
    第十九天作业
    day53
    day52
    day51
    day50
    day44
  • 原文地址:https://www.cnblogs.com/jbelial/p/2582638.html
Copyright © 2011-2022 走看看