`

Struts 2 的拦截器(二)

阅读更多

 

四、 开发自己的拦截器

 Struts 2 框架提供了许多拦截器,这些内建拦截器实现了 struts 2 的大部分功能。但还有一些系统逻辑相关的通用功能,则需要通过自定义拦截器来实现,比如我们可以开放自己的拦截器来完成权限控制,日志记录等。Struts 2 的拦截器系统是如此的简单、易用。

 

4.1  实现拦截器类

    如果用户要开发自己的拦截器,应该实现 com.opensymphony.xwork2.interceptor.Interceptor 接口,该接口定义如下:

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import java.io.Serializable;

public interface Interceptor extends Serializable {
    /**
     * Called to let an interceptor clean up any resources it has allocated.
     */
    void destroy();

    /**
     * Called after an interceptor is created, but before any requests are processed using
     * {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
     * the Interceptor a chance to initialize any needed resources.
     */
    void init();

    /**
     * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
     * request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
     *
     * @param invocation the action invocation
     * @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
     * @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
     */
    String intercept(ActionInvocation invocation) throws Exception;

}

上面接口包含 3 个方法:

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

 ● destroy() : 在拦截器实例被销毁之前,系统将回调该拦截器的 destroy 方法,一般用于销毁在 init() 方法里打开的资源

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

 

除此之外,Struts 2 还提供了一个 AbstractInterceptor ,该类提供了一个 init destroy 方法的空实现,如果拦截器不需要打开资源,则可以无需实现这 2 个方法。可见,用继承 AbstractInterceptor 类来实现自定义拦截器会更加简单:

package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.ActionInvocation;

public abstract class AbstractInterceptor implements Interceptor {

    /**
     * Does nothing
     */
    public void init() {
    }
    
    /**
     * Does nothing
     */
    public void destroy() {
    }

    /**
     * Override to handle interception
     */
    public abstract String intercept(ActionInvocation invocation) throws Exception;
}
 

下面实现了一个简单的拦截器:

SimpleInterceptor

package js.a;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import java.util.*;

public class SimpleInterceptor extends AbstractInterceptor {
    // 简单拦截器的名字
    private String name;

    // 为该简单拦截器设置名字的setter方法
    public void setName(String name) {
        this.name = name;
    }

    public String intercept(ActionInvocation invocation) throws Exception {
        // 取得被拦截的Action实例
        LoginAction action = (LoginAction) invocation.getAction();
        // 打印执行开始的实现
        System.out.println(name + " 拦截器的动作---------" + "开始执行登录Action的时间为:"
            + new Date());
        // 取得开始执行Action的时间
        long start = System.currentTimeMillis();
        // 执行该拦截器的后一个拦截器
        // 如果该拦截器后没有其他拦截器,则直接执行Action的execute方法
        String result = invocation.invoke();
        // 打印执行结束的时间
        System.out.println(name + " 拦截器的动作---------" + "执行完登录Action的时间为:"
            + new Date());
        long end = System.currentTimeMillis();
        System.out.println(name + " 拦截器的动作---------" + "执行完该Action的事件为"
            + (end - start) + "毫秒");
        return result;
    }
}
 

ActionInvocation 参数可以获得被拦截的 Action 实例,一旦取得了 Action 实例,几乎获得了全部的控制权: 可以实现将 HTTP 请求中的参数解析出来,设置成 Action 的属性(这是系统 params 拦截器干的事情);也可以直接将 HTTP 请求中的 HttpServletRequest 实例和 HttpServleResponse 实例传给 Action (这是 servletConfig 拦截器干的事情),也可以实现应用相关的逻辑

 

LoginAction

package js.a;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
    private String username;

    private String password;

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public String execute() throws Exception {
        System.out.println("进入execute方法执行体..........");
        Thread.sleep(1500);
        if (getUsername().equals("crazyit") && getPassword().equals("leegang")) {
            return SUCCESS;
        } else {
            return ERROR;
        }
    }
}

 struts.xml

<?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.2.dtd">
<struts>
   	
	<constant name="struts.custom.i18n.resources"
		value="messageResource"/>
	<constant name="struts.i18n.encoding" value="GBK"/>	
	 <include file="struts_1.xml"/>
</struts>

struts_1.xml

<?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.2.dtd">
<struts>
	<constant name="struts.custom.i18n.resources"
		value="messageResource"/>
	<constant name="struts.i18n.encoding" value="GBK"/>	
	<package name="js.a"  extends="struts-default" namespace="/10">
		<!-- 应用所需使用的拦截器都在该元素下配置 -->
		<interceptors>
			<!-- 配置mysimple拦截器 -->
			<interceptor name="mysimple" class="js.a.SimpleInterceptor">
				<!-- 为拦截器指定参数值 -->
				<param name="name">简单拦截器</param>
			</interceptor>
		</interceptors>
		<action name="login" class="js.a.LoginAction">
			<result name="error">/10/error.jsp</result>
			<result name="success">/10/welcome.jsp</result> 
			<!-- 拦截器一般配置在result元素之后! -->
			<!-- 配置系统的默认拦截器 -->
			<interceptor-ref name="defaultStack"/>
			<!-- 应用自定义的mysimple拦截器 -->
			<interceptor-ref name="mysimple">
				<param name="name">改名后的拦截器</param>
			</interceptor-ref>
		</action>
		<action name="">
			<result>.</result>
		</action>
	</package>
</struts>

 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_3_0.xsd" id="WebApp_ID" version="3.0">
	<display-name>struts2</display-name>
	<welcome-file-list> 
	  <welcome-file>index.jsp</welcome-file>
	</welcome-file-list>  
    <filter>  
        <filter-name>struts2</filter-name>  
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
    </filter>  
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

 login.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>登录页面</title>
</head>
<body>
<form action="login.action" method="post">
<table align="center">
	<caption><h3>用户登录</h3></caption>
	<tr>
		<td>用户名:<input type="text" name="username"/></td>
	</tr>
	<tr>
		<td>密码:<input type="text" name="password"/></td>
	</tr>
	<tr align="center">
		<td><input type="submit" value="登录"/>
			<input type="reset" value="重填" /></td>
	</tr>
</table>
</form>
</body>
</html>

 error.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>错误页面</title>
</head>
<body>
	您不能登录!
</body>
</html>

welcome.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>成功页面</title>
</head>
<body>
	您已经登录!
</body>
</html>

 index.jsp

<s:a href="" onclick="newWin('10/login.jsp');" cssStyle="cursor: hand;">login.jsp</s:a>
 

4.2  使用拦截器

以下所有代码都基于 4.1

 

使用拦截器需要 2 个步骤:

① 通过 <interceptor ../> 元素来定义拦截器

② 通过 <interceptor-ref ../> 元素来使用拦截器

 

4.1 中的 struts_1.xml

注意: 如果为 Action 指定了一个拦截器,则系统默认的拦截器栈将会失去作用。为了继续使用默认拦截器,所以上面配置文件中手动应用了默认拦截器。

 

4.3 拦截器和 Struts 2 插件的关系

扩展 Struts 2 的重要方式 : 插件,通过使用插件可以极好地扩充 Struts 2 的功能,在 Struts 2 项目的目录里,可以看到大量名为 struts2-xxx-plugin-2.2.jar 的文件,这些文件都是 Struts 2 的插件文件


Struts 2 的拦截器可用于完成各种细粒度的通用 “小功能” ,当我们需要为 Struts 2 扩展新功能时,也可能需要增加新的通用功能,这时候就需要开发自己的拦截器

 

当开发者开发了自己的拦截器之后,还必须配置拦截器,通常我们不可能修改 Struts 2 struts-default.xml ,而通用功能的拦截器也不应该在应用相关的 struts.xml 文件中配置。这就需要在 Struts 2 插件的 struts-plugin.xml 文件中配置拦截器了

 

例如: struts2-rest-plugin-2.2.1.jar 文件,包含了一个 struts-plugin.xml 文件:

 

struts-plugin.xml

<?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>
    <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="rest" class="org.apache.struts2.rest.RestActionProxyFactory" />
	<bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="rest" class="org.apache.struts2.rest.RestActionMapper" />

	<bean type="org.apache.struts2.rest.ContentTypeHandlerManager" class="org.apache.struts2.rest.DefaultContentTypeHandlerManager" />

    <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="xml" class="org.apache.struts2.rest.handler.XStreamHandler" />
    <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="json" class="org.apache.struts2.rest.handler.JsonLibHandler" />
    <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="html" class="org.apache.struts2.rest.handler.HtmlHandler" />
    <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="x-www-form-urlencoded" class="org.apache.struts2.rest.handler.FormUrlEncodedHandler" />
    <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="multipart/form-data" class="org.apache.struts2.rest.handler.MultipartFormDataHandler" />

    <constant name="struts.actionProxyFactory" value="rest" />
    <constant name="struts.rest.defaultExtension" value="xhtml" />
    <constant name="struts.mapper.class" value="rest" />
    <constant name="struts.mapper.idParameterName" value="id" />
    <constant name="struts.action.extension" value="xhtml,,xml,json" />

    <package name="rest-default" extends="struts-default">
        <result-types>
            <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult">
                <param name="statusCode">303</param>
            </result-type>
            <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult">
                <param name="statusCode">303</param>
            </result-type>
        </result-types>
        <interceptors>
            <!-- 配置 Struts 2 REST 插件的拦截器 -->
            <interceptor name="rest" class="org.apache.struts2.rest.ContentTypeInterceptor"/>
            <interceptor name="restWorkflow" class="org.apache.struts2.rest.RestWorkflowInterceptor"/>
            <interceptor name="messages" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
            <interceptor-stack name="restDefaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="messages">
                    <param name="operationMode">AUTOMATIC</param>
                </interceptor-ref>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="debugging"/>
                <interceptor-ref name="profiling"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven">
                    <param name="refreshModelBeforeResult">true</param>
                </interceptor-ref>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="params">
                  <param name="excludeParams">dojo\..*</param>
                </interceptor-ref>
                <interceptor-ref name="rest" />
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse,index,show,edit,editNew</param>
                </interceptor-ref>
                <interceptor-ref name="restWorkflow">
                    <param name="excludeMethods">input,back,cancel,browse,index,show,edit,editNew</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 配置默认的拦截器栈引用 -->
        <default-interceptor-ref name="restDefaultStack"/>
        <default-class-ref class="org.apache.struts2.rest.RestActionSupport"/>
    </package>
</struts>
 

通过上面配置文件可以看出 : 当需要为 Struts 2 扩展新功能时, Struts 2 插件是外在组织形式,而新增的拦截器则用于完成通用的核心功能,而 Struts 2 插件则负责组织这些新增的拦截器

 

五、 深入拦截器编程

拦截器的配置离不开 <interceptor .../> <interceptor-ref .../> <interceptor-stack .../> ,但对于拦截器的深入编程方面,还有一些值得注意的地方

5.1  拦截方法的拦截器

   在默认情况下,如果为某个 Action 定义了拦截器,则这个拦截器会拦截该 Action 内的所有方法。但在某些情况下,我们不想拦截所有方法,只需要拦截指定方法,此时,就需要使用 Struts 2 拦截器的方法过滤特性

 

   为了实现方法过滤特性, 需要使用一个 MethodFilterInterceptor 类,该类是 AbstractInterceptor 类的子类。如果用户需要自己实现的拦截器支持方法过滤特性,则应该继承 MethodFilterInterceptor


    MethodFilterInterceptor 类重写了  AbstractInterceptor 类的 intercept(ActionInvocation invocation) ,但提供了一个 doIntercept(ActionInvocation invocation) 抽象方法。 MethodFilterInterceptor intercept 已经实现了对 Action 的拦截行为(只实现了方法过滤的逻辑),但真正的拦截逻辑还需要开发者提供,也就是通过回调 doIntercept 方法实现。 因此用户应该重写 doIntercept(ActionInvocation invocation)

 

例如 :

MyFilterInterceptor

package js.a;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import java.util.*;

//方法过滤的拦截器,应该继承MethodFilterInterceptor抽象类
public class MyFilterInterceptor extends MethodFilterInterceptor {
    // 简单拦截器的名字
    private String name;

    // 为该简单拦截器设置名字的setter方法
    public void setName(String name) {
        this.name = name;
    }

    // 重写doIntercept方法,实现对Action的拦截逻辑
    public String doIntercept(ActionInvocation invocation) throws Exception {
        // 取得被拦截的Action实例
        LoginActionMy action = (LoginActionMy) invocation.getAction();
        // 打印执行开始的时间
        System.out.println(name + " 拦截器的动作---------" + "开始执行登录Action的时间为:"
            + new Date());
        // 取得开始执行Action的时间
        long start = System.currentTimeMillis();
        // 执行该拦截器的后一个拦截器,或者直接指定Action的execute方法
        String result = invocation.invoke();
        // 打印执行结束的时间
        System.out.println(name + " 拦截器的动作---------" + "执行完登录Action的时间为:"
            + new Date());
        long end = System.currentTimeMillis();
        // 打印执行该Action所花费的时间
        System.out.println(name + " 拦截器的动作---------" + "执行完该Action的事件为"
            + (end - start) + "毫秒");
        return result;
    }
}

方法过滤的拦截器与实现普通拦截器并没有太大区别,只要注意 2 个地方 :  实现方法过滤的拦截器需要继承 MethodFilterInterceptor 抽象类,并且重写 doIntercept 方法定义对 Action 的拦截逻辑

 

 在 MethodFilterInterceptor 抽象类中,额外增加 2 个方法:

 ● public void setExcludeMethods(String excludeMethods) : 排除需要过滤的方法 -----> 设置方法 “黑名单” ,所有在 excludMethods 字符串中列出的方法都不会被拦截

 ● public void setIncludeMethods(String includeMethods) : 设置需要过滤的方法 -----> 设置方法 “白名单” ,所有在 includeMehods 字符串中列出的方法都会被拦截

 

注意 :  如果一个方法同时在 excludeMethods includeMethods 中列出,则该方法会被拦截

 

因为 MethodFilterInterceptor 类包含如上 2 个方法,则该拦截器的子类也会获得这 2 个方法,可以在 struts.xml 中指定需要被拦截或者不需要被拦截的方法

 

 LoginActionMy

package js.a;

import com.opensymphony.xwork2.ActionSupport;

public class LoginActionMy extends ActionSupport {
    private String username;

    private String password;

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public String execute() throws Exception {
        System.out.println("进入execute方法执行体..........");
        Thread.sleep(1500);
        if (getUsername().equals("crazyit") && getPassword().equals("leegang")) {
            return SUCCESS;
        } else {
            return ERROR;
        }
    }

}

struts.xml

<?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.2.dtd">
<struts>
	<constant name="struts.custom.i18n.resources" 
		value="globalMessages"/>
	<constant name="struts.i18n.encoding" value="GBK"/>

	<package name="lee" extends="struts-default">
		<interceptors>
			<interceptor name="myfilter" class="js.a.MyFilterInterceptor">
				<param name="name">方法过滤拦截器</param>
			</interceptor>
		</interceptors>

              <action name="loginMy" class="js.a.LoginActionMy">
			<result name="error">/10/erroMy.jsp</result>
			<result name="success">/10/welcomeMy.jsp</result>
			<!-- 拦截器一般配置在result元素之后! -->
			<interceptor-ref name="defaultStack"/>
			<interceptor-ref name="myfilter">
				<param name="name">改名后的方法过滤拦截器</param>
                                 <!-- 不被拦截的方法 -->
       			        <param name="excludeMethods">execute,haha</param>
                                  <!-- 被拦截的方法 -->
			         <param name="includeMethods">execute</param>
			</interceptor-ref>
		</action>
		<action name="">
			<result>.</result>
		</action>
	</package>
</struts>

 同时指定多个方法,可以用 (,)隔开

 excludeMethods 参数指定了 execute 和 haha 方法不需要被拦截,又通过 includeMethods 参数指定了 execute 方法需要拦截,两者冲突,以 includeMethods 参数指定的为准,即拦截器会拦截 execute 方法


Struts 2 中提供了这种方法过滤的拦截器有如下几个:

● TokenInterceptor

● TokenSessionStoreInterceptor

● DefaultWorkflowInterceptor

● ValidationInterceptor

 

loginMy.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>登录页面</title>
</head>
<body>
<form action="loginMy.action" method="post">
<table align="center">
	<caption><h3>用户登录</h3></caption>
	<tr>
		<td>用户名:<input type="text" name="username"/></td>
	</tr>
	<tr>
		<td>密码:<input type="text" name="password"/></td>
	</tr>
	<tr align="center">
		<td><input type="submit" value="登录"/>
			<input type="reset" value="重填" /></td>
	</tr>
</table>
</form>
</body>
</html>
 

welcomeMy.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>成功页面</title>
</head>
<body>
	您已经登录!
</body>
</html>
 

erroMy.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>错误页面</title>
</head>
<body>
	您不能登录!
</body>
</html>
 
<s:a href="" onclick="newWin('10/loginMy.jsp');" cssStyle="cursor: hand;">loginMy.jsp</s:a>
 

5.2  拦截器的执行顺序

以下代码基于 4.1

 随着系统中配置拦截器的顺序的不同,系统中执行拦截器的顺序也不一样。通常认为: 先配置的拦截器,会先获得执行的机会,但实际的情况则有些出入

 

struts.xml

<?xml version="1.0" encoding="GBK"?>
<!-- 指定Struts 2的配置文件的DTD信息 -->
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
	"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<!-- 通过常量配置Struts 2的国际化资源信息 -->
	<constant name="struts.custom.i18n.resources" value="globalMessages"/>
	<!-- 通过常量配置Struts 2所使用的解码集-->
	<constant name="struts.i18n.encoding" value="GBK"/>
	<!-- 配置本系统所使用的包 -->
	<package name="lee" extends="struts-default">
		<!-- 配置应用所使用的拦截器 -->
		<interceptors>
			<!-- 配置mysimple拦截器 -->
			<interceptor name="mysimple" class="lee.SimpleInterceptor">
				<!-- 为拦截器指定参数值 -->
				<param name="name">简单拦截器</param>
			</interceptor>
		</interceptors>
		<!-- 配置处理用户请求的Action -->
		<action name="login" class="lee.LoginAction">
			<!-- 配置结果映射 -->
			<result name="error">/error.jsp</result>
			<result name="success">/welcome.jsp</result>
			<!-- 拦截器一般配置在result元素之后! -->
			<interceptor-ref name="defaultStack"/>
			<!-- 下面的配置片段两次引用同一个拦截器 -->
			<interceptor-ref name="mysimple">
				<param name="name">第一个</param>
			</interceptor-ref>
			<interceptor-ref name="mysimple">
				<param name="name">第二个</param>
			</interceptor-ref>
		</action>
		<action name="">
			<result>.</result>
		</action>
	</package>
</struts>
 

从运行后台里显示内容可以得出结论: Action 的控制逻辑方法执行之前,位于拦截器链前面的拦截器将先发生作用;在 Action 的控制方法执行之后,位于拦截器链前面的拦截器将后发生作用

 

5.3 拦截结果的监听器

以下代码基于 5.1


  为了精确定义在 execute() 执行结束后,在处理物理资源转向之前的动作,需要使用拦截结果监听器,这个监听器是通过手动注册在拦截内部的

 

  实现拦截结果监听器,必须实现 PreResultListener 接口:

MyPreResultListener.java

package js.a;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.PreResultListener;

public class MyPreResultListener implements PreResultListener {
    // 定义在处理Result之前的行为
    public void beforeResult(ActionInvocation invocation, String resultCode) {
        // 打印出执行结果
        System.out.println("返回的逻辑视图为:" + resultCode);
    }
}

  resultCode 参数就是被拦截 Action execute()  返回值。
  虽然 beforeResult() 也获得 ActionInvocation 参数,但通过这个参数来控制 Action 已经没有用了,因为 execute() 已经执行结束

 

拦截器代码 BeforeResultInterceptor.java :

package js.a;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class BeforeResultInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        // 将一个拦截结果的监听器注册给该拦截器
        invocation.addPreResultListener(new MyPreResultListener());
        System.out.println("execute方法执行之前的拦截...");
        // 调用下一个拦截器,或者Action的执行方法
        String result = invocation.invoke();
        System.out.println("execute方法执行之后的拦截...");
        return result;
    }
}

  结果:

execute方法执行之前的拦截...
进入execute方法执行体..........
返回的逻辑视图为::error
execute方法执行之后的拦截...
 

   上面代码手动注册了一个拦截结果的监听器,该监听器中的 beforeResult() 肯定会在系统处理物理资源转向之前被执行,上面的拦截器也定义了需要在处理物理资源转向之前执行的代码
   定义在 MyPreResultListener 类中的 beforeResult() BeforeResultInterceptor 类中的 intercept() 中在 Result 之前执行的动作,更早执行。

 

struts.xml

<?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.2.dtd">
<struts>
	<constant name="struts.custom.i18n.resources"
		value="messageResource"/>
	<constant name="struts.i18n.encoding" value="GBK"/>	
	<package name="js.a"  extends="struts-default" namespace="/10">
		<!-- 应用所需使用的拦截器都在该元素下配置 -->
		<interceptors>			
			<interceptor name="resultInterceptor"	class="js.a.BeforeResultInterceptor"/>
		</interceptors>		
		<action name="loginA" class="js.a.LoginActionMy">
			<result name="error">/10/error.jsp</result>
			<result name="success">/10/welcome.jsp</result>
			<!-- 拦截器一般配置在result元素之后! -->
			<interceptor-ref name="defaultStack"/>
			<interceptor-ref name="resultInterceptor"/>
		</action>
		<action name="">
			<result>.</result>
		</action>
	</package>
</struts>

 LoginActionMy.java   在 5.1

 error.jsp,welcome.jsp 4.1

 

loginMy1.jsp

<body>
<form action="loginA.action" method="post">
<table align="center">
	<caption><h3>用户登录</h3></caption>
	<tr>
		<td>用户名:<input type="text" name="username"/></td>
	</tr>
	<tr>
		<td>密码:<input type="text" name="password"/></td>
	</tr>
	<tr align="center">
		<td><input type="submit" value="登录"/>
			<input type="reset" value="重填" /></td>
	</tr>
</table>
</form>
</body>
 <s:a href="" onclick="newWin('10/loginMy1.jsp');" cssStyle="cursor: hand;">loginMy1.jsp</s:a>

 

5.4  覆盖拦截器栈里特定拦截器的参数

以下代码基于 5.1

 

    拦截器栈中有多个拦截器,如果要覆盖该拦截器栈中某个拦截器的指定参数,需要在配置使用拦截器栈的地方 <interceptor-ref /> 元素中使用 <param/> 元素来传入参数,在 <param /> 中指定参数名时应使用:“拦截器名.参数名” 形式,这样才能让 Struts 2 明白我们想覆盖哪个拦截器的哪个参数

 

<?xml version="1.0" encoding="GBK"?>
<!-- 指定Struts 2的配置文件的DTD信息 -->
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
	"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<!-- 通过常量配置Struts 2的国际化资源信息 -->
	<constant name="struts.custom.i18n.resources"
		value="globalMessages"/>
	<!-- 通过常量配置Struts 2所使用的解码集-->
	<constant name="struts.i18n.encoding" value="GBK"/>
	<!-- 配置本系统所使用的包 -->
	<package name="lee" extends="struts-default">
		<!-- 配置应用所使用的拦截器 -->
		<interceptors>
			<!-- 配置mysimple拦截器 -->
			<interceptor name="mysimple" class="lee.SimpleInterceptor">
				<!-- 为拦截器指定参数值 -->
				<param name="name">简单拦截器</param>
			</interceptor>
			<!-- 配置第二个拦截器 -->
			<interceptor name="second" class="lee.SecondInterceptor"/>
			<!-- 配置名为my-stack的拦截器栈 -->
			<interceptor-stack name="my-stack">
				<!-- 配置拦截器栈内的第一个拦截器 -->
				<interceptor-ref name="mysimple">
					<param name="name">第一个</param>
				</interceptor-ref>
				<!-- 配置拦截器栈内的第二个拦截器 -->
				<interceptor-ref name="second">
					<param name="name">第二个</param>
				</interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<!-- 配置处理用户请求的Action -->
		<action name="login" class="lee.LoginAction">
			<!-- 配置结果映射 -->
			<result name="error">/error.jsp</result>
			<result name="success">/welcome.jsp</result>
			<!-- 拦截器一般配置在result元素之后! -->
			<interceptor-ref name="defaultStack"/>
			<!-- 应用上面的拦截器栈 -->
			<interceptor-ref name="my-stack">
				<!-- 覆盖指定拦截器的指定参数值 -->
				<param name="second.name">改名后的拦截器</param>
			</interceptor-ref>
		</action>
		<action name="">
			<result>.</result>
		</action>
	</package>
</struts>

 

  上面配置了一个名为 my-stack 的拦截器栈,并且包括 2 个拦截器,这 2 个拦截器分别引用 mysimple second 拦截器,并且覆盖了 mysimple 拦截器的默认参数
  在 login Action 中使用 my-stack 拦截器时,使用了 <param .../> 元素来覆盖了该拦截器栈里 second 拦截器的 name 参数 (second.name )

 

 

 

 

 

 

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    Struts2拦截器(Interceptor)

    Struts2拦截器(Interceptor) Struts2拦截器(Interceptor)

    Struts2拦截器及其用法详细说明

    在Struts2中,拦截器(Interceptors)扮演着核心角色,增强了框架的功能和灵活性。这篇文章将深入探讨Struts2拦截器的概念、工作原理以及如何在实际应用中使用它们。 **一、什么是Struts2拦截器** 拦截器是基于AOP...

    struts2 拦截器

    2. **拦截器链**:在Struts2中,多个拦截器可以形成一个拦截器链,每个拦截器按照定义的顺序依次执行。如果所有拦截器都允许Action执行,那么Action的结果将被传递到下一个拦截器,直到整个链执行完毕。 ### 二、...

    struts2 拦截器实例

    在Struts2中,拦截器(Interceptor)扮演着核心角色,它们允许开发者在Action执行前后插入自定义的逻辑,如日志、权限检查、事务管理等。现在我们将深入探讨Struts2的拦截器机制及其实例应用。 ### 一、Struts2拦截...

    详解Struts2拦截器

    ### Struts2拦截器详解 #### 一、Struts2拦截器概述 Struts2框架作为Java Web开发中的一种流行框架,其核心组件之一便是**拦截器**。拦截器不仅在Struts2中扮演着重要角色,更是整个框架灵活性与扩展性的基石。...

    Struts2拦截器.ppt

    Struts2拦截器.ppt Struts2拦截器.ppt Struts2拦截器.ppt

    struts2拦截器

    标题“struts2拦截器”指的是Struts2框架中的拦截器机制,这是一个关键的组件,可以让我们在不修改实际业务代码的情况下,实现对请求处理流程的扩展和定制。 描述中提到的“基于struts2的拦截器测试,实现了页面的...

    Struts2拦截器实现权限控制demo

    在这个“Struts2拦截器实现权限控制demo”中,我们将深入探讨如何利用拦截器来实现细粒度的用户权限管理。 首先,我们需要了解Struts2中的拦截器工作原理。拦截器是基于Java的动态代理模式实现的,它们按照配置的...

    Struts2 拦截器

    拦截器是Struts2框架的核心特性之一,它们扮演着处理请求、增强功能和实现业务逻辑的角色。在Struts2中,拦截器就像过滤器一样工作,通过链式调用在动作执行前后进行预处理和后处理。 首先,我们来理解一下拦截器的...

    struts2拦截器的使用方法

    #### 二、Struts2拦截器的工作原理 拦截器的工作原理是基于责任链模式。当用户发起一个请求时,这个请求会经过一系列拦截器的处理,这些拦截器构成了一个责任链。每个拦截器都有机会处理请求或继续传递请求到下一个...

    struts2拦截器应用小例子

    当请求到达控制器时,Struts2会依次调用这个栈中的拦截器,每个拦截器都有机会处理请求,然后决定是否将请求传递给下一个拦截器或直接返回响应。 创建一个简单的Struts2拦截器,你需要遵循以下步骤: 1. 创建拦截...

    Struts2拦截器原理分析

    拦截器是Struts2框架的核心组成部分,它们在请求处理流程中起到了关键的作用。在本文中,我们将深入探讨Struts2拦截器的工作原理。 ### 一、拦截器概念 拦截器是基于Java的动态代理机制实现的,它允许我们在Action...

    Struts2拦截器源程序

    在Struts2中,拦截器扮演着至关重要的角色,它们是实现MVC(Model-View-Controller)架构的关键组件之一。拦截器允许开发者在动作执行前后插入自定义逻辑,比如日志记录、权限检查、数据验证等,而无需修改核心业务...

    Struts2 拦截器注解(二十七)

    拦截器是Struts2框架的核心组件之一,它允许开发者在动作执行前后插入自定义逻辑,实现如权限验证、日志记录、性能优化等多种功能。在"Struts2 拦截器注解"这个主题中,我们将深入探讨如何利用注解来简化拦截器的...

    Struts2拦截器源码

    首先,理解拦截器的定义:拦截器是AOP(面向切面编程)的一个概念,在Struts2中,拦截器是基于Java的动态代理机制实现的。它们是一系列实现了`Interceptor`接口的类,可以在Action执行前后插入额外的行为。这些行为...

    struts2拦截器实现拦截不文明字迹

    拦截器是Struts2框架的一个重要组成部分,能够帮助开发者实现一些在请求处理前后执行的通用逻辑,如日志记录、权限验证、数据校验等。在本场景中,我们将探讨如何使用Struts2拦截器来实现对不文明字迹或者敏感词汇的...

    使用struts2拦截器对登陆权限验证

    在Struts2中,拦截器(Interceptor)扮演着至关重要的角色,它允许开发者在动作执行前后插入自定义逻辑,如日志记录、权限验证等。在本案例中,我们将深入探讨如何使用Struts2拦截器实现登录权限验证,同时结合...

    Struts2 拦截器的执行顺序(二十九)

    这篇博客“Struts2 拦截器的执行顺序(二十九)”可能探讨了Struts2拦截器链的工作原理和它们的执行顺序,这对于理解Struts2的内部机制至关重要。 首先,让我们深入理解Struts2的拦截器。拦截器是在Action调用前后...

    Struts2学习案例(拦截器)

    在本学习案例中,重点在于Struts2的拦截器(Interceptor)功能,这是Struts2的核心特性之一,它允许开发者在Action执行前后进行自定义处理,实现了灵活的业务逻辑控制和增强的功能。 首先,我们来理解一下什么是...

    创建自己struts2拦截器

    Struts2是一个强大的MVC框架,它通过使用拦截器(Interceptor)来实现业务逻辑与表现层的解耦,提供了一种灵活的扩展机制。在Struts2中,拦截器是AOP(面向切面编程)的一种实现,它可以监控、修改或增强方法调用的...

Global site tag (gtag.js) - Google Analytics