拦截器,在AOP(Aspect-OrientedProgramming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作,拦截是AOP的一种实现策略,那如何配置拦截器和自定义拦截器呢,其实在我们的“struts2-core”jar包中,有一个“struts-default.xml”文件,里面已经有了配置好的拦截器,我们只需要拿过来看它是怎么写的即可,如下代码:struts-default.xml
<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="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
<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="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
<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="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />
<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\..*</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 JSON validation stack -->
<interceptor-stack name="jsonValidationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="jsonValidation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
···········(后面太多,不写出来了,我们可以自己打开文件去看)
</interceptors>
好了,下面就是我们自定义拦截器和配置拦截器
(1)所有的Struts2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。该接口提供了三个方法:
-1) void init();在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。
-2) void destroy();该方法跟init()方法对应。在拦截器实例被销毁之前系统将回调该方法。
-3) String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。
但是,
继承类
com.opensymphony.xwork2.interceptor.AbstractInterceptor
是更简单的一种实现拦截器类的方式,因为此类提供了init()和destroy()方法的空实现,这样我 们只需要实现intercept()方法即可,这有点像适配器设计模式(
如果现在一个类要实现一个接口,而该子类又不希望实现接口中所有的抽象方法,那么此时就在中间加一个 抽象类,用抽象类去实现接口的全部抽象方法,再在使用的类去继承抽象类,把一些该用的方法继承,不用的方法不继承,此种设计模式就称为适配器设计模式)
这里,我们就继承抽象类,如下
LoginInterceptor.java
package com.zhuimeng.interceptor;
import java.util.Map;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* 自定义拦截器继承AbstractInterceptor抽象类
*/
public class LoginInterceptor extends AbstractInterceptor {
/*
* (non-Javadoc)
* @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
*/
@Override
public String intercept(ActionInvocation arg0) throws Exception {
System.out.println("我是LoginInterceptor自定义拦截器");
// 将所有session中的属性保存在Map集合里
Map map = arg0.getInvocationContext().getSession();
if (map.get("username") != null) {
// 执行相应的Action
return arg0.invoke();
} else {
// 跳转到登陆页去(login.jsp)
return ActionSupport.LOGIN;
}
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#destroy()
*/
@Override
public void destroy() {
super.destroy();
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#init()
*/
@Override
public void init() {
super.init();
}
}
(2)现在自定义好了拦截器,那就必须要在struts.xml文件配置,才会起作用,如下
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.0.dtd">
<struts>
<package name="output" namespace="/" extends="struts-default">
<!-- 配置拦截器栈 -->
<interceptors>
<!-- 定义拦截器 -->
<interceptor name="login" class="com.zhuimeng.interceptor.LoginInterceptor"/>
</interceptors>
<action name="output" class="com.zhuimeng.struts2.action.OutputAction">
<result name="login">/login.jsp</result>
<!-- 声明好的拦截器放到action中,一般配置在result之后 -->
<interceptor-ref name="login"></interceptor-ref>
</action>
</package>
</struts>
(3)前台页面,前台页面就简单多了,往session对象里存放了一些信息,
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>login.jsp</title>
</head>
<body>
<% session.setAttribute("username","HELLO"); %>
hello,I am jsp
</body>
</html>
如果进来访问的话:
http://localhost:8080/interceptor/output.action,控制台出现的结果则是->
我是LoginInterceptor自定义拦截器
并没有输出action中的信息,原因就是拦截器中的intercept方法返回的是
ActionSupport.LOGIN;很显然,struts.xml文件找到result节点就已经回到jsp页面去了
如果再次访问的话:
http://localhost:8080/interceptor/output.action,控制台出现的结果则是->
我是LoginInterceptor自定义拦截器
*********使用拦截器的Action**********
了
(4)拦截器栈:就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
我们也用具体的代码去理解,如果现在要求action使用多个拦截器的话,改怎么做呢?
无非就是在定义一个拦截器类,如下:
TestInterceptor.java
package com.zhuimeng.struts2.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* 使用拦截器的Action
*/
public class OutputAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("*********使用拦截器的Action**********");
return "login";
}
}
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.0.dtd">
<struts>
<package name="output" namespace="/" extends="struts-default">
<!-- 配置拦截器栈 -->
<interceptors>
<!-- 定义拦截器 -->
<interceptor name="login" class="com.zhuimeng.interceptor.LoginInterceptor"/>
<interceptor name="test" class="com.zhuimeng.interceptor.TestInterceptor"/>
<!-- 定义拦截器栈:将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器栈的拦截器就会按其之前定义的顺序被调用 -->
<interceptor-stack name="mystack">
<interceptor-ref name="login"/>
<interceptor-ref name="test"/>
</interceptor-stack>
</interceptors>
<action name="output" class="com.zhuimeng.struts2.action.OutputAction">
<result name="login">/login.jsp</result>
<!-- 声明好的拦截器放到action中,一般配置在result之后 -->
<interceptor-ref name="mystack"></interceptor-ref>
</action>
</package>
</struts>
如上述的配置,我在调用action之前,首先经过拦截器,拦截器的顺序则为:login->test,所以,当在浏览器中输入:
http://localhost:8080/struts2_13_interceptor/output.action的时候,控制台出现的结果则是
我是LoginInterceptor自定义拦截器
TimerInterceptor
*********使用拦截器的Action**********