Struts2框架学习之六:理解并使用拦截器
来源:互联网 发布:彩卡网络下单系统 编辑:程序博客网 时间:2024/05/19 17:48
前言
拦截器是Struts2框架的核心功能,理解并使用拦截器有助于更灵活使用Struts2。拦截器与Servlet中的过滤器有些类似却又不尽相同。因为在Struts2中拦截器更像一个可插拔的组件,围绕Action和Result进行,可以在方法调用之前、之后使用。通过Struts2的工作流程(后面还会看到一个请求在Struts2中详细的执行流程)可以发现调用一个Action之前之后有许多的拦截器,这些拦截器都通过后才执行具体的action。对于每一个拦截器来说,可以直接返回,从而终止余下的拦截器。
从Struts2的工作流程说起
首先请看截取自官方的一张图:
从图中可以看到,从一个具体的请求到Action需要经过多个拦截器,action处理完毕之后,后续的拦截器会继续执行,最终到浏览器中。Struts2的工作流程如下:
- 请求发送给StrutsPrepareAndExecuteFilter
- StrutsPrepareAndExecuteFilter判断该请求是否是一个Struts2请求,如果是则进入第3步
- 如果是Struts2请求,则把请求交给ActionProxy,是Action的代理类
- ActionProxy创建一个ActionInvocation实例,并进行初始化
- 在执行具体的Action之前,ActionProxy会涉及相关拦截器的调用
- Action调用结束之后,会根据struts.xml文件中action的result配置对象得到对应的返回结果。调用execute方法之后,对返回结果进行渲染
- 执行后面的拦截器
- 把结果返回给浏览器
从整个请求处理过程来看,拦截器是处理的关键。ok,通过以上请求处理过程,我们知道了一个拦截器在Struts2中的工作方式。下面从编写一个简单的拦截开始,学习使用拦截器。
一个简单的拦截器
主要有两种方式:
- 实现Interceptor接口
- 继承AbstractInterceptor抽象类
编写自己的拦截器必须实现com.opensymphony.xwork2.interceptor.Interceptor接口,该接口有三个方法:init()、destroy()、intercept()。init方法在拦截器实例创建之后,intercept方法之前调用,主要用于初始化拦截器所需要的资源;destroy方法在拦截器实例销毁之前调用,用于销毁init初始化分配的资源;intercept方法则是在Action执行之前调用,可以通过invocation对象获取Action的状态,从而根据状态的不同进行需要的拦截操作。
下面以实现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文件中得到,主要有:
- execAndWait(该拦截器可以让需要运行较长时间的action在后台运行,并向用户显示进度信息)
- exception(主要用于异常处理)
- fileUpload(用于文件上传)
- i18n(国际化的支持)
- logger(日志,记录action的开始于结束日志)
- modelDriven(支持模型驱动的拦截器)
- validation(定义自己的验证器)
开发安全验证功能的拦截器
在日常开发中,进行登录验证是很常见的。这里开发的拦截器主要实现的功能是:如果用户没有登录则提示没有登录的信息,并返回到登录页面。如果用户已经登录,则显示资源。这里主要介绍实际开发中拦截器的开发步骤。
步骤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的某个状态进行拦截操作,使用拦截器可以更方便处理业务逻辑。除了以上方式的开发拦截器外还有注解方式,不过注解方式的一个明显缺点是不利于代码的复用,而且注解的底层使用反射的方式完成的,所以使用注解开发,性能是一个值得考虑的问题。
- Struts2框架学习之六:理解并使用拦截器
- Struts2框架之拦截器
- 自己实现Struts2(六)实现参数拦截器并调试框架
- SSH学习(六)Struts2拦截器
- struts2框架学习之工程搭建、拦截器和包
- (六)struts2之拦截器
- ssh框架学习-struts2 使用自定义拦截器进行文字过滤拦截
- Struts2学习之Struts2中的拦截器
- 黑马程序员---struts2学习笔记之六(自定义拦截器)
- 009-Struts2框架拦截器二之方法拦截器
- 框架技术--struts2拦截器与自定义拦截器使用
- Struts2 拦截器 理解
- Spring MVC学习之六:拦截器
- struts2拦截器(六)
- struts2学习笔记之拦截器(Interceptor)
- Struts2学习之拦截器机制
- Struts2学习笔记之自定义拦截器
- Struts2学习笔记之自定义拦截器
- MySQL调优三步曲(慢查询、explain profile)(转)
- wxPython+Matplotlib
- C语言总结
- RecycleView的基本使用方法
- POJ 2159 Ancient Cipher(古老的密码)
- Struts2框架学习之六:理解并使用拦截器
- 创建虚拟机(工作用)
- iOS开发利用桥接(__bridge)简单实现Foundation 和 Core Foundation 相互转换.
- 递推平均值滤波方法分析
- 正则表达式
- 自定义Toast的显示效果
- iOS各种验证
- 理解JMS规范中消息的传输模式和消息持久化
- project euler 94