Struts配置详解

一、Stuts的元素

1 web.xml

       任何一个web应用程序都是基于请求响应模式进行构建的,所以无论采用哪种MVC框架,都离不开web.xml文件的配置.换句话说,web.xml并不是Struts2框架特有的文件,只有在Web应用中配置了web.xml文件,MVC框架才能真正地与Web应用融合起来.因此,web.xml文件是所有JavaWeb应用程序都需要的核心文件.

       Struts2框架需要在web.xml中配置其核心控制器—StrutsPrepareAndExecuteFilter,用于对框架进行初始化,以及处理所有的请求.

  StrutsPrepareAndExecuteFilter可以包含一些初始化参数,经常使用的如config——要加载的XML形式的配置文件列表(多个配置文件以逗号分隔,) 如果没有设置这个参数,Struts2框架将默认加载struts-default.xml,struts-plugin.xml和struts.xml.

       StrutsPrepareAndExecuteFilter作为一个Filter在Web应用中运行,它负责拦截所有的用户请求,当用户请求到达时,该Filter会过滤用户请求.如果用户请求以action结尾,该请求将被传递到Struts2框架进行处理.

2 Action

      实际上,在MVC框架中,控制器是由两个部分组成,分别如下:

  • 核心过滤器(Filter):用于拦截用户请求,对请求进行处理
  • 业务控制器(Action):调用相应的Model类实现业务处理,返回结果.

       对于开发人员来说,使用Struts2框架,主要的编码工作就是编写Action类,而自定义的Action需要实现com.opensymphony.xwork2.Action接口和继承com.opensymphony.xwork2.ActionSupport类,Struts2并不要求编写的Action类一定要实现Action接口,可以编写一个普通的Java类作为Action类,只要该类含有一个返回字符串的无参的public方法即可.

       在实际开发中,Action类通常都继承自Struts2提供的com.opensymphony.xwork2.ActionSupport类,以便简化开发.

3 Result

       result元素的作用是实现结果视图的调用,并决定视图以哪种形式展现给客户端.简单地说,就是用来设定在Action处理结束后,系统下一步将要做什么.

       Action类在处理完用户操作后,会返回一个处理结果.这个结果是一个简单字符串,框架根据这个字符串选择对应的Result,所以我们又将其称为逻辑视图名称.这个逻辑视图名由result元素的name属性来表示.result元素的值用来指定这个逻辑视图对应的物理视图资源的位置.需要特别指出的是,逻辑视图名称只有与物理视图资源联系在一起,才能发挥作用,所以必须要在配置文件中设置二者之间的对应关系.

       通过对Struts2执行过程的分析,可以发现Struts2应用的整个过程都是按照请求/响应的过程执行的,如下图:

1)     当Web服务器接收到请求之后,将请求交由web.xml中配置的struts2框架的核心过滤器StrutsPrepareAndExecuteFilter.

2)     由StrutsPrepareAndExecuteFilter确定请求对应的Action(业务控制器)

3)     框架根据Action返回的结果字符串,由StrutsPrepareAndExecuteFilter选择对应的result,将结果呈现给用户.

二、 Struts2的配置文件 struts.xml

1.  constant元素

        constant元素用于配置常量,通过常量的配置,可以改变Struts2框架的一些行为,从而满足不同应用的需求.constant元素包含两个属性:其中name属性表示常量的名称,value表示常量的值.例如:

<constant name="struts.configuration.xml.reload" value="true" />

 

Struts2默认的常量配置在default.properties文件中,我们可以在struts.xml文件中进行修改:

常用的常量配置:

<!-- 常用的常量设置 -->
    <!--指定默认编码,作用于HttpServletRequest的setCharacterEncoding() 方法 -->
    <constant name="struts.i18n.encoding" value="UTF-8" />
    
    <!--设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
    <constant name="struts.serve.static.browserCache" value="false" />

    <!--设置struts配置文件修改后,系统是否自动重新加载该文件,,默认为false(生产环境下使用) ,开发阶段最好打开 -->
    <constant name="struts.configuration.xml.reload" value="true" />

    <!--开发模式下使用,这样可以打印详细的错误信息 -->
    <constant name="struts.devMode" value="true" />

    <!--默认的视图主题, 该Struts标签的样式 -->
    <constant name="struts.ui.theme" value="simple" />

    <!--与spring整合时,指定由spring负责action对象的创建 -->
    <constant name="struts.objectFactory" value="spring" />

    <!--该属性设置Struts2是否支持动态方法调用,该属性的默认值是true,如果需要关闭动态方法的调用,属性为false -->
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />

    <!--上传文件的大小限制 -->
    <constant name="struts.multipart.maxSize" value="10240000" />

    <!-- 指定需要Struts2处理的请求后缀: 设置常量“struts.action.extension”进行修改, 多个后缀名,用逗号隔开 -->
    <constant name="struts.action.extension" value="do,action" />

2 package元素

<package name="default" namespace="/" extends="struts-default">

Struts2框架会把action,result等元素组织在一个名为package(包)的逻辑单元中.Struts的package很想java中的包,但与java包不同的是,Struts2中的包可以”继承”已经定义好的包,

我们自定义的package要直接或间接的继承 struts-default的包.

       package的属性:

  • name 属性:为必需并且唯一的,用来指定包的名称,便于被其他包继承
  • extends属性类似Java的extends关键字,指定继承那个包
  • namespace是一个可选属性,该属性定义该包中action的命名空间,如果没有设置该属性,则action被放入默认命名空间中.Struts2空间使用action的名称和它所在包的命名空间来标识一个action,默认的命名空间用””表示,也可以使用”/”定义一个根命名空间,注意两者是有区别的.如果请求Web应用程序路径下的action,则框架在根命名空间中查找对应的action.

3.action元素

对于Struts2应用的开发者而言,Action才是应用的核心,开发者需要提供大量的Action类,并在struts.xml文件中配置Action.Action主要三个作用:

        1.action最重要的作用是为给定的请求封装需要做的实际工作(调用特定的业务处理类);

        2.为数据的转移提供场所

     3.Action必须帮助框架决定由哪个结果呈现请求响应

Action元素的属性:

  1.method属性

    在之前的程序中,每实现一个功能都会去创建一个Action.并且完成相应的方法,那么是否可以在同一个Action中实现不同的功能呢?答案是可以的,那我们就需要使用到

   action元素的method属性实现在同一个Action中处理不同的请求。  

package org.suke.struts.web.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 一个Action可以包含多个请求处理方法
 * @author Administrator
 *
 */
public class UserAction extends ActionSupport {
    
    /**
     * 处理登录请求的方法
     * @return
     */
    public String login(){
        return SUCCESS;
    }
    
    /**
     * 处理注册请求的方法
     * @return
     */
    public String register(){
        
        return SUCCESS;
    }
}

   struts.xml的配置

  

    在上面的配置文件中,可以看到配置文件中分别定义了两个action元素,每个action元素的name属性是不同的,但是其指向的实现类的引用却是相同的.那么,Struts2在接收请求后通过method属性,

   确定该执行同一个Action中哪一个方法,也就是说,如果用户请求的是login.action,那么久调用UserAction的login()方法,如果是register.action,则调用register()方法。

2.动态调用DMI:

  不使用method实现统一.

<action name="userAction" class="org.suke.struts.web.action.UserAction">
            <result name="success">/index.jsp</result>
</action>

  然后再在index.jsp中定义如下链接:

<a href="<%=path %>/userAction!login.action">登录</a><br>
<a href="<%=path %>/userAction!register.action ">注册</a><br>

  注意查看上面的链接地址,它们都是针对UserAction,然后再加地上“!+UserAction中相应的方法名”,最后再写上.action即可以访问到统一页面index.jsp。这样做虽然能减少页面,

  但是由于它们实质用到的是同一个Action,所以这就意味着我们要使用的拦截器相同,相同的跳转result。实际中这种方式很少使用,在此略作了解。

  如果不想使用动态方法调用,我们可以通过常量来关闭,即在struts.xml中增加如下配置:

<constant name="struts.enable.DynamicMethodInvocation" value="false"/>

 

3 .Action的通配符的使用

  在配置<action../>元素时,需要指定name,class和method属性,其中name属性支持通配符,然后可以在method属性使用表达式,通配符用”* ”表示.表示匹配任意的字符串。

<action name="*User" class="org.suke.struts.web.action.UserAction" method="{1}">
            <result name="success">/{1}.jsp</result>
        </action>

 

  在action元素的name属性中使用星号,允许这个Action匹配所有以User结束的URI,如loginUser.action.配置该action元素时,还指定了method属性,该属性使用一个表达式{1},

  该表达式的值就是name属性值中第一个*的值.例如,当请求为loginUser.action时,通配符匹配的是login,那么这个值将替换{1},最终请求loginUser.action,将由UserAction的login()方法执行。

4. 配置默认的Action

  如果请求一个不存在的Action,那么结果将会在页面上呈现HTTP404错误,为了解决这个问题.Struts2框架允许指定一个默认的Action,即如果没有一个Action匹配请求,那么默认的Action被执行.

<!-- 使用默认的action -->
        <default-action-ref name="defaultAction"></default-action-ref>
        <!-- 配置默认的action -->
        <action name="defaultAction">
            <result>/error.jsp</result>
        </action>

 

5. Result的配置

  1.Result的常用结果类型

以上对type类型作简要的说明,下面来看实例:当一个Action处理后要返回的Result是另一个Action时,作如何配置,关键就是配置type类型。

步骤一:建立两个Action:TestAction、Test2Action
步骤二:web.xml配置省略。struts.xml主要配置内容如下:

<package name="resultTest" extends="struts-default">
        <action name="test" class="com.asm.TestAction">
            <result name="success" type="chain">
                <param name="actionName">test2</param>
            </result>
        </action>

        <action name="test2" class="com.asm.Test2Action">
            <result name="success">/test2Suc.jsp</result>
        </action>    
</package>

说明:在名为“test”的action中,我们配置result元素的type类型值为chain,意为将继续把Action传递到下一个名为test2的Action中去,在test2.action中会把页面转向到test2Suc.jsp中去。

   在type类型为chain时,它的param有4个值可配,除了这里用到的name=”actionName”外(必须配置,否则报错),还有name=namespace|method|skipActions。

   其中namespace指定要转向到action的名字空间,由于此处是转到Action位于同一个namespace下,而namesapace的默认值the current namespace

   所以可以省略不写(需要说明的是如果要跳到别的名称空间的action中去,除了使用namespace指定外,还可以用:/要跳去action所在名称空间的值/要跳去的action的name值)。

        Method用于指定转向到一个目标action所调用的方法,默认是调用下一个action的execute方法,所以此处仍可以省略。

        SkipActions是一个可选的属性,一般不用。具体可以参看chain所对应类的api帮助。
        在本实例中,我们还在TestAction中设定一个username字段,并在execute方法执行为它赋了值,并在test2Suc.jsp中引用了此值。其实这种做法在web开发中还是很有用处,

   比如可以代替隐藏域。需要注意的是之所以在action的传递中能把设定的这个值保存下去,主要是因为转向都是服务器跳转。

        如果我们跳转时采取了客户端跳转,也就是重定向,比如在test2 action的result中指定type类型为redirect,要想传递参数可以在result指向的jsp页面中附加参数即可,我们可以在test2 action的result中写成:

<result name="success" type="redirect">/test2Suc.jsp?username=${username}</result> 

 

   随后在test2Suc.jsp页面中引用时会出现三个问题:

   1.EL表达式引用失效,(EL表达式应该使用${param.username}形式)。我们也可以使用<%=request.getParameter("username")%>获取参数值。

   2.由于在前面的TestAction中设定的值为中文,而附加到这里的uri请求的参数后面时会出现乱码问题。(可以使用URI编码再解码解决此问题)

   3.值栈取值失效:因为每一次request共享同一个值栈,所以服务器端的forward跳转也是能共享同一值栈得。但是着当test action执行后把请求交由test2 action时,

    test2 action采取的是redirect重定向到test2Suc.jsp页面,这时其实就是重发的一次request,所以在test action保存的值栈内容全部失效。这也就是为什么我们要附加参数的原因。

    而参数是保存在actionContext中,所以采用了#的方式来取出值。图示说明: 

  2.  全局结果

  之前我们配置的结果都在action元素的内部,这些结果不能被其他的Action使用,在一些情况下,多个Action可能需要访问同一个结果,这时需要配置全局结果来满足多个Action共享一个结果.

<!-- 配置全局的Result -->
        <global-results>
            <result name="success">/success.jsp</result>
            <result name="input" type="redirect">/login.jsp</result>
        </global-results>

   全局结果同样也使用result元素配置,与action配置result元素的区别在于:全局结果需要在global-results元素中嵌套result元素,如果在Action中的result元素名称与全局结果的名称相同时,

  Action的result元素将会覆盖全局result结果.也就是说:Action处理用户请求结束后,会先在本Action中的result结果中搜索域逻辑视图名队员的结果,

  只有当在Action中无法匹配与逻辑视图名对应的结果时,才会去寻找全局结果并执行,

 

posted @ 2017-12-15 20:41  365天小人物  阅读(2726)  评论(0编辑  收藏  举报