天天看点

解决自定义拦截器导致默认的拦截器不起作用的问题

在​​上篇文章​​中我们留下了这个问题。在这里我们一点一点的解决。

问题一

由于我们写了自己的拦截器,默认的拦截器不起作用了。

解决办法一

把默认拦截器加入到配置文件中
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- 开发者模式 -->
    <constant name="struts.devMode" value="true"></constant>
    <package name="user" extends="struts-default" namespace="/user">
        <!-- 声明自己定义的拦截器,名字以及对应的java类 -->
        <interceptors> 
            <interceptor name="myInterceptor" class="com.scx.web.intercepter.LoginIntercepter"></interceptor>
        </interceptors>
        <!-- 全局逻辑结果视图 -->
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <!-- 用户登录的操作方法 -->
        <action name="login" class="com.scx.web.action.UserAction" method="login">
            <result name="success" type="redirectAction">toMain</result>
        </action>
        <!-- 显示主页的操作方法 -->
        <action name="toMain" class="com.scx.web.action.UserAction" method="main">
            <!-- 默认拦截器配置进来 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <!-- 自定义拦截器配置进来 -->
            <interceptor-ref name="myInterceptor"></interceptor-ref>
            <result name="success">/main.jsp</result>
        </action>
        <!-- 显示另一个页面的操作方法 -->
        <action name="toOther" class="com.scx.web.action.UserAction" method="other">
            <!-- 默认拦截器配置进来 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <!-- 自定义拦截器配置进来 -->
            <interceptor-ref name="myInterceptor"></interceptor-ref>
            <result name="success">/other.jsp</result>
        </action>
    </package>
</struts>      

问题二

解决方法一中存在的问题:当有多个拦截器,多个action动作时,需要配置的地方太多。

解决办法二

抽取公共的包,把全局配置放入公共包中

每次我们在Struts.xml编写包时都会将其继承于struts-default,这是struts2核心jar包里面为我们提供的。

解决自定义拦截器导致默认的拦截器不起作用的问题

想去看的同学可以解压Struts2的核心包, 里面有struts-default.xml,打开就能看到,第128行。

这里的继承和javase里面的继承一样,我们当然也可以继承于自己新建的包,有个前提就是,我们新建的包一定要是抽象的,即未配置任何action动作。

一定要仔细看注释,否则可能看不懂。

简而言之就是:

  • 我们新建了一个名为my-default的package 继承于struts-default
  • 我们在my-default包里面配置我们的自定义拦截器栈myDefaultStack,引入自定义的拦截器和系统默认的拦截器栈
  • 在action动作的包继承于my-default。在主页和其它页面的action动作里添加我们自定义的拦截器栈myDefaultStack
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- 开发者模式 -->
    <constant name="struts.devMode" value="true"></constant>
    <package name="my-default" abstract="true" extends="struts-default">    
        <interceptors> 
            <!-- 声明自己定义的拦截器,名字以及对应的java类 -->
            <interceptor name="myInterceptor" class="com.scx.web.intercepter.LoginIntercepter"></interceptor>
            <!-- 自定义的拦截器栈 -->
            <interceptor-stack name="myDefaultStack">
                <!-- 配置自己定义的拦截器 -->
                <interceptor-ref name="myInterceptor"></interceptor-ref>
                <!-- 配置默认的拦截器栈 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 全局逻辑结果视图 -->
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
    </package>
    <!-- 继承于上面的my-default -->
    <package name="user" extends="my-default" namespace="/user">
        <!-- 用户登录的操作方法 -->
        <action name="login" class="com.scx.web.action.UserAction" method="login">
            <result name="success" type="redirectAction">toMain</result>
        </action>
        <!-- 显示主页的操作方法 -->
        <action name="toMain" class="com.scx.web.action.UserAction" method="main">
            <!-- 引入自定义的拦截器栈  name和上面我们自定义的拦截器栈名相对应-->
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result name="success">/main.jsp</result>
        </action>
        <!-- 显示另一个页面的操作方法 -->
        <action name="toOther" class="com.scx.web.action.UserAction" method="other">
            <!-- 引入自定义的拦截器栈  name和上面我们自定义的拦截器栈名相对应-->
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result name="success">/other.jsp</result>
        </action>
    </package>
</struts>      

这样似乎解决了很多拦截器的问题,但是还没解决很多action动作仍然需要配置的问题,到底能不能不配置呢?

问题三

解决方法二还没解决很多action动作仍然需要配置的问题,到底能不能不配置呢?

解决办法三

思路:我们在设置【开发模式】时,覆盖掉了一个default.properties中的常量,能不能把struts-default.xml中的默认拦截器栈的设置给覆盖掉呢?答案是可以的。

同样也是在struts-default.xml中可以找到这行代码

解决自定义拦截器导致默认的拦截器不起作用的问题
  • 在my-default包里面设置默认的拦截器栈
  • 删除解决方法二action里面配置的自定义拦截器栈

配置后的代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- 开发者模式 -->
    <constant name="struts.devMode" value="true"></constant>
    <package name="my-default" abstract="true" extends="struts-default">    
        <interceptors> 
            <!-- 声明自己定义的拦截器,名字以及对应的java类 -->
            <interceptor name="myInterceptor" class="com.scx.web.intercepter.LoginIntercepter"></interceptor>
            <!-- 自定义的拦截器栈 -->
            <interceptor-stack name="myDefaultStack">
                <!-- 配置自己定义的拦截器 -->
                <interceptor-ref name="myInterceptor"></interceptor-ref>
                <!-- 配置默认的拦截器栈 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 设置默认拦截器 -->
        <default-interceptor-ref name="myDefaultStack"/>
        <!-- 全局逻辑结果视图 -->
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>

    </package>
    <!-- 继承于上面的my-default -->
    <package name="user" extends="my-default" namespace="/user">
        <!-- 用户登录的操作方法 -->
        <action name="login" class="com.scx.web.action.UserAction" method="login">
            <result name="success" type="redirectAction">toMain</result>
        </action>
        <!-- 显示主页的操作方法 -->
        <action name="toMain" class="com.scx.web.action.UserAction" method="main">
            <result name="success">/main.jsp</result>
        </action>
        <!-- 显示另一个页面的操作方法 -->
        <action name="toOther" class="com.scx.web.action.UserAction" method="other">
            <result name="success">/other.jsp</result>
        </action>
    </package>
</struts>      

这样配置 似乎我们完成了我们的目标,无论有多少个自定义拦截器都可以配置到my-default包里面,无论都多少个action只要它继承于my-default就可以。可是你有没有发现,这样连我们的登录页面也被拦截了。

问题真是一个接着一个出现 。累觉不爱啊

解决自定义拦截器导致默认的拦截器不起作用的问题

问题四

解决方法三把我们的登录界面都被拦截了

解决办法四

需要通过AbstractInterceptor类的子类入手,通过查看发现,该类还有一个子类是抽象的
解决自定义拦截器导致默认的拦截器不起作用的问题
  • excludeMethods配置哪些动作方法不拦截
  • includeMethods配置那些动作方法拦截

    我们都可以在struts.xml中通过注入的方式进行配置。根据自己的需求为不同的参数注入。

所以我们在自定义拦截器时,还可以继承MethodFilterInterceptor并且重写doIntercept方法。
解决自定义拦截器导致默认的拦截器不起作用的问题
在struts.xml配置的部分代码如下
解决自定义拦截器导致默认的拦截器不起作用的问题

运行似乎没有问题。

还是有个问题 不知道大家有没有发现

我们是在my-default里面配置哪些方法需要拦截,哪些方法不需要拦截。但是在没有写动作类和动作方法之前,不确定方法名叫什么。

问题五

我们在声明时配置了哪些方法需要拦截,哪些方法不需要拦截。但是在没有写动作类和动作方法之前,不确定方法名叫什么。

解决办法五

我们可以在需要使用拦截器的时候给它注入参数。
解决自定义拦截器导致默认的拦截器不起作用的问题
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- 开发者模式 -->
    <constant name="struts.devMode" value="true"></constant>
    <package name="my-default" abstract="true" extends="struts-default">    
        <interceptors> 
            <!-- 声明自己定义的拦截器,名字以及对应的java类 -->
            <interceptor name="myInterceptor" class="com.scx.web.intercepter.LoginIntercepter"></interceptor>
            <!-- 自定义的拦截器栈 -->
            <interceptor-stack name="myDefaultStack">
                <!-- 配置自己定义的拦截器 -->
                <interceptor-ref name="myInterceptor"></interceptor-ref>
                <!-- 配置默认的拦截器栈 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 设置默认拦截器 -->
        <default-interceptor-ref name="myDefaultStack"/>
        <!-- 全局逻辑结果视图 -->
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>

    </package>
    <!-- 继承于上面的my-default -->
    <package name="user" extends="my-default" namespace="/user">
        <!-- 用户登录的操作方法 -->
        <action name="login" class="com.scx.web.action.UserAction" method="login">
            <interceptor-ref name="myDefaultStack">
                <!-- 在使用拦截器时给拦截器注入参数 -->
                <param name="myInteceptor.excludeMethods">login</param>
            </interceptor-ref>
            <result name="success" type="redirectAction">toMain</result>
        </action>
        <!-- 显示主页的操作方法 -->
        <action name="toMain" class="com.scx.web.action.UserAction" method="main">
            <result name="success">/main.jsp</result>
        </action>
        <!-- 显示另一个页面的操作方法 -->
        <action name="toOther" class="com.scx.web.action.UserAction" method="other">
            <result name="success">/other.jsp</result>
        </action>
    </package>
</struts>      

继续阅读