盐城疝气哪家医院好:struts2.x中的拦截器

来源:百度文库 编辑:偶看新闻 时间:2024/05/04 06:20:05

拦截器:Interceptor。指在执行某一方法之前或之后做一些东西。与servlet里面的filter过滤器是很类似。拦截器本身就是一个普通的类。

拦截器:就是在调用action的过程中插入自己想加入的逻辑

问题引入:假如有一业务需求

如果用户登录后,就可以访问action中的所有方法;


如果用户没有登录,就不允许访问action中的方法,并且提示"你没有权限执行该是操作"

要自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor接口

一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了。拦截器的拦截行为将会在Action的exceute方法执行之前被执行

在struts.xml文件中定义拦截器,拦截器栈:



       

       

       

       

       

            

            

       


       


        ......


 

3.    使用拦截器
一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了。拦截器的拦截行为将会在Action的exceute方法执行之前被执行。



            /success.jsp

            /error.jsp







           

       


       此处需要注意的是,如果为Action指定了一个拦截器,则系统默认的拦截器栈将会失去作用。为了继续使用默认拦截器,所以上面配置文件中手动引入了默认拦截器。

******************************************************************************************************************************************************************************

拦截器:与过滤器非常相似,都是一个接口,该接口中都有两个相同的方法init(),destory()这两个方法仅被执行一次,主方法不同,它会被执行多次。
假如有这样一个业务:如果用户登录后,则可以访问action中的所有方法;如果用户没有登录,则不允许访问action中的方法,并且提示“你没有权限执行该项操作”
实现:



第1步:
自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor接口。
public Permission implements Interceptor{
    public void destory(){}

    public void init(){}

    public String intercept(ActionInvocation invocation) throws Exception{
        System.out.println("进入拦截器");
        if(session里存在用户){
            String result=invocation.invoke();
        }else{
            return "logon";
        }
    }
   
}
第2步:在struts.xml中配置:

   
       
       
           
           
       

   

  
    /hello.jsp
   
  

因为struts2中,如对文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中
的拦截器实现的,所以,我们定义的拦截器要引用系统默认的defaultStack,这样,应用才可以使用struts2框
架提供的众多功能。
如果希望包下面的所有action都使用自定义的拦截器,可以通过
把拦截器定义为默认拦截器。注意:每个包只能指定一个默认的的拦截器,另外,一旦我们为该包中的某个action显示
地指定了某个拦截器,则默认拦截器不会起作用。

 *****************************************************************************************************************************************************************************

Struts2的基石——拦截器(Interceptor)

Interceptor(以下译为拦截器)是Struts 2的一个强有力的工具,有许多功能(feature)都是构建于它之上,如国际化、转换器,校验等。

什么是拦截器

拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。

在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。

谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

实现原理

Struts2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器,如图1所示。

  图1 拦截器调用序列图

已有的拦截器

Struts2已经为您提供丰富多样的,功能齐全的拦截器实现。大家可以到struts2-all-2.0.1.jar或struts2-core-2.0.1.jar包的struts-default.xml查看关于默认的拦截器与拦截器链的配置。

在本文使用是Struts 2的2.0.1版本。需要下载的朋友请点击以下链接:
http://apache.justdn.org/struts/binaries/struts-2.0.1-all.zip

以下部分就是从struts-default.xml文件摘取的内容:

< interceptor name ="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
< interceptorname ="autowiring"class ="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
< interceptorname ="chain"class ="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
< interceptorname ="conversionError"class ="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
< interceptorname ="createSession"class ="org.apache.struts2.interceptor.CreateSessionInterceptor"/>
< interceptorname ="debugging"class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor"/>
< interceptorname ="external-ref"class ="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
< interceptorname ="execAndWait"class ="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
< interceptorname ="exception"class ="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
< interceptorname ="fileUpload"class ="org.apache.struts2.interceptor.FileUploadInterceptor"/>
< interceptorname ="i18n"class ="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
< interceptorname ="logger"class ="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
< interceptorname ="model-driven"class ="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
< interceptorname ="scoped-model-driven"class ="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
< interceptorname ="params"class ="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
< interceptorname ="prepare"class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
< interceptorname ="static-params"class ="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
< interceptorname ="scope"class ="org.apache.struts2.interceptor.ScopeInterceptor"/>
< interceptorname ="servlet-config"class ="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
< interceptorname ="sessionAutowiring"class ="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
< interceptorname ="timer"class ="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
< interceptorname ="token"class ="org.apache.struts2.interceptor.TokenInterceptor"/>
< interceptorname ="token-session"class ="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
< interceptorname ="validation"class ="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
< interceptorname ="workflow"class ="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
< interceptorname ="store"class ="org.apache.struts2.interceptor.MessageStoreInterceptor"/>
< interceptorname ="checkbox"class ="org.apache.struts2.interceptor.CheckboxInterceptor"/>
< interceptorname ="profiling"class ="org.apache.struts2.interceptor.ProfilingActivationInterceptor"/>

配置和使用拦截器

在struts-default.xml中已经配置了以上的拦截器。如果您想要使用上述拦截器,只需要在应用程序struts.xml文件中通过 “”将struts-default.xml文件包含进来,并继承其中的struts-default包(package),最后在定义 Action时,使用“”引用拦截器或拦截器栈(interceptor stack)。一旦您继承了struts-default包(package),所有Action都会调用拦截器栈 ——defaultStack。当然,在Action配置中加入“”可以覆盖defaultStack。

下面是关于拦截器timer使用的例子。首先,新建Action类tuotrial/TimerInterceptorAction.java,内容如下:

package tutorial;

import com.opensymphony.xwork2.ActionSupport;

public class TimerInterceptorAction extendsActionSupport {
  @Override
   public Stringexecute() {
       try {
           // 模拟耗时的操作
          Thread.sleep( 500);
      } catch (Exception e) {
          e.printStackTrace();
       }
       return SUCCESS;
   }
}

配置Action,名为Timer,配置文件如下:

        "-//Apache Software Foundation//DTD StrutsConfiguration 2.0//EN"
       "http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts>
    < include file ="struts-default.xml" />    
    < package name ="InterceptorDemo" extends="struts-default" >
        < action name ="Timer" class="tutorial.TimerInterceptorAction" >
           
            /Timer.jsp
       
   

至于Timer.jsp可以随意写些什么到里面。发布运行应用程序,在浏览器的地址栏键入http://localhost:8080/Struts2_Interceptor/Timer.action,在出现Timer.jsp页面后,查看服务器的后台输出。

2006 - 12 - 6 14 : 27 : 32 com.opensymphony.xwork2.interceptor.TimerInterceptordoLog
信息: Executed action [ //Timer!execute] took 2859ms.

在您的环境中执行Timer!execute的耗时,可能上述的时间有些不同,这取决于您PC的性能。但是无论如何,2859 ms与500 ms还是相差太远了。这是什么原因呢?其实原因是第一次加载Timer时,需要进行一定的初始工作。当你重新请求Timer.action时,以上输出会 变为:

2006 - 12 - 6 14 : 29 : 18 com.opensymphony.xwork2.interceptor.TimerInterceptordoLog
信息: Executed action [ //Timer!execute] took 500ms.

OK,这正是我们期待的结果。上述例子演示了拦截器timer的用途——用于显示执行某个action方法的耗时,在我们做一个粗略的性能调试时,这相当有用。

自定义拦截器

作为“框架(framework)”,可扩展性是不可或缺的,因为世上没有放之四海而皆准的东西。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。

 

大家在开始着手创建自定义拦截器前,切记以下原则:
拦截器必须是无状态的,不要使用在API提供的ActionInvocation之外的任何东西。

要求拦截器是无状态的原因是Struts 2不能保证为每一个请求或者action创建一个实例,所以如果拦截器带有状态,会引发并发问题。

所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。除此之外,大家可能 更喜欢继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor。

以下例子演示通过继承AbstractInterceptor,实现授权拦截器。

首先,创建授权拦截器类tutorial.AuthorizationInterceptor,代码如下:

package tutorial;

import java.util.Map;

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

public class AuthorizationInterceptor extendsAbstractInterceptor {

  @Override
   public Stringintercept(ActionInvocation ai) throws Exception {
      Map session = ai.getInvocationContext().getSession();
      String role = (String)session.get( " ROLE " );
       if ( null !=role) {
          Object o = ai.getAction();
           if (o instanceof RoleAware) {
              RoleAware action = (RoleAware) o;
              action.setRole(role);
          }
           returnai.invoke();
      } else {
           returnAction.LOGIN;
       }        
   }

}

以上代码相当简单,我们通过检查session是否存在键为“ROLE”的字符串,判断用户是否登陆。如果用户已经登陆,将角色放到Action 中,调用Action;否则,拦截直接返回Action.LOGIN字段。为了方便将角色放入Action,我定义了接口 tutorial.RoleAware,代码如下:

package tutorial;

public interface RoleAware {
   void setRole(Stringrole);
}

接着,创建Action类tutorial.AuthorizatedAccess模拟访问受限资源,它作用就是通过实现RoleAware获取角色,并将其显示到ShowUser.jsp中,代码如下:

package tutorial;

import com.opensymphony.xwork2.ActionSupport;

public class AuthorizatedAccess extendsActionSupport implementsRoleAware {
   private Stringrole;
  
   public void setRole(String role) {
       this .role = role;
   }
  
   public StringgetRole() {
       return role;
   }

  @Override
   public Stringexecute() {
       return SUCCESS;
   }
}

以下是ShowUser.jsp的代码:

<% @ page  contentType= " text/html; charset=UTF-8 " %>
<% @taglib prefix = "s " uri = "/struts-tags " %>
< html>
< head>
    < title > Authorizated User

< body>
    < h1 > Your role is: < s:property value ="role" />

然后,创建tutorial.Roles初始化角色列表,代码如下:

package tutorial;

import java.util.Hashtable;
import java.util.Map;


public class Roles {
   public Map < String, String> getRoles() {
      Map < String, String >roles = new Hashtable < String, String >( 2 );
      roles.put( " EMPLOYEE " , " Employee " );
      roles.put( " MANAGER " , " Manager " );
       return roles;
   }
}

接下来,新建Login.jsp实例化tutorial.Roles,并将其roles属性赋予标志,代码如下:

<% @ page  contentType= " text/html; charset=UTF-8 " %>
<% @taglib prefix = "s " uri = "/struts-tags " %>
< html>
< head>
    < title > Login

< body>
    < h1 > Login
    Please select a role below:
    < s:bean id ="roles" name="tutorial.Roles" />
    < s:form action ="Login" >
        < s:radio list ="#roles.roles" value="'EMPLOYEE'" name ="role" label ="Role"/>
        < s:submit />
   

创建Action类tutorial.Login将role放到session中,并转到Action类tutorial.AuthorizatedAccess,代码如下:

package tutorial;

import java.util.Map;

import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

public class Login extends ActionSupport implementsSessionAware {
   private Stringrole;    
   private Mapsession;

   public StringgetRole() {
       return role;
   }

   public void setRole(String role) {
       this .role = role;
   }
  
   public void setSession(Map session) {
       this .session = session;
   }

  @Override
   public String execute(){
      session.put( "ROLE " , role);
       return SUCCESS;
   }    
}

最后,配置struts.xml文件,内容如下:

        "-//Apache Software Foundation//DTD StrutsConfiguration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
< struts>
    < include file ="struts-default.xml" />    
    < package name ="InterceptorDemo" extends="struts-default" >
        < interceptors >
           
       
        < action name ="Timer" class="tutorial.TimerInterceptorAction" >
           
            /Timer.jsp
       
        < action name ="Login" class="tutorial.Login" >
            AuthorizatedAccess
       
        < action name ="AuthorizatedAccess" class ="tutorial.AuthorizatedAccess">
           
            /Login.jsp
            /ShowRole.jsp
       
   

发布运行应用程序,在浏览器地址栏中输入:http://localhost:8080/Struts2_Interceptor/AuthorizatedAccess.action。由于此时,session还没有键为“ROLE”的值,所以返回Login.jsp页面,如图2所示:

  图2 Login.jsp

选中Employee,点击Submit,出现图3所示页面:

  图3 ShowRole.jsp

总结

拦截器是Struts 2比较重要的一个功能。通过正确地使用拦截器,我们可以编写高可复用的代码。