拦截器(Interceptor)是Struts 2的核心组件,Struts 2框架的大部分功能都是经过拦截器来完成的,例如数据校验,国际化,文件上传和下载等。为了实现这些功能,Struts 2框架提供了一个强大的拦截器策略。html
拦截器的配置是在struts.xml文件中完成的,拦截器一般使用<interceptor>标签来定义,该标签有两个属性name和class,分别用来指定拦截器名称及其实现类。java
<interceptor name="interceptorName" class="interceptorClass"> <param name="paramName">paramValue</param> </interceptor>
<package name="default" extends="struts-default" > <interceptors> <!--定义两个拦截器,拦截器名分别为interceptor1和interceptor2--> <interceptor name="interceptor1" class=”interceptorClass”/> <interceptor name="interceptor2" class=”interceptorClass”/> <!--定义一个拦截器栈,拦截器包含了两个拦截器--> <interceptor-stack name="myStack"> <interceptor-ref name="interceptor1"/> <interceptor-ref name="interceptor2"/> </interceptor-stack> </interceptors> </package>
注意:在一个拦截器栈中也能够引用另外一个拦截器栈。spring
<?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> <package name="default" extends="struts-default"> <interceptors> <!--定义两个拦截器--> <interceptor name="interceptor1" class="interceptorClass"/> <interceptor name="interceptor2" class="interceptorClass"/> <!--定义一个拦截器栈--> <interceptor-stack name="myStack"> <interceptor-ref name="interceptor1"/> <interceptor-ref name="interceptor2"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <!--配置包下的默认拦截器,既能够是拦截器,也能够是拦截器栈--> <default-interceptor-ref name="myStack"/> <action name="login" class="tutorial.Login"> <result name="input">login.jsp</result> </action> </package> </struts>
struts-default.xml文件位于:struts2-core-2.3.x.jar文件中。包struts-default内容参考以下(摘录自struts-default.xml):apache
<package name="struts-default" abstract="true"> <result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> </result-types> <interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" /> <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/> <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/> <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/> <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" /> <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" /> <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" /> <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" /> <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" /> <!-- Basic stack --> <interceptor-stack name="basicStack"> <interceptor-ref name="exception"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> </interceptor-stack> <!-- Sample validation and workflow stack --> <interceptor-stack name="validationWorkflowStack"> <interceptor-ref name="basicStack"/> <interceptor-ref name="validation"/> <interceptor-ref name="workflow"/> </interceptor-stack> <!-- Sample file upload stack --> <interceptor-stack name="fileUploadStack"> <interceptor-ref name="fileUpload"/> <interceptor-ref name="basicStack"/> </interceptor-stack> <!-- Sample model-driven stack --> <interceptor-stack name="modelDrivenStack"> <interceptor-ref name="modelDriven"/> <interceptor-ref name="basicStack"/> </interceptor-stack> <!-- Sample action chaining stack --> <interceptor-stack name="chainStack"> <interceptor-ref name="chain"/> <interceptor-ref name="basicStack"/> </interceptor-stack> <!-- Sample i18n stack --> <interceptor-stack name="i18nStack"> <interceptor-ref name="i18n"/> <interceptor-ref name="basicStack"/> </interceptor-stack> <!-- An example of the paramsPrepareParams trick. This stack is exactly the same as the defaultStack, except that it includes one extra interceptor before the prepare interceptor: the params interceptor. This is useful for when you wish to apply parameters directly to an object that you wish to load externally (such as a DAO or database or service layer), but can't load that object until at least the ID parameter has been loaded. By loading the parameters twice, you can retrieve the object in the prepare() method, allowing the second params interceptor to apply the values on the object. --> <interceptor-stack name="paramsPrepareParamsStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="i18n"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack> <!-- A complete stack with all the common interceptors in place. Generally, this stack should be the one you use, though it may do more than you need. Also, the ordering can be switched around (ex: if you wish to have your servlet-related objects applied before prepare() is called, you'd need to move servletConfig interceptor up. This stack also excludes from the normal validation and workflow the method names input, back, and cancel. These typically are associated with requests that should not be validated. --> <interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack> <!-- The completeStack is here for backwards compatibility for applications that still refer to the defaultStack by the old name --> <interceptor-stack name="completeStack"> <interceptor-ref name="defaultStack"/> </interceptor-stack> <!-- Sample execute and wait stack. Note: execAndWait should always be the *last* interceptor. --> <interceptor-stack name="executeAndWaitStack"> <interceptor-ref name="execAndWait"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> <interceptor-ref name="defaultStack"/> <interceptor-ref name="execAndWait"> <param name="excludeMethods">input,back,cancel</param> </interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="defaultStack"/> <default-class-ref class="com.opensymphony.xwork2.ActionSupport" /> </package>
<package name="default" extends="struts-default"> <interceptors> <!--定义三个拦截器--> <interceptor name="interceptor1" class="interceptorClass"/> <interceptor name="interceptor2" class="interceptorClass"/> <interceptor name="interceptor3" class="interceptorClass"> <param name="paramName">paranValue1</param> </interceptor> <!--定义一个拦截器栈--> <interceptor-stack name="myStack"> <interceptor-ref name="interceptor1"/> <interceptor-ref name="interceptor2"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <action name="login" class="tutorial.Login"> <result name="input">login.jsp</result> <!--在名为login的Action中使用已经定义的拦截器--> <interceptor-ref name="interceptor1"/> <interceptor-ref name="interceptor2"/> <interceptor-ref name="interceptor3"> <param name="paramName">paramValue2</param> </interceptor-ref> <interceptor-ref name="myStack"/> </action> </package>
注意:拦截器的参数指定有两种方式,一种是在定义拦截器时指定参数,该种方式指定的参数是默认参数;另外一种是在使用拦截器时指定参数,该种方式指定的参数将会覆盖默认参数值。编程
上述内容摘录自:《Java Web整合开发实战》第8章cookie
login.jsp,登陆界面session
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ page isELIgnored="false"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <body> <font style="color:red"><s:property value="errorMessage"/></font> <s:form action="intercepLogin" method="post"> 帐号:<s:textfield name="username"></s:textfield> <br /> 密码:<s:textfield name="password"></s:textfield> <br /> <s:submit value="提交"></s:submit> </s:form> </body> </html>
showDetail.jsp,显示详细信息页面app
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ page isELIgnored="false"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <body> Hello, we are here! </body> </html>
InptercepLoginAction.java,处理登陆请求框架
package com.clzhang.struts2.demo11; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class InptercepLoginAction extends ActionSupport { private String username; private String password; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String execute() { System.out.println(username + "\t" + password); // 一到登陆页面,即移除session中变量 ActionContext.getContext().getSession().remove("userInfo"); // 只要用户名与密码长度大于等于4,都认为是合法用户 if (username.trim().length() >= 4 && password.trim().length() >= 4) { ActionContext.getContext().getSession().put("userInfo", username); return SUCCESS; } return INPUT; } }
ShowAction.java,处理显示详细信息请求jsp
package com.clzhang.struts2.demo11; import com.opensymphony.xwork2.ActionSupport; public class ShowAction extends ActionSupport { public String execute() { return SUCCESS; } }
LoginInterceptor.java,拦截器类,处理检查用户是否已经登陆
package com.clzhang.struts2.demo11; import java.util.Map; import com.opensymphony.xwork2.Action; 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实例 ActionContext ctx = invocation.getInvocationContext(); Map session = ctx.getSession(); String user = (String)session.get("userInfo"); // 若是没有登录 if (user != null) { System.out.println("当前用户已经登陆,继续处理请求..."); return invocation.invoke(); } ctx.put("errorMessage", "你尚未登陆,或者登陆超时,请从新登陆后继续操做!"); return Action.LOGIN; } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="myStruts" extends="struts-default"> <interceptors> <interceptor name="authority" class="com.clzhang.struts2.demo11.LoginInterceptor"> </interceptor> <!-- 拦截器栈 --> <interceptor-stack name="myDefault"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="authority"/> </interceptor-stack> </interceptors> <global-results> <result name="login">/struts2/demo11/login.jsp</result> </global-results> <action name="intercepLogin" class="com.clzhang.struts2.demo11.InptercepLoginAction"> <result name="input">/struts2/demo11/login.jsp</result> <result name="success" type="redirectAction"> <param name="actionName">intercepShow</param> </result> </action> <action name="intercepShow" class="com.clzhang.struts2.demo11.ShowAction"> <result>/struts2/demo11/showDetail.jsp</result> <interceptor-ref name="myDefault"/> </action> </package> </struts>
打开IE,输入地址:http://127.0.0.1:8080/st/struts2/intercepShow.action
结果以下:
任意输入4位长度用户名与密码,登陆,便可以显示详细页面。