在struts2的工作原理博文中http://blog.csdn.net/u010412719/article/details/51193352,可以看到,拦截器是struts2的核心,所有复杂的功能都是由拦截器来完成,拦截器可以在Action和result执行之前之后进行一些处理。
下面将介绍如何定义和使用拦截器。
如何自定义一个拦截器?
有以下三个步骤:
1、先自定义一个继承AbstractInterceptor(或实现Interceptor接口)的类。Interceptor接口中有三个函数:init()/destory()/intercept().而AbstractInterceptor是实现了Interceptor接口,并对方法init()和destory()方法进行了空实现。因此,我们一般会选择继承AbstractInterceptor类,这样我们就只需要重写intercept()这一个方法。如果我们选择实现Interceptor接口,则需要重写上面提到的3个抽象方法。
2、在配置文件struts.xml文件中对拦截器进行注册。
3、在需要使用的Action中引用我们自定义的拦截器。
上面的步骤比较清晰,下面我们举一个例子来对这三个步骤进行详细说明。
例如:我们想实现这样一个功能,什么样的功能呢,就是我们想观察下我们的一个Action的执行时间有多长?
实现这样一个功能,就可以借助于自定义拦截器来完成。
代码中有一行代码需要注意下:
String result=invocation.invoke();
这行代码的作用就是:执行剩下其它的拦截器,如果此拦截器是最后一个,则执行Action。此方法的返回值就是Action执行完成之后返回的字符串,即将用于视图映射。
配置拦截器如下:
<!-- 注册拦截器 -->
<interceptors>
<interceptor name="timerInterceptor" class="com.timer.intercept.TimerIntercept">
</interceptor>
</interceptors>
在Action中引用拦截器如下:
<!-- 引用拦截器 -->
<interceptor-ref name="timerInterceptor"></interceptor-ref>
如果我们自定义了自己的拦截器,struts2就不会为Action使用默认拦截器。如果我们在自定义了自己的拦截器后,也要将默认拦截器在Action进行引用。如下:
<interceptor-ref name="defaultStack"></interceptor-ref>
具体例子的struts.xml文件内容截图如下:
以上我们就这样定义、配置和引用了一个拦截器。
注意:在给Action中引用多个拦截器,我们需要注意他们的顺序,因为这决定这这些拦截器的执行顺序。
关于拦截器,有一个拦截器栈的概念,拦截器栈就是多个拦截器的集合。当我们有多个拦截器时,我们就可以自定一个拦截器栈,并将所有即将在Action中引用的拦截器放入其中,最后,在需要引用的地方直接引用此栈即可。
假设我们有这样一个需求:只有管理员admin能够进入后台管理系统,而其他人时不能够进入的,在后台管理系统由一系列的系统文件是只有进行后台管理系统之后才能看得到,不进行是看不到的。
因此这里就需要进行开发权限验证拦截器的帮助,才能实现。
登陆界面在前面介绍过,只涉及到一个表单的编写。
代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+ request.getServerPort()+path+"/"; %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'login.jsp' starting page</title>
</head>
<body>
${ loginError } <!-- 返回错误登陆的信息给此界面 -->
<form action="loginAction.action" method="post">
用户名:<input type="text" name="username"> <br/>
密码:<input type="password" name="password"><br/>
<input type="submit" value="登陆"/>
</form>
</body>
</html>
创建一个Action类来接收输入参数,并处理登陆请求。
代码如下:
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport implements SessionAware{
private String username;
private String password;
private Map<String,Object> session;
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 login(){
if("admin".equals(username)&&"123".equals(password)){
session.put("loginInfo", username);
return SUCCESS;
}
else{
session.put("loginError", "用户名或密码不正确");
return ERROR;
}
}
@Override
public void setSession(Map<String, Object> session) {
this.session=session;
}
}
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/* * 自定义一个拦截器 * */
public class LoginInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext context=ActionContext.getContext();
Map<String,Object> session=context.getSession();
if(session.get("loginInfo")!=null){
String result=invocation.invoke();
return result;
}
else{
return "login";
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false"></constant>
<package name="default" namespace="/" extends="struts-default">
<!-- 注册拦截器 -->
<interceptors>
<interceptor name="myInter" class="com.struts.intercept.LoginInterceptor"></interceptor>
<!-- 自定义一个拦截器栈,引用我们自定义的拦截器和默认的拦截器栈,这样在下面我们只需要在下面引用自定义的拦截器栈即可 -->
<interceptor-stack name="mystack">
<interceptor-ref name="myInter"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 通过此Action返回内部页面,需要判断用户是否已登录,如果未登陆则跳转到登陆页面 -->
<action name="auth">
<result>/WEB-INF/page/innerPage.jsp</result>
<result name="login">/login.jsp</result>
<interceptor-ref name="mystack"></interceptor-ref>
</action>
<!-- 登陆action ,如果用户成功登陆,则可以访问/WEB-INF/page/innerPage.jsp 否则,返回login.jsp -->
<action name="loginAction" method="login" class="com.struts.action.LoginAction">
<result>/WEB-INF/page/innerPage.jsp</result>
<result name="error">/login.jsp</result>
</action>
</package>
</struts>
注释写的比较详细,这里就不再介绍。
1、当我们打开浏览器,首次输入http://localhost:8080/AuthInterceptor/auth时,由于拦截器的作用,会返回到login.jsp页面
2、当我们在登陆界面,由于用户名或密码不正确,则会提示错误信息。如下:
3、当我们的用户名和密码均正确时,则访问到了内部页面。
4、当我们访问成功之后,再一次访问http://localhost:8080/AuthInterceptor/auth时,则由于Session中保存了之前的用户信息,因此,可以正常访问,这和我们在生活中的登陆比较类似,在我们刚刚登陆过退出之后,有的系统就可以直接进行登陆,而不是要求我们继续输出用户名和密码,但是有的系统却不是这样,例如银行系统,则当我们退出之后,则需要重新输入的。
以上只是从自定义一个拦截器出发来简单的介绍了下如何使用拦截器。
慕课网:《Struts2拦截器浅析》这个视频教程