zoukankan      html  css  js  c++  java
  • J2EE中的过滤器和拦截器

    过滤器和拦截器的相似之处就是拦截请求,做一些预处理或者后处理。

    而过滤器和拦截器的区别在于过滤器是相对HTTP请求而言的,而拦截器是相对Action中的方法的。

    过滤器:访问web服务器的时候,对一个请求,我们可以设置请求编码,设置请求参数,设置其是否能访问某个页面,设置相应编码等。

    拦截器:访问web服务器的时候,在你调用的方法前做一个拦截,加上我想要的任意操作。比喻记录操作日志,加上某个特定业务(AOP)。

    1、过滤器

    过滤器需要做两部分的工作:Filter过滤类、web.xml配置

    Filter类部分:

    package com.chanshuyi.servlet;
    
    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.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * Test Servlet Filter
     * @author chenyr
     */
    //@WebFilter(filterName = "myfilter", urlPatterns = {"/*.*"})
    //你可以通过这段注释来声明这个Filter,从而不用在web.xml文件中配置,但你用的Servlet版本必须是3.0以上
    public class MyServletFilter implements Filter {
        
        /** Filter Config Info **/
        private FilterConfig config;
        
        public void init(FilterConfig config) throws ServletException {
            this.config = config;
        }
    
        public void destroy() {
            this.config = null;
        }
    
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            //-------- Preprocess --------
            long before =  System.currentTimeMillis();
            System.out.println("Begin filtering...");
            HttpServletRequest hrequest = (HttpServletRequest)request;
            System.out.println("Intercept the user request address:" + hrequest.getServletPath());
            
            //-------- Do the Servlet --------
            chain.doFilter(request, response);
            
            //-------- afterprocess --------
            long after = System.currentTimeMillis();
            System.out.println("End filtering...");
            System.out.println("Redirect To:" + hrequest.getRequestURI() + "  Time Cost:" + (after - before));
        }
    }

    web.xml部分:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      <filter>
              <filter-name>myfilter</filter-name>
              <filter-class>com.chanshuyi.servlet.MyServletFilter</filter-class>
      </filter>
      
      <filter-mapping>
              <filter-name>myfilter</filter-name>
              <url-pattern>/*</url-pattern>
      </filter-mapping>
    </web-app>

    2、拦截器

    Struts的拦截器本质上还是通过过滤器来实现的。

    拦截器实现需要做两部分的工作:Interceptor过滤类、struts.xml配置

    拦截器类:

    package com.chanshuyi.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    
    @SuppressWarnings("serial")
    public class MyInterceptor extends AbstractInterceptor {
        
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            
            //get the target action
            //LoginAction action = (LoginAction)invocation.getAction();
            System.out.println(name + "Interceptor begin to work ...");
            long startMill = System.currentTimeMillis();
            
            //execute the target action method
            String result = invocation.invoke();
            
            long endMill = System.currentTimeMillis();
            System.out.println(name + "Interceptor ends, time cost:" + (endMill - startMill));
            System.out.println("result is : " + result);
            
            return result;
        }
    }

    你可以通过实现Interceptor接口来实现拦截器。但是Java为我们提供了AbstractInterceptor类,通过实现AbstractInterceptor类可以让我们减少编码(因为AbstractInterceptor已经帮我们实现了init()/destory()方法,我们只需再实现interceptor方法即可)

    struts.xml配置部分:

    <struts>
        <package name="default" namespace="/" extends="struts-default">
            <interceptors>
                <interceptor name="loginInter" class="com.chanshuyi.interceptor.MyInterceptor">
                    <param name="name">[默认的拦截器名字]</param>
                </interceptor>
            </interceptors>
        
            <action name="login" class="com.chanshuyi.action.LoginAction" method="execute">
                <result name="success">/hello.jsp</result>
                <result name="login">/hello.jsp</result>
                
                <interceptor-ref name="defaultStack"/>
                <interceptor-ref name="loginInter">
                    <param name="name">[修改后的拦截器名字]</param>
                </interceptor-ref>
            </action>
        </package>
    </struts>

    MARK CHENYR (这里需要补充)

    3、只拦截部分Action部分方法的拦截器

    通过继承AbstractInterceptor的子类:MethodFilterInterceptor类,可以实现对Action中方法级的过滤。

    它与继承AbstractInterceptor实现过滤在代码上的不同在于:

    1).需要继承的是MethodFilterInterceptor类

    2).需要实现的是doInterceptor方法,而不是interceptor方法

    3).可以通过setExcludeMethod/setIncludeMethod方法或配置文件的方式实现方法的过滤

    拦截器部分代码(将intercept方法换成doIntercept即可):

    @SuppressWarnings("serial")
    public class CopyOfMyInterceptor extends MethodFilterInterceptor {
        
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String doIntercept(ActionInvocation invocation) throws Exception {
            
            //get the target action
            //LoginAction action = (LoginAction)invocation.getAction();
            System.out.println(name + "Interceptor begin to work ...");
            long startMill = System.currentTimeMillis();
    
         //直接调用setExcludeMethod/setIncludeMethod方法给excludeMethod/includeMethod属性赋值。这与用配置文件赋值是一样的
            
            //execute the target action method
            String result = invocation.invoke();
            
            long endMill = System.currentTimeMillis();
            System.out.println(name + "Interceptor ends, time cost:" + (endMill - startMill));
            System.out.println("result is : " + result);
            
            return result;
        }
    }

    通过配置文件实现对方法的过滤:

    <struts>
        <package name="default" namespace="/" extends="struts-default">
              <interceptors>
                <interceptor name="loginInter" class="com.chanshuyi.interceptor.MyInterceptor">
                    <param name="name">[默认的拦截器名字]</param>
                </interceptor>
            </interceptors>
    
            <action name="login" class="com.chanshuyi.action.LoginAction" method="execute">
                    <result name="success">/hello.jsp</result>
                    <result name="login">/hello.jsp</result>
                
                    <interceptor-ref name="defaultStack"/>
                    <interceptor-ref name="loginInter">
                        <param name="name">[修改后的拦截器名字]</param>
                        <!-- 多个方法用英文逗号隔开 -->
                        <param name="excludeMethods">execute</param>                
           <!-- 通过配置文件赋值,本质上是给继承了MethodFilterInterceptor的CopyOfMyInterceptor类的excludeMethods属性复制。所以你也可以不在这里复制,而直接在CopyOfMyInterceptor类中用setExcludedMethod/setIncludeMethod赋值 -->
                    </interceptor-ref>
         </action>
      </package>
    </struts>
    

    4、关于过滤器和拦截器的执行顺序

    在一般情况下,过滤器和拦截器都是先配置先执行的。

    下面用过滤器的一个例子说明:

    web.xml部分代码:

    <!-- 第一个过滤器 -->
    <filter>
        <filter-name>filter1</filter-name>
        <filter-class>filter.Filter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 第二个过滤器 -->
    <filter>
        <filter-name>filter2</filter-name>
        <filter-class>filter.Filter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    Filter1类的关键代码:

    public void doFilter(ServletRequest request, ServletResponse response,
    		  FilterChain chain) throws IOException, ServletException {
    		 try {
    			 System.out.println("filter1");
    			  chain.doFilter(request, response);
    			  System.out.println("filter1   go back");
    		 } catch (Exception e) {
    		  e.printStackTrace();
    		}
    }
    

    Filter2类与Filter1类一样,只是输出内容变成了“filter2”以及“filter2   go back”。

    运行结果为:

    filter1
    filter2
    filter2   go back
    filter1  go back
    

    可以看出,过滤器和拦截器的执行顺序是先定义先执行,并且执行是类似于堆栈的先进后出的执行顺序。  

    5、关于过滤器和拦截器的思考

    在说拦截器和过滤器之前,先说这两者的几点区别:

    1.过滤器可以对所有HTTP请求进行拦截,但拦截器只能对Action请求进行拦截

    2.过滤器是Servlet中的概念,拦截器是Struts中的概念

    在Struts还没有出来的时候,拦截器这个概念是不存在的。在Struts出来之后,拦截器也来了。拦截器是通过Servlet来实现的,拦截器对过滤器进行了一层封装,使Struts框架更加好用。

    在使用了Struts框架的项目中,更多人直接使用拦截器,过滤器的概念就被弱化了。这是我的一些理解。因此在使用了Struts的项目中,你可以直接使用拦截器对所有Action请求进行拦截,对他们进行权限控制。

    但拦截器不能拦截直接访问的页面,那这些页面如何保障权限的控制呢?答案是将页面房在WEB-INF目录下(WEB-INF目录下的文件不能通过客户端直接访问),只将少数必要的文件放在Web-Root目录,这样就可以实现这些页面的安全。

    总的来说,如果你的项目使用了Struts,那么你可以直接用Struts的拦截器实现权限控制等。

    但如果你的项目是用纯Servlet写的,那么你只能用过滤器实现了。

    ===================== 相信美好的事情终会发生 ====================

    struts.xml文件中拦截器配置集锦

    <!-- 配置拦截器 -->
    <interceptor name="interceptor1" class="classRoute"/>
    <interceptor name="interceptor1" class="classRoute">
    <param name="paraName">Param Value</param>
    </interceptor>
    <!-- 拦截器栈 -->
    <interceptor-stack name="stackName">
    <interceptor name="interceptor1" class="classRoute"/>
    <interceptor-ref name="interceptorName">
    <param name="paraName">Param Value</param>
    </interceptor-ref>
    </interceptor-stack>
    <!-- 使用拦截器 -->
    <action name="" class="" method="">
    <result>...</result>
    <!-- 一定要加上Struts的默认拦截器 -->
    <interceptor-ref name="defaultStack"/>
    <!-- 使用自己的拦截器 -->
    <interceptor-ref name="myInterceptor"/>
    </action>
    <!-- 设置默认拦截器 -->
    <package>
    <interceptors>...</interceptors>
    <!-- 设置默认拦截器 -->
    <default-interceptor-ref name=""></default-interceptor-ref>
    <action>...</action>
    </package>
    

      

      

  • 相关阅读:
    设计模式——迭代器模式
    FTP服务:FileZilla的配置和使用
    FTP服务:使用FileZilla搭建FTP服务
    FTP服务:ISS搭建服务
    javaweb项目使用RSA算法
    我在博客园的第一篇博客
    杰表打印跟乱码修改
    jsp页面角色判断
    test : 摘自 https://www.cnblogs.com/yyman001/p/3366764.html
    mybatis中sql查询不到数据单独运行sql可以获取数据
  • 原文地址:https://www.cnblogs.com/chanshuyi/p/3924186.html
Copyright © 2011-2022 走看看