前言html
拦截器是Struts2框架的核心功能,理解并使用拦截器有助于更灵活使用Struts2。拦截器与Servlet中的过滤器有些相似却又不尽相同。由于在Struts2中拦截器更像一个可插拔的组件,围绕Action和Result进行,能够在方法调用以前、以后使用。经过Struts2的工做流程(后面还会看到一个请求在Struts2中详细的执行流程)能够发现调用一个Action以前以后有许多的拦截器,这些拦截器都经过后才执行具体的action。对于每个拦截器来讲,能够直接返回,从而终止余下的拦截器。java
从Struts2的工做流程提及apache
首先请看截取自官方的一张图:浏览器
从图中能够看到,从一个具体的请求到Action须要通过多个拦截器,action处理完毕以后,后续的拦截器会继续执行,最终到浏览器中。Struts2的工做流程以下:安全
从整个请求处理过程来看,拦截器是处理的关键。ok,经过以上请求处理过程,咱们知道了一个拦截器在Struts2中的工做方式。下面从编写一个简单的拦截开始,学习使用拦截器。markdown
一个简单的拦截器session
主要有两种方式:多线程
编写本身的拦截器必须实现com.opensymphony.xwork2.interceptor.Interceptor接口,该接口有三个方法:init()、destroy()、intercept()。init方法在拦截器实例建立以后,intercept方法以前调用,主要用于初始化拦截器所须要的资源;destroy方法在拦截器实例销毁以前调用,用于销毁init初始化分配的资源;intercept方法则是在Action执行以前调用,能够经过invocation对象获取Action的状态,从而根据状态的不一样进行须要的拦截操做。app
下面以实现Interceptor接口为例,编写一个计算Action执行execute方法的时间的拦截器。代码以下:框架
package interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class TimeIntercptor implements Interceptor {
private static final long serialVersionUID = 1L;
@Override
public void destroy() {
}
@Override
public void init() {
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
long start = System.currentTimeMillis();
//执行action的execute方法
String result = invocation.invoke();
long end = System.currentTimeMillis();
System.out.println("执行execute方法的时间是" + (end - start));
return result;
}
}
在编写一个action并在struts.xml配置文件中进行配置,在浏览器中进行测试就能够获得执行execute方法的具体时间了。在编写拦截器类的时候须要注意:在拦截器中不该该有实例变量,由于拦截器是无状态的,无状态的解释是若是拦截器有状态,那么在多线程同时访问拦截器实例的时候,拦截器的状态是不可预知的。
至此,咱们已经学会了如何编写一个简单的拦截器,下面介绍在拦截器中自带的拦截器哟哪些。
Struts2中自带的拦截器
自带的拦截器能够在struts-default.xml文件中获得,主要有:
开发安全验证功能的拦截器
在平常开发中,进行登陆验证是很常见的。这里开发的拦截器主要实现的功能是:若是用户没有登陆则提示没有登陆的信息,并返回到登陆页面。若是用户已经登陆,则显示资源。这里主要介绍实际开发中拦截器的开发步骤。
步骤1:编写基本页面
登陆页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<% 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>登陆</title>
<s:head/>
</head>
</html>
<s:form action="login2">
<s:actionerror/>
<s:textfield label="用户名" name="user.username"></s:textfield>
<s:password label="密码" name="user.password"></s:password>
<s:submit value="登陆"></s:submit>
</s:form>
登陆成功页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<% 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>登陆 | 成功</title>
</head>
<body>
<h3>
<s:property value="user.username"/>,欢迎访问struts2官方网站!
</h3>
</body>
</html>
资源页面:
<%@ 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>绝密资源</title>
</head>
<body>
<strong>这是绝密资源!</strong>
</body>
</html>
步骤二:编写Action
LoginAction2.java:
package action;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import bean.User;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction2 extends ActionSupport implements SessionAware {
private static final long serialVersionUID = 1L;
private User user;
private Map<String, Object> session;
//经过login!input来访问login.jsp
public String input() throws Exception{
return INPUT;
}
@Override
public String execute() throws Exception {
if("admin".equals(user.getUsername()) && "admin".equals(user.getPassword())){
System.out.println(user.getUsername()+"=" + user.getPassword());
session.put("user", user);
return SUCCESS;
}else{
addActionError("登陆失败!");
return INPUT;
}
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
步骤四:编写拦截器
代码以下:
package interceptor;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class AuthenticationInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
/** * 对登陆与否进行拦截验证 */
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext context = ActionContext.getContext();
Map<String, Object> session = context.getSession();
Object user = session.get("user");
if(user == null){
//若是用户未登陆,则返回登陆页面,并添加错误信息
ActionSupport action = (ActionSupport) invocation.getAction();
action.addActionError("您尚未登陆,请先登陆!");
return action.LOGIN;
}else{
//若是用户已经登陆,则执行后面的拦截器方法
return invocation.invoke();
}
}
}
步骤五:在struts.xml中进行配置
<interceptors>
<interceptor name="auth" class="interceptor.AuthenticationInterceptor" />
<interceptor-stack name="securityStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="auth" />
</interceptor-stack>
</interceptors>
<global-results>
<result name="login">/WEB-INF/pages/login.jsp</result>
</global-results>
<action name="login2" class="action.LoginAction2">
<result name="input">/WEB-INF/pages/login.jsp</result>
<result>/WEB-INF/pages/success.jsp</result>
</action>
对于受保护的资源引用上面的拦截器便可
<action name="resource" class="action.ResourceAction">
<result>/WEB-INF/pages/resource.jsp</result>
<interceptor-ref name="annotatedStack" />
</action>
步骤六:在浏览器中输入http:localhost:8090/struts2/login2!input进行测试。
至此,一个安全验证的拦截器就开发完毕。
拦截器小结
从开发过程能够看待,拦截器的做用是Action的某个状态进行拦截操做,使用拦截器能够更方便处理业务逻辑。除了以上方式的开发拦截器外还有注解方式,不过注解方式的一个明显缺点是不利于代码的复用,并且注解的底层使用反射的方式完成的,因此使用注解开发,性能是一个值得考虑的问题。
以上内容转载自https://blog.csdn.net/u011116672/article/details/50381656