拦截器基础

Posted 专注改变人生。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拦截器基础相关的知识,希望对你有一定的参考价值。

 

二、自定义拦截器应用

  2.1  第一个自定义拦截器

  • index.jsp
<body>
    <a href="<%=path%>/Interceptor/InterceptorAction">此页面跳转的action会被自定义拦截器拦截</a>
</body>
  • struts.xml
   <package name="default" namespace="/Interceptor" extends="struts-default">
                    <!-- 定义拦截器 -->
        <interceptors>
            <interceptor name="interceptorTest" class="interceptor.InterceptorTest"></interceptor>
        </interceptors>
        
        <action name="InterceptorAction" class="action.InterceptorAction">
            <result name="re">/index_2.jsp</result>
                <!-- 引用拦截器 -->
            <interceptor-ref name="interceptorTest"></interceptor-ref>
        </action>
    </package>
  • InterceptorTest.java(编写拦截器的代码)
package interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

/**
 * 自定义的拦截器
 * @author Administrator
 *
 */

public class InterceptorTest implements Interceptor {

    public void destroy() {
    }

    public void init() {
    }

    public String intercept(ActionInvocation actionInterceptor) throws Exception {
    
        System.out.println("我是第一次自定义拦截器");
        /*
         * 让Action的方法执行,并返回action的结果。
         * ActionInvocation。invoke()方法会调用下一个拦截器 或 执行下一个Action,如果是执行actino就返回action的result值。
         * 而ActionInvocation。getResultCode()只获得action的result返回值并不执行action。
         */
        String next=actionInterceptor.invoke();
        return null;
    }

}
  • InterceptorAction.java(被拦截的action)
package action;

public class InterceptorAction {
    public String execute(){
        
        System.out.println("我是action");
        return "re";
    }
}
  • index_2.jsp(action执行成功后跳转的页面)
<body>
    我是跳转后的页面
</body>

 

结果:

查看后台可知,拦截器中的方法比action的方法先执行,说明拦截成功。

 

 

  2.2  拦截器栈:如果拦截器很多的话,可以把这些拦截器放到拦截器栈里,在action类中引用拦截器栈,拦截器栈中的每个拦截器会按顺序对action进行拦截。

如上例,再加一个拦截器。

  • struts.xml
  <package name="default" namespace="/Interceptor" extends="struts-default">
                    <!-- 定义拦截器 -->
        <interceptors>
            <interceptor name="interceptorTest" class="interceptor.InterceptorTest"></interceptor>
            <interceptor name="interceptor_two" class="interceptor.Interceptor_two"></interceptor>
                    <!-- 定义拦截器栈,引入拦截器 -->
            <interceptor-stack name="mystack">
            <interceptor-ref name="interceptor_two"></interceptor-ref>
                <interceptor-ref name="interceptorTest"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        
        
        <action name="InterceptorAction" class="action.InterceptorAction">
            <result name="re">/index_2.jsp</result>
                <!-- 引用拦截器栈-->
            <interceptor-ref name="mystack"></interceptor-ref>
        </action>
    </package>
  • 解析:当访问url为"/工程名/Interceptor/InterceptorAction"这个action 的时候,此时这个action里引用了拦截器栈,拦截器栈里有两个拦截器,会按顺序逐一地对action进行拦截

 

2.3  默认拦截器

  •  struts.xml

 

  <package name="default" namespace="/Interceptor" extends="struts-default">
                    <!-- 定义拦截器 -->
        <interceptors>
            <interceptor name="interceptorTest" class="interceptor.InterceptorTest"></interceptor>
            <interceptor name="interceptor_two" class="interceptor.Interceptor_two"></interceptor>
                <!-- 
            设定哪一个拦截器或者拦截器栈为默认的
            1:当Action中没有使用interceptor-ref引用时,默认拦截器将会起作用。如果Action中配置interceptor-ref,那么
              默认的拦截器将不起作用    
            2:将设定default-interceptor-ref为自定义的拦截器后,struts-default.xml中定义的默认拦截器将不起作用。
              所有Struts的功能将不能使用。要将defaultStack拦截器栈引用到自定义到拦截器栈中        
            3:其他的package要使用自定义的拦截器,将package做一个继承即可。    
        -->
            <interceptor-stack name="mystack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="interceptor_two"></interceptor-ref>
                <interceptor-ref name="interceptorTest"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="mystack"></default-interceptor-ref>
        
        <action name="InterceptorAction" class="action.InterceptorAction">
            <result name="re">/index_2.jsp</result>
        </action>
    </package>

           1:当Action中没有使用interceptor-ref引用时,默认拦截器将会起作用。如果Action中配置interceptor-ref,那么
              默认的拦截器将不起作用
            2:将设定default-interceptor-ref为自定义的拦截器后,struts-default.xml中定义的默认拦截器将不起作用。
              所有Struts的功能将不能使用。要将defaultStack拦截器栈引用到自定义到拦截器栈中。 
            3:其他的package要使用自定义的拦截器,将package做一个继承即可。

           4. Struts2在struts-default包中定义了一个默认的拦截器栈引用:defaultStack。因此当我们定义的包继承自struts-default包时也继承了它的默认拦截器引用:defaultStack,当我们不为Action显式的应用拦截器,则defaultStack栈会起作用。

 

 2.4   用自定义拦截器实现登录验证

  •  servlet里用过滤器实现登录验证,而struts2可以用拦截器来实现登录验证,但是在开发中,一般使用过滤器来实现登录验证,因为拦截器只能拦截action。

  •  index.jsp
<body>
        <h2>登录系统</h2>
        <form action="interceptor/main" method="post">

        用户名:<s:textfield name="username"></s:textfield><br/>&nbsp;码:<s:password name="password"></s:password>
        <s:submit value="提交"></s:submit>
        </form>
</body>
  • sturts.xml(如果没有<interceptor-ref name="defaultStack"></interceptor-ref>的话,那么在action中就无法得到表单的值,这个功能是默认拦截器引用:defaultStack的功能之一)
  <package name="default" namespace="/interceptor" extends="struts-default">
        <interceptors >
            <interceptor name="login" class="interceptor.LoginInterceptor"></interceptor>
        </interceptors>
 
           <action name="main" class="action.GoMainAction">
           <interceptor-ref name="defaultStack"></interceptor-ref>
           <interceptor-ref name="login"></interceptor-ref>
               <result name="main">/index_2.jsp</result>
           </action>
    </package>

 

  •  GoMainAction.java
package action;

import javax.servlet.http.HttpSession;

import org.omg.CORBA.Request;

import com.opensymphony.xwork2.ActionSupport;

import actionUtil.BaseAction;

public class GoMainAction extends BaseAction{
    /*
     * 在action中获取表单值的前提是必须在struts.xml中引用默认拦截器引用:defaultStack
     */
    private String username;
    private String password;
    
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }


    public String execute(){

        if((this.username).equals("admin")){
            if((this.password).equals("123")){
                HttpSession session=request.getSession();
                session.setAttribute("login", "ok");
                return "main";
                
            }else{
                System.out.println("密码错误");
                return null;
            }
            
        }else{
            
            System.out.println("用户名错误");
            return null;
        }
    }
}
  • LoginInterceptor.java
package interceptor;

import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.ValueStack;

import action.GoMainAction;

public class LoginInterceptor  implements Interceptor{

    public void destroy() {
    }

    public void init() {
    }

    public String intercept(ActionInvocation actionInvocation) throws Exception {
      
        Object action=actionInvocation.getAction();  //拿到被拦截的action对象
        ActionContext context=actionInvocation.getInvocationContext(); //拿到action的广义值栈。
        HttpServletRequest request=ServletActionContext.getRequest();  //拿到request对象
        HttpServletResponse response = ServletActionContext.getResponse();      //拿到response对象
            
        Map<String,Object> sessionMap=context.getSession();
        
        //    ValueStack valuestack=context.getValueStack();  //拿到action的狭义值栈。
        
        if(action.getClass().equals(GoMainAction.class)){
            //如果是验证登录的action,。则不进行拦截
            actionInvocation.invoke();
            
             return null;
        }else{
    
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        String loginURL = request.getContextPath() + "/index.jsp";
        out.println("<script language=\'javascript\'>");
        out.println("window.alert(\'您还未登录,或者登录已超时,请重新登录\');");
        out.println("window.location.href = \'" + loginURL + "\';");
        out.println("</script>");
        
        return null;
        }
    }

}
  • index_2.jsp
<body>
    登录成功
</body>
  • 用拦截器实现登录验证的问题: 1.  只能拦截action而无法拦截页面,也就是说无法拦截未登录用户访问需要登录的页面。

 

 2.5  利用拦截器实现监听程序运行效率(监听每个方法的运行时间,时间越长代表效率越低)

  •  index.jsp
<body>
        <a href="interceptor/TestAction!one">方法1的运行效率</a>
        <a href="interceptor/TestAction!two">方法2的运行效率</a>
</body>
  • struts.xml
 <package name="default" namespace="/interceptor" extends="struts-default">
    <interceptors>
        <interceptor name="test" class="interceptor.TestInterceptor"></interceptor>    
    </interceptors>
    
        <action name="TestAction" class="action.TestAction">
         <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="test"></interceptor-ref>
        </action>
    </package>
  • TestAction.java
package action;

public class TestAction {
    public String execute(){
        return null;
    }
    /**
     * 要测试的方法1
     * @return
     */
    
    public String one(){
        System.out.println("运行one方法");
    return null;    
    }
    /**
     * 要测试的方法2
     * @return
     */
    public String two(){
        System.out.println("运行two方法");
        try {
            Thread.sleep(6000);  //停留6秒
        } catch (InterruptedException e) {
            
            e.printStackTrace();
        }
        return null;
    }
}
  • TestInterceptor.java(拦截器)
package interceptor;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.ValueStack;

public class TestInterceptor implements Interceptor{

    public void destroy() {
    }

    public void init() {    
    }

    public String intercept(ActionInvocation actionInvocation) throws Exception {
        
        Object obj=actionInvocation.getAction();  //获取正在拦截的对象
        ActionContext actionContext=actionInvocation.getInvocationContext(); //获取被拦截action的上下文对象
        ValueStack valuestack=actionContext.getValueStack();  //获取action的狭义值栈
        
        HttpServletRequest request = ServletActionContext.getRequest(); //获取erquest对象
        StringBuffer requestURL=request.getRequestURL();  //获取超时方法的URL
        
        //让action方法执行,并测试
        long start=System.currentTimeMillis();  //获取方法执行前的时间
        actionInvocation.invoke();  //执行方法
        long end=System.currentTimeMillis();   //获取方法执行后的时间
        
        int  diffSecond = (int) ((end - start) / 1000);  //获取方法总共执行时间差
        if(diffSecond >5){
            System.out.println("requestURI= " + requestURL +",间隔时间= "+diffSecond);  //如果方法执行时间超过5秒就把这个URL打印出来
        }  
        return null;
    }

}

结果:

  • 如结果,这样我们就把那些运行了很久的方法找了出来。

 

以上是关于拦截器基础的主要内容,如果未能解决你的问题,请参考以下文章

[vscode]--HTML代码片段(基础版,reactvuejquery)

ViewPager里面的TextView拦截触摸事件

如何利用redis来进行分布式集群系统的限流设计

AOP框架Dora.Interception 3.0 [3]: 拦截器设计

[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础

servlet,过滤器,监听器,拦截器的区别