欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SSH开发模式——Struts2(第二小节)

程序员文章站 2022-06-30 08:45:33
上一小节已经学会了如何去搭建Struts2的开发环境,该篇博客我们继续深入Struts2,了解Struts2框架的拦截器。 首先对我们在web.xml文件配置的过滤器进行一个源码的分析。 在StrutsPrepareAndExecuteFilter源码中,有一个init()方法,它调用方法获得了一个 ......

上一小节已经学会了如何去搭建struts2的开发环境,该篇博客我们继续深入struts2,了解struts2框架的拦截器。

首先对我们在web.xml文件配置的过滤器进行一个源码的分析。
在strutsprepareandexecutefilter源码中,有一个init()方法,它调用方法获得了一个dispatcher对象,这就是我们要分析的关键了。进入到它的源码,在其init()方法中调用了init_traditionalxmlconfigurations()方法,该方法的源码如下:

    private void init_traditionalxmlconfigurations() {
        string configpaths = initparams.get("config");
        if (configpaths == null) {
            configpaths = default_configuration_paths;
        }
        string[] files = configpaths.split("\\s*[,]\\s*");
        for (string file : files) {
            if (file.endswith(".xml")) {
                if ("xwork.xml".equals(file)) {
                    configurationmanager.addcontainerprovider(createxmlconfigurationprovider(file, false));
                } else {
                    configurationmanager.addcontainerprovider(createstrutsxmlconfigurationprovider(file, false, servletcontext));
                }
            } else {
                throw new illegalargumentexception("invalid configuration file name");
            }
        }
    }

注意了,在这个方法里有这样一句代码,configpaths = default_configuration_paths;,关键就是这个字段,我们继续跟进。

    private static final string default_configuration_paths = "struts-default.xml,struts-plugin.xml,struts.xml";

看到这里你总该明白了吧,为什么新建的struts2的配置文件名字必须为struts.xml?为什么struts2的配置文件中package标签要继承struts-default?相信应该不用我解释了。

其实,过滤器的作用有很多,之前也有介绍,但是,如果把所有的任务都交给过滤器处理,那过滤器的负担将会非常重,过滤器的代码会非常多,也不符合我们低耦合,高内聚的设计思想。

我们假设要实现一个功能,在一个类中将该功能分为几个步骤。

class aa{
    第一步:
    第二步:
    第三步:
    第四步:
}

但是我们现在这样设计实现。

class a1{
    第一步:
}
class a2{
    第二步:
}
class a3{
    第三步:
}
class a4{
    第四步:
}

每个类只实现一步,然后直接调用四个类的方法即可。
这样有什么好处呢?这样四个步骤都不会相互影响,想单独调用某个步骤你可以很容易地实现。这就是分离关注的思想。把要处理的问题,分别用一个类来完成,每个类只完成一个功能。这样的一个类就叫 拦截器
那拦截器和过滤器有什么区别呢?
相同点:都是起拦截作用的。
不同点:过滤器是j2ee的标准,任何的一个程序都可以使用。
              拦截器是struts2框架的标准,不能离开struts2框架,必须依赖struts2框架使用。
              过滤器拦截的是web.xml配置文件,其它的拦截工作都交给了拦截器。
              执行顺序为过滤器先执行,拦截器后执行。

在struts-default.xml文件中,定义了很多的拦截器。

<!-- 
    interceptors:定义了struts2框架的拦截器
    *name:拦截器的名称,是唯一的
    *class:拦截器对应的action类的完整路径
 -->
        <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="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="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="annotationworkflow" class="com.opensymphony.xwork2.interceptor.annotations.annotationworkflowinterceptor" />
            <interceptor name="multiselect" class="org.apache.struts2.interceptor.multiselectinterceptor" />
       </interceptors>

拦截器非常的多,其中也有很多我们眼熟的关键字吧,cookie、params、i18n等等。
在拦截器定义的下面,又定义了很多的interceptor-stack标签,这些标签定义的是拦截器栈。它们有什么作用呢?
这里我只贴出一个默认的拦截器栈作讲解。

<!-- 
     interceptor-stack:拦截器栈
        *存放了上面定义的拦截器,拦截器栈相当于list集合,在这里存放的拦截器是有先后顺序的
        按照声明的顺序先后执行
-->
            <interceptor-stack name="defaultstack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletconfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedmodeldriven"/>
                <interceptor-ref name="modeldriven"/>
                <interceptor-ref name="fileupload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticparams"/>
                <interceptor-ref name="actionmappingparams"/>
                <interceptor-ref name="params">
                    <param name="excludeparams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(request|response)\..*,parameters\...*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionerror"/>
                <interceptor-ref name="validation">
                    <param name="excludemethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludemethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="debugging"/>
            </interceptor-stack>

至于它是否真的有执行顺序呢?我就不带大家验证了,大家可以找几个拦截器,然后在对应的类中打上断点,然后运行验证即可。

需要注意的是,程序默认执行的是defaultstack拦截器栈,那有没有人想为什么程序默认执行的是该拦截器栈,因为它的名字是defaultstack,所以就会执行它吗?显然,这里面是有原因的。我们往下阅读源码,找到了这样一句配置:<default-interceptor-ref name="defaultstack"/> ,它就是用来配置默认执行的拦截器栈的。
拦截器就先介绍到这里。
之前算是一个对struts2框架的入门,有很多地方大家可能都不太理解,因为要让大家能够迅速地了解这个框架,所以没有更深层次地去介绍,只是讲述了它的冰山一角。接下来,我们就要对struts2框架进行一个系统的学习,敬请期待吧。