一、理解Struts2拦截器
1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.
2. 拦截器栈(Interceptor Stack)Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。
二、定义Struts2拦截器
1. InputAction.java
@Override public String execute() throws Exception{ if(!str1.equals("") && !str2.equals("")){ ActionContext context = ActionContext.getContext(); Map<String, Object> session = context.getSession(); session.put("str1", str1); session.put("str2", str2); System.out.println("action内部代码结束。"); return SUCCESS; }else{ return INPUT; } }
2. struts.xml配置
<interceptors> <interceptor name="checkLogin" class="StrutsDemo.LoginInterceptor"></interceptor> <interceptor-stack name="myInterceptorStack"> <interceptor-ref name="checkLogin"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors>
3. LoginInterceptor.java
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class LoginInterceptor extends AbstractInterceptor {
/**
*
*/
private static final long serialVersionUID = 5391150071862840190L;
@Override
public String intercept(ActionInvocation actioninvocation) throws Exception {
System.out.println("action执行前插入 代码");
final String result = actioninvocation.invoke();
System.out.println("action执行后插入 代码");
return result;
}
}
4. input.jsp
<form action="<%=request.getContextPath()%>/inputAction.do" method="post"> <input type="text" name="str1"> <input type="text" name="str2"> <input type="submit"> </form>
通过访问input.jsp我们在控制台可以看到如下打印内容:
action执行前插入 代码
action内部代码结束。
success
action执行后插入 代码
其中 actioninvocation.invoke(); 返回的是一个String的字符串,它返回的其实就是拦截器所拦截的action的excute()方法的结果。
三、拦截器的配置需要注意事项
struts.xml里的配置排列顺序:
result-types
interceptors
default-interceptor-ref
default-action-ref
default-class-ref
global-results
global-exception-mappings
action*(就是所有的action放到最后)
此处需要注意的是,如果为Action指定了一个拦截器,则系统默认的拦截器栈将会失去作用。
为了继续使用默认拦截器,所以上面配置文件中手动引入了默认拦截器:<interceptor-ref name="defaultStack"/>
四、拦截器结合注解的使用
@Override public String intercept(ActionInvocation arg0) throws Exception { QueryFilter filter = (QueryFilter) arg0.getStack().findValue("filter");//通过值栈查找当前action是否包含某个属性 // 没有通过filter进行查询的action,直接执行并返回 if (filter == null) return arg0.invoke(); ActionProxy proxy = arg0.getProxy(); String methodName = proxy.getMethod();//获取代理对象当前调用的方法名 Object action = proxy.getAction(); // 获取actio上的注解信息 Method method = action.getClass().getMethod(methodName); NeedDlLog needLog = method.getAnnotation(NeedDlLog.class); // 没有加注解NeedDlLog的action,直接执行并返回 if (needLog == null) return arg0.invoke(); // 获取注解的参数(下载报表名称),并作为日志信息的一部分输出 EDlModelType dlmType = needLog.value(); JSONObject value = new JSONObject(filter.getValue().toString()); value.append(DOWNLOAD_TITLE_KEY, dlmType.getDownloadTitle()); // log记录 logger.info("download-filter:" + value.toString()); return arg0.invoke(); }