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.