社会主义接班人 阅读(45) 评论(0)

对于Struts中的标签这里就不一一列举了,标签也比较简单,所以就跳过,会用就好了,今天主要说下拦截器。拦截器interceptor类似于Filter,在执行Action方法前后执行,拦截器是一种AOP面向切片编程思想的编程方式。提供了一种机制使开发者能把相对独立的代码抽象出来,配置到Action前后执行。Filter中有Filter链在拦截器中有拦截栈,在Action前后被一次执行。Struts2内置了许多现成的拦截器,Struts2的某些功能如数据转换、数据校验等也是基于拦截器实现的。这些拦截器配置在struts-default.xml中,如果需要这些功能直接使用即可。下面举几个常用的拦截器的列子。

<interceptors>
            <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
            <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
            <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
            <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
            <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/>
            <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
            <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
            <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
            <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
            <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
            <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
            <interceptor name="i18n" class="org.apache.struts2.interceptor.I18nInterceptor"/>
            <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
            <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
            <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
            <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
            <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
            <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
            <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
            <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
            <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
            <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
            <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
            <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
            <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
            <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
            <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
            <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
            <interceptor name="datetime" class="org.apache.struts2.interceptor.DateTextFieldInterceptor" />
            <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
            <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
            <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
            <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />

            <!-- Basic stack -->
            <interceptor-stack name="basicStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
            </interceptor-stack>

            <!-- Sample validation and workflow stack -->
            <interceptor-stack name="validationWorkflowStack">
                <interceptor-ref name="basicStack"/>
                <interceptor-ref name="validation"/>
                <interceptor-ref name="workflow"/>
            </interceptor-stack>

            <!-- Sample file upload stack -->
            <interceptor-stack name="fileUploadStack">
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="basicStack"/>
            </interceptor-stack>

            <!-- Sample model-driven stack  -->
            <interceptor-stack name="modelDrivenStack">
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="basicStack"/>
            </interceptor-stack>

            <!-- Sample action chaining stack -->
            <interceptor-stack name="chainStack">
                <interceptor-ref name="chain"/>
                <interceptor-ref name="basicStack"/>
            </interceptor-stack>

            <!-- Sample i18n stack -->
            <interceptor-stack name="i18nStack">
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="basicStack"/>
            </interceptor-stack>

            <!-- An example of the paramsPrepareParams trick. This stack
                 is exactly the same as the defaultStack, except that it
                 includes one extra interceptor before the prepare interceptor:
                 the params interceptor.

                 This is useful for when you wish to apply parameters directly
                 to an object that you wish to load externally (such as a DAO
                 or database or service layer), but can't load that object
                 until at least the ID parameter has been loaded. By loading
                 the parameters twice, you can retrieve the object in the
                 prepare() method, allowing the second params interceptor to
                 apply the values on the object. -->
            <interceptor-stack name="paramsPrepareParamsStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
            </interceptor-stack>

            <!-- A complete stack with all the common interceptors in place.
                 Generally, this stack should be the one you use, though it
                 may do more than you need. Also, the ordering can be
                 switched around (ex: if you wish to have your servlet-related
                 objects applied before prepare() is called, you'd need to move
                 servletConfig interceptor up.

                 This stack also excludes from the normal validation and workflow
                 the method names input, back, and cancel. These typically are
                 associated with requests that should not be validated.
                 -->
            <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="datetime"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="debugging"/>
            </interceptor-stack>

            <!-- The completeStack is here for backwards compatibility for
                 applications that still refer to the defaultStack by the
                 old name -->
            <interceptor-stack name="completeStack">
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>

            <!-- Sample execute and wait stack.
                 Note: execAndWait should always be the *last* interceptor. -->
            <interceptor-stack name="executeAndWaitStack">
                <interceptor-ref name="execAndWait">
                    <param name="excludeMethods">input,back,cancel</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack"/>
                <interceptor-ref name="execAndWait">
                    <param name="excludeMethods">input,back,cancel</param>
                </interceptor-ref>
            </interceptor-stack>

       </interceptors>

        <default-interceptor-ref name="defaultStack"/>
View Code

拦截器

名字

说明

Alias Interceptor

alias

在不同请求之间将请求参数在不同名字件转换,请求内容不变

Chaining Interceptor

chain

让前一个Action的属性可以被后一个Action访问,现在和chain类型的result<result type=”chain”>)结合使用。

Checkbox Interceptor

checkbox

添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox

Cookies Interceptor

cookies

使用配置的name,value来是指cookies

Conversion Error Interceptor

conversionError

将错误从ActionContext中添加到Action的属性字段中。

Create Session Interceptor

createSession

自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。

Debugging Interceptor

debugging

提供不同的调试用的页面来展现内部的数据状况。

Execute and Wait Interceptor

execAndWait

在后台执行Action,同时将用户带到一个中间的等待页面。

Exception Interceptor

exception

将异常定位到一个画面

File Upload Interceptor

fileUpload

提供文件上传功能

I18n Interceptor

i18n

记录用户选择的locale

Logger Interceptor

logger

输出Action的名字

Message Store Interceptor

store

存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。

Model Driven Interceptor

model-driven

如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。

Scoped Model Driven

scoped-model-driven

如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用ActionsetModel方法将其放入Action内部。

Parameters Interceptor

params

将请求中的参数设置到Action中去。

Prepare Interceptor

prepare

如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。

Scope Interceptor

scope

Action状态存入sessionapplication的简单方法。

Servlet Config Interceptor

servletConfig

提供访问HttpServletRequestHttpServletResponse的方法,以Map的方式访问。

Static Parameters Interceptor

staticParams

struts.xml文件中将<action>中的<param>中的内容设置到对应的Action中。

Roles Interceptor

roles

确定用户是否具有JAAS指定的Role,否则不予执行。

Timer Interceptor

timer

输出Action执行的时间

Token Interceptor

token

通过Token来避免双击

Token Session Interceptor

tokenSession

Token Interceptor一样,不过双击的时候把请求的数据存储在Session

Validation Interceptor

validation

使用action-validation.xml文件中定义的内容校验提交的数据。

Workflow Interceptor

workflow

调用Actionvalidate方法,一旦有错误返回,重新定位到INPUT画面

Parameter Filter Interceptor

N/A

从参数列表中删除不必要的参数

Profiling Interceptor

profiling

通过参数激活profile

一、Token防重复提交拦截器

token拦截器用于保证表单只被提交一次,如果再次提交该表单,拦截器会拦截请求,防止提交重复数据。它的原理是显示表单的时候在session中对该表单做一个标记,该标记只能使用一次,使用过后就失效,从而保证表单最多只提交一次数据。重复提交数据会因为标记已失效而提交失败。首先定义Action。这里定义了一个TokenAction。

package com.cyw.test;

import java.util.ArrayList;
import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

public class TokenAction extends ActionSupport {

    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String execute() throws Exception {
    
        return "success";
    }
}
View Code

2.表单设置

这里主要是在表单中增加 <struts:token></struts:token>标签。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="struts" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>注册页面</title>
</head>
<body>
<struts:fielderror></struts:fielderror>
    <struts:form action="token" method="post">  
    <struts:token></struts:token>
    <struts:textfield name="name" label="用户名"></struts:textfield>
    <br/>  
    <struts:submit value="注册"></struts:submit>   
    </struts:form>   
</body>
</html>
View Code

3.拦截器配置

在struts.xml中增加配置,配置token拦截器。Action中必须配置一个invalid.token的result页面。如果重复提交会跳转到该页面中。

        <action name="token"  class="com.cyw.test.TokenAction">
            <interceptor-ref name="token"></interceptor-ref>
            <interceptor-ref name="basicStack"></interceptor-ref>
            <result name="success">/success.jsp</result>
            <result name="input">/register.jsp</result>    
            <result name="invalid.token">/tokenInvalid.jsp</result>    
        </action>

4.结果

首先进入表单页面,提交表单

首次提交会提交成功,提交完成之后刷新页面此时会跳转到重复页面。

二、自定义拦截器

自定义拦截器一般继承抽象类AbstractInterceptor,该抽象类有3个方法。destroy()、init()、intercept(ActionInvocation arg0),最主要的是intercept(ActionInvocation arg0)方法。

Init方法在拦截器类被创建之后,在对Action镜像拦截之前调用,相当于一个post-constructor方法,使用这个方法可以给拦截器类做必要的初始话操作。

Destroy方法在拦截器被垃圾回收之前调用,用来回收init方法初始化的资源。

Intercept是拦截器的主要拦截方法,如果需要调用后续的Action或者拦截器,只需要在该方法中调用invocation.invoke()方法即可,在该方法调用的前后可以插入Action调用前后拦截器需要做的方法。如果不需要调用后续的方法,则返回一个String类型的对象即可。

下面的列子是对Action进行拦截判断是否有session,如果有则判断登录成功,没有则未登录。首先创建拦截器。

package com.cyw.test;

import java.util.Map;

import javax.servlet.http.*;

import org.apache.struts2.ServletActionContext;

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

public class MyInterceptor extends   AbstractInterceptor{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Override
    public void destroy() {
        System.out.println("MyInterceptor Destroy");
        super.destroy();
    }

    @Override
    public void init() {
        System.out.println("MyInterceptor init");
        super.init();
    }

    @Override
    public String intercept(ActionInvocation arg0) throws Exception {
        
        Map<String,Object> maps=arg0.getInvocationContext().getSession();
        String sessionName=(String)maps.get("userName");
        if(sessionName==null)
        {
            return "notlogin";
        }
        else
        {
            return arg0.invoke();
        }
        
    }

}
View Code

然后创建了2个Action,一个登录一个登录后的。

package com.cyw.test;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {

    @Override
    public String execute() throws Exception {
        return "regist";
    }

}
View Code
package com.cyw.test;

import com.opensymphony.xwork2.ActionSupport;

public class IndexAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        return "success";
    }
}
View Code

在struts2.xml中注入拦截器。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="default" namespace="" extends="struts-default">
        <interceptors>
        <!-- login拦截器 -->
        <interceptor name="loginInterceptor" class="com.cyw.test.MyInterceptor"/>
        <interceptor-stack name="myInterceptorStack">
          <interceptor-ref name="basicStack"></interceptor-ref>
          <interceptor-ref name="defaultStack"></interceptor-ref>
          <interceptor-ref name="loginInterceptor"/>
        </interceptor-stack>
        </interceptors>
        <global-results>
            <result name="notlogin">/notlogin.jsp</result>
        </global-results>
        <action name="login"  class="com.cyw.test.LoginAction">
            <result name="regist">/register.jsp</result>
        </action>
        <action name="index"  class="com.cyw.test.IndexAction">
         <interceptor-ref name="myInterceptorStack"></interceptor-ref>
            <result name="success">/success.jsp</result>
        </action>
    </package>
</struts>

上面的xml中定义了一个拦截器栈,然后再Action中引用它,也可以在每个Action中一个一个的引入拦截器,同时可以使用<param>来对拦截器进行初始化参数。

实验结果:

由于对indexAction进行了拦截,所以判断session是否存在不存在跳转到notlogin.jsp页面。

三、拦截器与过滤器的比较

1、filter基于filter接口中的doFilter回调函数,interceptor则基于Java本身的反射机制;   
2、filter是依赖于servlet容器的,没有servlet容器就无法回调doFilter方法,而interceptor与servlet无关;   
3、filter的过滤范围比interceptor大,filter除了过滤请求外通过通配符可以保护页面、图片、文件等,而interceptor只能过滤请求,只对action起作用,在action之前开始,在action完成后结束(如被拦截,不执行action);   
4、filter的过滤一般在加载的时候在init方法声明,而interceptor可以通过在xml声明是guest请求还是user请求来辨别是否过滤;   
5、interceptor可以访问action上下文、值栈里的对象,而filter不能;   
6、在action的生命周期中,拦截器可以被多次调用,而过滤器只能在容器初始化时被调用一次。