Struts2自带的logger拦截器只是打印出了Action所对应的URL以及执行的方法名称,这对实际开发来说是肯定不够的。实际开发中为了调试方便,要记录的信息比较多,通常需要把这次请求相关的几乎所有信息都打印出来,比如:
- 要访问哪个Action类
- 要访问这个Action类的哪个方法
- 打印出这次请求中所有的request中的parameter参数
- 这次请求最后跳转到哪个页面。
如果我们现在就要在拦截器中实现这样的功能,该怎么实现呢?
1)ActionInvocation接口
在实现拦截器的功能的时候,需要使用ActionInvocation接口,这个接口有很多的功能,这里并不打算全部讲到,只描述一下接下来我们要用到的功能,更多的功能请参见Struts2的API文档。
- getAction方法:返回这次请求准备执行的Action对象。
- getProxy方法:返回这次请求的ActionProxy对象,可以在这个对象上获得要运行Action的哪个方法。
- getInvocationContext方法:返回这个Action执行的上下文(ActionContext),可以在这个上下文对象中获取到大量的数据,比如请求的parameter值、session的值等等。
在ActionContext中取到的parameter值是一个Map<String,Object>,其中以String为key,以String[]为value。这个Map中记录了所有的request参数。 - getResult方法:返回Result运行之后代表结果的Result对象。
2)具体的LoggerInterceptor,示例代码如下:
package cn.javass.hello.struts2impl.action; import java.util.Map; import org.apache.struts2.dispatcher.ServletDispatcherResult; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.Result; import com.opensymphony.xwork2.interceptor.Interceptor; public class LoggerInterceptor implements Interceptor{ public void destroy() { } public void init() { } public String intercept(ActionInvocation invocation) throws Exception { System.out.println("=================begin================="); //找到运行的Action对象,并打印其类名 System.out.println("Action:"+invocation.getAction().getClass().getName()); //找到运行的ActionProxy对象,并打印其要运行的方法名 System.out.println("Method:"+invocation.getProxy().getMethod()); //找到这次请求的request中的parameter参数,并打印 Map<String, Object> params = invocation.getInvocationContext().getParameters(); for (String key:params.keySet()){ Object obj = params.get(key); if(obj instanceof String[]){ String[] arr = (String[]) obj; System.out.println("Param:"+key); for (String value:arr){ System.out.println(value); } } } //运行后续的拦截器、Action和Result String resultCode = invocation.invoke(); //在Action和Result运行之后,得到Result对象 //并且可以强制转换成ServletDispatcherResult,打印其下一个JSP的位置 Result rresult = invocation.getResult(); if (rresult instanceof ServletDispatcherResult){ ServletDispatcherResult result = (ServletDispatcherResult) rresult; System.out.println("JSP:"+result.getLastFinalLocation()); } System.out.println("=================end================="); return resultCode; } }
3)在struts.xml中配置和使用这个拦截器,示例如下:
<package name="helloworld" extends="struts-default"> <interceptors> <interceptor name="testInteceptor" class="cn.javass.hello.struts2impl.action.MyInterceptor"/> <interceptor name="myLogger" class="cn.javass.hello.struts2impl.action.LoggerInterceptor"/> <interceptor-stack name="myStack"> <interceptor-ref name="timer"/> <interceptor-ref name="myLogger"/> <interceptor-ref name="testInteceptor"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="myStack"/> <global-results> <result name="math-exception">/${folder}/error.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="math-exception" exception="java.lang.ArithmeticException"/> <exception-mapping result="math-exception" exception="java.lang.Exception"/> </global-exception-mappings> <action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction"> <result name="toWelcome">/${folder}/welcome.jsp</result> <result name="input">/${folder}/login.jsp</result> </action> </package>
4)测试一下,运行登录页面,填入用户名和密码,点击提交按钮。然后查看后台的输出,示例如下:
=================begin================= Action:cn.javass.hello.struts2impl.action.HelloWorldAction Method:execute Param:submitFlag login Param:account 212 Param:password 222222222222 在acton执行之前 用户输入的参数为===account=212,password=222222222222,submitFlag=login 在Result运行之后 JSP:/s2impl/welcome.jsp =================end================= 2014-5-18 21:37:37 com.opensymphony.xwork2.interceptor.TimerInterceptor info 信息: Executed action [//helloworldAction!execute] took 7 ms.