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, 0, 8192)) != -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>

以上就是使用拦截器实现的防止重复提交问题。

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

时间: 2024-08-07 12:24:00

Struts2.x教程(三) Struts2拦截器的相关文章

Struts2学习第三天——拦截器与文件传输

文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.06.15 lutianfei none 内容摘要: 1.国际化(了解) 2.拦截器(Interceptor)-重点 3.struts2文件上传与下载(次重点) 4.ognl与valuestack 国际化 国际化原理,什么是国际化 ? 同一款软件 可以为不同用户,提供不同语言界面 -- 国际化软件 需要一个语言资源包(很多properties文件,每个properties文件 针对一个国家或者语言 ,通过java程序根

struts2.1.6教程五、拦截器

在前面我们已经初步使用过拦截器,下面继续细细探讨. 1.概述strust2中的拦截器 拦截器是Struts2框架的核心,它主要完成解析请求参数.将请求参数赋值给Action属性.执行数据校验.文件上传等工作.Struts2设计的灵巧性,拦截器起了关键性的作用,当需要扩展Struts2功能时,只需要提供对应拦截器,并将它配置在Struts2容器中即可:如果不需要该功能时,也只需要取消该拦截器的配置即可.    Struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在stru

【Struts2三】拦截器

拦截器:就是在访问action之前,对其进行拦截!可以在拦截器中做一些逻辑的处理!比如权限验证,没有权限就不给予访问! 拦截器等效于servlet中的过滤器! 使用拦截器步骤: 1.定义自己的拦截器: import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; /** * 定义自己的拦截器,需要实现Intercept接口! * */ public 

Struts2重新学习之自定义拦截器(判断用户是否是登录状态)

拦截器 一:1:概念:Interceptor拦截器类似于我们学习过的过滤器,是可以再action执行前后执行的代码.是web开发时,常用的技术.比如,权限控制,日志记录. 2:多个拦截器Interceptor连在一起组成了Interceptor栈.拦截器是AOP面向切面编程的一种实现,具有热插拔的效应. 3:Struts2拦截器,每个拦截器类只有一个对象实例,即采用了单利模式.所有引用这个拦截器的action都共享着一拦截器类的实例. 拦截器和过滤器的区别 1:拦截器和过滤器的概念非常类似 2:

Struts2.x教程(一) Struts2介绍

一.Struts2是什么 Struts2是在WebWork2基础发展而来的.和Struts1一样, Struts2也是基于MVC的web层框架. 那么既然有了Struts1,为何还要Struts2? Struts2和Struts1虽然都是基于MVC的Web框架,但是它们的实现机制完全不同. Struts1是基于Servlet的实现,并且Struts1的API过分依赖容器,导致了Action开发.测试都非常繁琐,而Struts2是基于过滤器的实现,API不再依赖容器,测试过程中不必再模拟Web容器

springboot三种拦截器的使用与比较

springboot中有三种拦截器可供选择:filter.interceptort和aop.本文主要讨论三种拦截器的使用场景与使用方式. 下文中的举例功能是计算每个请求的从开始到结束的时间,例子来源是慕课网. 一.filter 特点:可以获取原始的ServletRequest,但无法获取具体方法 实现: 1.继承javax.servlet.Filter类, [email protected]注解将其注入到框架中 3.实现其中的dofilter方法,所有的请求都会经过该方法,可以在此计算出每个请求

struts2进阶【6】——拦截器

小解拦截器 可以说,"拦截器"是Struts2的重点内容.见名知义,拦截器的作用主要就是拦截东西,拦截什么呢?当然是'action'了,在执行'action'之前 拦截器会起作用,执行一些预先处理的代码,接着去执行action中相关的方法,之后,流程又会回到拦截器里面,接着去执行后续的一些操作. 在这里还要提两点: 1. Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2. 拦截器栈(Interceptor Stack).Struts2拦截器栈就是将拦截器按一定的顺序联结成

Struts2利用token和tokenSession拦截器防止重复提交

有时候网络响应慢,用户可能会再次点击提交按钮,或者在保存页面refresh 也会造成重复提交,这样会造成数据库中有多条相同的数据: 我们当然可以利用js来控制,但是如果浏览器禁用了JS,那就不能控制了. Struts2中设计了token和tokenSession拦截器来拦截重复提交: jsp页面: 1 <@ taglib prefix="s" uri="/struts-tags" /> 2 3 <s:form action="testTo

[原创]java WEB学习笔记74:Struts2 学习之路--自定义拦截器,struts内建的拦截器

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------