Struts2 - Struts2的拦截器Interceptor(从零开始学习Strust2_08)

开发环境:

Eclipse IDE for Java EE Developers(下载地址

struts-2.3.1.2(下载地址

apache-tomcat-6.0.35(下载地址


效果图:






以下讲解摘录自《Struts2 权威指南》李刚

       拦截器体系是Struts2的一个重要组成部分,对于Struts2框架而言,可以将其理解为一个空容器,正是大量的内建拦截器完成了该框架的大部分操作。比如,params拦截器将http请求中的参数解析出来,设置成Action的属性;servlet-config拦截器直接将http请求中的HttpServletRequest实例和HttpServletResponse实例传给Action;fileUpload拦截器则负责解析请求参数中的文件域,并将一个文件域设置成Action的三个属性等等。

       对于Struts2的拦截器体系而言,当我们需要使用某个拦截器时,只需要在配置文件中应用该拦截器即可;如果不需要使用该拦截器,也只需要取消在配置文件中应用该拦截器-不管是否应用某个拦截器,对于整个Struts2框架不会有任何影响。这种设计哲学是一种可插拔式的设计,具有非常好的可扩展性。

       拦截器可以动态地拦截发送到指定Action的请求,通过拦截器机制,我们可以再Action执行的前后插入某些代码。通过这种方式,就可以把多个Action中需要重复指定的代码提取出来,放在拦截器里定义,从而提供更好的代码重用性。

      对于struts2框架的Action而言,它们有一些总是需要完成输入校验,有一些总是需要解析文件上传表单中的文件域,有一些总是需要防止表单的多次提交等等。

      在这种需求下,当然可以通过在Action中分别调用不同的方法来实现这些需求,但这种直接调用方法的方式缺陷很明显:Action类直接调用的用所需方法,造成了该Action与特定方法耦合,降低了Action类的复用性。

      拦截器通过在配置文件中指定拦截器,从而可以让拦截器方法在目标方法执行之前或者执行之后自动执行,从而完成通用操作的动态插入。在这种策略下,类型转换的处理、数据校验的处理、文件上传的处理、阻止表单多次提交的处理。。。这些不同的通用处理,都被定义成相应的拦截器。如果用户的Action需要使用特定的通用功能,只需要在struts.xml文件制定拦截器引用,可以在Action之前完成这些通用方法。

通过实现Interceptor接口,实现自己的拦截器

Init():在该拦截器被初始化之后,拦截器执行拦截之前,系统将回调该方法。对于每个拦截器而言,该init()方法只执行一次。因此,该方法的方法体主要用于打开一些一次性的资源,例如数据库资源等。

Destroy():该方法与init()方法对应。在拦截器实例被销毁之前,系统将回调拦截器的destroy方法,该方法用于销毁在init()方法打开的资源。

Intercept(ActionInvocation invocation):该方法是用户需要实现的拦截动作。就像Action的execute方法一样,intercept方法会返回一个字符串作为逻辑视图。如果该方法直接返回一个字符串,系统将会跳转到该逻辑视图对应的实际视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以用过该参数的invoke方法,将控制权转给下一个拦截器或者转给Action的execute方法。

      当配置一个包时,可以为其制定默认拦截器。一旦为某个包指定了默认的拦截器,如果该包中的Action没有显示制定拦截器,则默认的拦截器将会起作用。

      Struts2的内建拦截器defaultStack(通常不推荐自己为每一个Action分别定义拦截器,而是推荐直接使用系统的defaultStack拦截器栈)

      Struts2的struts-default包中指定defaultStack拦截器时默认的拦截器,因此如果用户定义的包继承了struts-default包,则也会将defaultStack拦截器栈作为默认的拦截器栈。这意味着:如果系统中的Action配置没有指定拦截器引用,系统会将defaultStack拦截器自动作用于该Action。

但是,如果为Action指定了一个拦截器,则系统默认的拦截器将会失去作用,为了继续使用默认拦截器,在配置文件中需要动手引入默认拦截器。

Struts2自带的拦截器

拦截器

名字

说明

Alias Interceptor

alias

在不同请求之间将请求参数在不同名字件转换,请求内容不变

Chaining Interceptor

chain

让前一个Action的属性可以被后一个Action访问,现在和chain类型的result()结合使用。

Checkbox Interceptor

checkbox

添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。

Cookies Interceptor

cookies

使用配置的name,value来是指cookies

Conversion Error Interceptor

conversionError

将错误从ActionContext中添加到Action的属性字段中。

Create Session Interceptor

createSession

自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。

Debugging Interceptor

debugging

提供不同的调试用的页面来展现内部的数据状况。

Execute and Wait Interceptor

execAndWait

在后台执行Action,同时将用户带到一个中间的等待页面。

Exception Interceptor

exception

将异常定位到一个画面

File Upload Interceptor

fileUpload

提供文件上传功能

I18n Interceptor

i18n

记录用户选择的locale

Logger Interceptor

logger

输出Action的名字

Message Store Interceptor

store

存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。

Model Driven Interceptor

model-driven

如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。

Scoped Model Driven

scoped-model-driven

如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。

Parameters Interceptor

params

将请求中的参数设置到Action中去。

Prepare Interceptor

prepare

如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。

Scope Interceptor

scope

将Action状态存入session和application的简单方法。

Servlet Config Interceptor

servletConfig

提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。

Static Parameters Interceptor

staticParams

从struts.xml文件中将中的中的内容设置到对应的Action中。

Roles Interceptor

roles

确定用户是否具有JAAS指定的Role,否则不予执行。

Timer Interceptor

timer

输出Action执行的时间

Token Interceptor

token

通过Token来避免双击

Token Session Interceptor

tokenSession

和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中

Validation Interceptor

validation

使用action-validation.xml文件中定义的内容校验提交的数据。

Workflow Interceptor

workflow

调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面

Parameter Filter Interceptor

N/A

从参数列表中删除不必要的参数

Profiling Interceptor

profiling

通过参数激活profile


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>struts2_20120315_01</display-name>
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

struts.xml,在struts中定义了自定义的拦截器AuthInterceptor,在Action中引入了自定的拦截器,同时也引入了默认的系统拦截器栈defaultStack;

这里需要注意一点就是拦截器的引入顺序~~~~先引入defaultStack,再引入自定义的AuthInterceptor。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

	<constant name="struts.devMode" value="true" />

	<package name="default" extends="struts-default">
		<interceptors>
			<interceptor name="AuthInterceptor"
				class="com.zeph.struts2.interceptor.AuthInterceptor"></interceptor>
		</interceptors>
		<action name="LoginAction" class="com.zeph.struts2.action.LoginAction">
			<result name="success">/success.jsp</result>
			<result name="error">/error.jsp</result>
			<result name="input">/index.jsp</result>
			<interceptor-ref name="defaultStack" />
			<interceptor-ref name="AuthInterceptor" />
		</action>
	</package>
	
</struts>

LoginAction.java 在execute方法中,删除了验证userName==admin,将此功能写入到自定义的拦截器中AuthInterceptor。

package com.zeph.struts2.action;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {

	private static final long serialVersionUID = 1L;

	private String userName;
	private String password;
	private ActionContext context;

	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;
	}

	@Override
	public void validate() {
		if (getUserName().length() == 0) {
			addFieldError("userName", "User Name is required.");
		}
	}

	@Override
	public String execute() throws Exception {
		context = ActionContext.getContext();
		Integer count = (Integer) context.getApplication().get("count");
		if (count == null) {
			count = 1;
		} else {
			count++;
		}
		// 删除了admin的用户名的判断,把它放在自定义的拦截器中
		context.getApplication().put("count", count);
		context.getSession().put("userName", getUserName());
		return SUCCESS;

	}
}

AuthInterceptor.java 自定的拦截器,方法是通过实现Interceptor接口来实现。

package com.zeph.struts2.interceptor;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.zeph.struts2.action.LoginAction;

public class AuthInterceptor implements Interceptor {

	private static final long serialVersionUID = 1L;

	@Override
	public void destroy() {

	}

	@Override
	public void init() {

	}

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		LoginAction loginAction = (LoginAction) invocation.getAction();
		String userName = loginAction.getUserName();
		if (userName != null && userName.equals("admin")) {
			return invocation.invoke();
		} else {
			return Action.INPUT;
		}

	}

}

index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>login</title>
</head>
<body>
	<s:form action="LoginAction">
		<s:textfield name="userName" label="UserName"/>
		<s:password name="password" label="Password"/>
		<s:submit/>
	</s:form>
</body>
</html>


success.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login Success</title>
</head>
<body>
	<s:property value="#session.userName" />
	,login success,
	<a href="context.jsp">redirect to context</a>. times:
	<s:property value="#application.count" />
</body>
</html>

error.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>error</title>
</head>
<body>
	<P>Sorry, login failed!!!!</P>
</body>
</html>

context.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>context page</title>
</head>
<body>
	welcome,
	<s:property value="#session.userName" />
	.
	<script language="JavaScript" type="text/javascript">
		var today;
		var day;
		var date;
		today = new Date();
		if (today.getDay() == 0)
			day = "Sunday ";
		if (today.getDay() == 1)
			day = "Monday";
		if (today.getDay() == 2)
			day = "Tuesday ";
		if (today.getDay() == 3)
			day = "Wednesday";
		if (today.getDay() == 4)
			day = "Thursday ";
		if (today.getDay() == 5)
			day = "Friday";
		if (today.getDay() == 6)
			day = "Saturday ";
		date = "Today is " + (today.getYear()) + "/" + (today.getMonth() + 1)
				+ "/" + today.getDate();
		document.write(date);
		document.write(" " + day);
	</script>
</body>
</html>

















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值