Struts2.x教程(三) Struts2拦截器

一、Struts2拦截器介绍
    Struts2拦截器是使用AOP实现的,主要是针对action对象进行拦截,可以在访问action的某个方法、字段之前或之后实施拦截。
    可以为action配置多个拦截器,Struts2会将这一组拦截器按照一定顺序组织成一个拦截器栈。action可以直接引用某个拦截器栈来实现配置多个拦截器的目的。
 
    对于继承struts_default的package中的action,都会默认引用name=defaultStack的拦截器栈(在struts_default中定义了Struts2提供的各种拦截器),action对于拦截器的调用顺序参考下图:
 
 
二、拦截器实现
    Struts2的拦截器都实现了com.opensymphony.xwork2.interceptor. Interceptor接口:
public  interface Interceptor  extends Serializable {
     //销毁方法
     void destroy();
     //初始化方法
     void init();
     //拦截方法
    String intercept(ActionInvocation invocation)  throws Exception;
}
我们要实现一个自定义的拦截器,就要实现Interceptor接口,并主要实现intercept()方法。例如下面,我们实现一个简单的认证拦截器:
public  class AuthorityInterceptor  implements Interceptor {
    
     public  void init() {
    }
    
     public  void destroy() {
    }
    
    @Override
     public String intercept(ActionInvocation invocation)  throws Exception {
        Object user  = ActionContext.getContext().getSession().get( "user");
         if (user  == null) {
            System.out.println( "未登录,请先登录!");
             return  "login";
        }
         return invocation.invoke();
    }
}
 
在自定义的拦截器中的intercept()中,我们可以返回一个字符串Result,此时请求会终止并跳转到对应的result。
invocation是一个ActionInvocation的引用,ActionInvocation负责调用该请求的action及其一系列拦截器,当我们调用invocation.invoke()时,它会判断此时拦截器栈是否还有拦截器,是的话会调用下一个拦截器的拦截方法,否则会调用action对应的请求方法。
 
以上,我们就实现了一个自定义的拦截器。
 
要让这个自定义的拦截器工作,就需要在struts.xml配置文件中进行配置:
首先,要在package元素下,对拦截器进行声明:
        <interceptors>
            <interceptor name="authorityInterceptor" class="com.boya.struts2.interceptor.AuthorityInterceptor"></interceptor>
        </interceptors>
然后,在action元素中引用这个拦截器就可以了,如:
         <action name="user" class="com.boya.struts2.web.UserAction">
             <interceptor-ref name="authorityInterceptor" />
              <result>/success.jsp </result>
         </action>
 
但是,需要注意的是:
当在action元素中设置了<interceptor-ref name="authorityInterceptor" />,它会覆盖默认的defaultStack拦截器栈的引用。假设自定义的拦截器仅仅是一个日志拦截,那么这样配置,defaultStack中的拦截器都不会调用,比如最重要的参数拦截器ParametersInterceptor,调用action时就会出现问题。因此在对action添加拦截器引用时,通常这样配置:
         <action name="user" class="com.boya.struts2.web.UserAction">
              <interceptor-ref name="defaultStack" />
              <interceptor-ref name="authorityInterceptor" />
             <result>/success.jsp</result>
         </action>
 
三、使用拦截器实现文件上传
Struts 2是使用commons-fileupload进行文件上传的,首先使用commons-fileupload将文件上传到临时目录中,然后Struts2拦截器将文件信息封装入action对象,然后以操作本地文件的方式完成指定目录的上传。
文件上传实现步骤:
1、页面设置文件上传表单
<s:form action="doUpload" method="POST" enctype="multipart/form-data">
    <s:file name="upload" label="File"/>
    <s:submit/>
</s:form>
2、编写文件上传Action
public  class FileUploadAction  extends ActionSupport {
     private  static  final  long serialVersionUID  =  5156288255337069381L;
     private String contentType;     //上传文件的类型
     private File upload;     //上传文件
     private String fileName;     //上传文件的名称
     private String caption;     //提交的相关信息
     public String input()  throws Exception {
         return SUCCESS;
    }
     public String upload()  throws Exception {
        String path  =  "upload\\";
        InputStream in  =  new FileInputStream(upload);
        String contextPath  = ServletActionContext.getServletContext().getRealPath( "/");
        File dir  =  new File(contextPath);
         if ( !dir.exists()) {
            dir.mkdir();
        }
        String filePath  = contextPath  + path  + fileName;
        OutputStream out  =  new FileOutputStream(filePath);
         int bytesRead;
         byte[] buffer  =  new  byte[ 8192];
         while ((bytesRead  = in.read(buffer,  08192))  !=  - 1) {
            out.write(buffer,  0, bytesRead);
        }
        out.close();
        in.close();
        
         return SUCCESS;        
    }
     public String getUploadFileName() {
         return fileName;
    }
     public  void setUploadFileName(String fileName) {
         this.fileName  = fileName;
    }
     public String getUploadContentType() {
         return contentType;
    }
     public  void setUploadContentType(String contentType) {
         this.contentType  = contentType;
    }
     public File getUpload() {
         return upload;
    }
     public  void setUpload(File upload) {
         this.upload  = upload;
    }
     public String getCaption() {
         return caption;
    }
     public  void setCaption(String caption) {
         this.caption  = caption;
    }
}
注意:拦截器会将文件名称及文件的编码类型封装入uploadFileName和uploadContentType属性中,其中upload是对应页面中file标签的name名称,FileName和ContentType是固定后缀,因此getter和setter方法要对应这两个名称,否则无法对文件信息进行封装。
 
3、在struts.xml配置文件中,配置action请求即可
        <action name="upload" class="com.boya.ssh.web.FileUploadAction" method="input">
            <result>/upload.jsp</result>
        </action>
        <action name="doUpload" class="com.boya.ssh.web.FileUploadAction" method="upload">
            <result name="input">/upload.jsp</result>
            <result>/upload-success.jsp</result>
        </action>
 
注意:
    a、Struts2是使用拦截器来完成文件上传的,而因为action默认引用的defaultStack拦截器栈中已经包含了fileUpload拦截器,因此无需再添加文件上传拦截器的引用。
    b、Struts2默认上传文件最大为2M,可以通过 <constant name="struts.multipart.maxSize" value="20971520/> 来修改最大上传文件的限制(修改为20M,单位为字节)
 
四、重复提交拦截器
在Struts2中防止重复提交机制也是通过拦截器实现的,它的原理是:
1、在页面中添加<s:token />标签:
    它会在session中生成一个key为struts.token的随机字符串,
    同时在页面添加对应的隐藏于标签,如:
        <input type="hidden" name="struts.token.name" value="token" />
        <input type="hidden" name="token" value="448CL36HMFSEORYB9X12ZHU8B10W87U9" />
2、提交表单时,同时将隐藏域进行提交,在token拦截器中对提交的token值和session中保存的token值进行比较:
    如果相等,执行后续请求处理,同时将session中的token清空。
    如果不等,则拦截请求。
它正是通过这种方式对重复的请求进行拦截,以防止重复提交。
 
Struts2提供了两种重复提交拦截器实现;
    token:出现重复提交后跳转到指定的页面,需要配置 <result name="invalid.token">/input</result>
    tokenSession:重复提交时按钮无效,页面不会调整,第一次的请求完成后跳转到成功页面
对比这两种拦截机制,tokenSession适用性更强些。
 
实现步骤:
1、页面添加<s:token />,放在form表单内即可。
    Struts1的token标签必须使用<html:form />,而Struts2已经没有这个限制了,普通的html标签仍然可以使用<s:token />来实现防止重复提交。
2、在struts.xml中添加拦截器引用,defaultStack拦截器栈中没有token拦截器,因此需要添加引用
        <action name="saveUser" class="com.boya.ssh.web.UserAction" method="save">
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="token" />
            <result name="invalid.token">/user-input</result>
            <result>/user.jsp</result>
        </action>
使用tokenSession拦截器则无需配置invalid.token:
        <action name="saveUser" class="com.boya.ssh.web.UserAction" method="save">
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="tokenSession" />
            <result>/user.jsp</result>
        </action>
 
以上就是使用拦截器实现的防止重复提交问题。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值