Struts2 struts.xml文件配置

struts.xml文件配置详解

1、<include>
当系统变大后,会导致struts.xml内容非常多,这时就可以采用模块化的方式将不同的配置文件分散在不同的配置里面,
然后由struts.xml将它们统一的加载进来,比如struts_1.xml 、struts_2.xml 、struts_3.xml 三个文件,分别是针对不同模块的配置,
最后就可以由struts.xml统一将其整合起来,整合的方式就是把这它们包含进来即可。
<include file="struts_1.xml"/>
<include file="struts_2.xml"/>
<include file="struts_3.xml"/>
在struts_1.xml 或者struts_2.xml 中的配置方式与struts.xml 中的配置方式是一模一样的。
即它们顶部都必须有XML声明和DTD ,它们DTD都是相同的。
接下来是<struts/>根元素,即不能认为struts_1.xml 是被包含文件,便将顶部XML声明和DTD省略掉,这是不可以的。
最后由struts.xml统一引入,于是系统加载,便将struts_1.xml及struts_2.xml等的配置都加载到内存中。
这就相当于进行模块化的配置。对于大中型的系统来说,是不可避免的会使用模块化的配置方式的。
2、<constant>
常量属性的配置,用于改变Struts2框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成。
    1.<constant name="struts.i18n.encoding" value="UTF-8" />
    指定Web应用的默认编码集,相当于调用 HttpServletRequest的setCharacterEncoding方法。

    2.<constant name="struts.i18n.reload" value="false"/>
    该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发, 但在产品发布阶段应将该属性设置为false。

    3.<constant name="struts.custom.i18n.resources" value="application"/>
    该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开。

    4.<constant name="struts.action.extension" value="action" />
    该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。

    5.<constant name="struts.serve.static.browserCache " value="true" />
    设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭。

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

    7.<constant name="struts.configuration.files" value="struts-default.xml,struts-plugin.xml,struts.xml"/>
    该属性指定Struts 2框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,)隔开。该属性的默认值为struts- default.xml,struts-plugin.xml, struts.xml,看到该属性值,读者应该明白为什么Struts 2框架默认加载struts.xml文件了。

    8.<constant name="struts.configuration" value="org.apache.struts2.config.DefaultConfiguration"/>
    指定加载struts2配置文件管理器,默认为org.apache.struts2.config.DefaultConfiguration,开发者可以自定义配置文件管理器,该类要实现Configuration接口,可以自动加载struts2配置文件。

    8.<constant name="struts.continuations.package" value=""/>
    含有Actions的完整连续的package名称。

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

    11.<constant name="struts.serve.static.browserCache" value="false"/>
    该属性设置浏览器是否缓存静态内容。当应用处于开发阶段时,我们希望每次请求都获得服务器的最新响应,则可设置该属性为false。

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

    13.<constant name="struts.enable.SlashesInActionNames" value="false"/>
    该属性设置Struts 2是否允许在Action名中使用斜线,该属性的默认值是false。如果开发者希望允许在Action名中使用斜线,则可设置该属性为true。

    14.<constant name="struts.tag.altSyntax" value="true"/>
    该属性指定是否允许在Struts 2标签中使用表达式语法,因为通常都需要在标签中使用表达式语法,故此属性应该设置为true,该属性的默认值是true。

    15.<constant name="struts.devMode" value="false"/>
    该属性设置Struts 2应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。

    16.<constant name="struts.ui.theme" value="xhtml"/>
    该属性指定视图标签默认的视图主题,该属性的默认值是xhtml,可以为simple,xhtml或ajax。

    17.<constant name="struts.ui.templateDir" value="template"/>
    该属性指定视图主题所需要模板文件的位置,该属性的默认值是template,即默认加载template路径下的模板文件。

    18.<constant name="struts.ui.templateSuffix" value="ftl"/>
    该属性指定模板文件的后缀,该属性的默认属性值是ftl。该属性还允许使用ftl、vm或jsp,分别对应FreeMarker、 Velocity和JSP模板。

    19.<constant name="struts.velocity.configfile" value="velocity.properties"/>
    该属性指定Velocity框架所需的velocity.properties文件的位置。该属性的默认值为 velocity.properties。

    20.<constant name="struts.velocity.contexts" value=""/>
    该属性指定Velocity框架的Context位置,如果该框架有多个Context,则多个Context之间以英文逗号(,)隔开。

    21.<constant name="struts.velocity.toolboxlocation" value=""/>
    该属性指定Velocity框架的toolbox的位置。

    22.<constant name="struts.url.http.port" value="80"/>
    该属性指定Web应用所在的监听端口。该属性通常没有太大的用处,只是当Struts 2需要生成URL时(例如Url标签),该属性才提供Web应用的默认端口。

    23.<constant name="struts.url.https.port" value="443"/>
    该属性类似于struts.url.http.port属性的作用,区别是该属性指定的是Web应用的加密服务端口。

    24.<constant name="struts.url.includeParams" value="none|get|all"/>
    该属性指定Struts 2生成URL时是否包含请求参数。该属性接受none、get和all三个属性值,分别对应于不包含、仅包含GET类型请求参数和包含全部请求参数。

    25.<constant name="struts.dispatcher.parametersWorkaround" value="false"/>
    对于某些Java EE服务器,不支持HttpServlet Request调用getParameterMap()方法,此时可以设置该属性值为true来解决该问题。该属性的默认值是false。对于 WebLogic、Orion和OC4J服务器,通常应该设置该属性为true。

    26.<constant name="struts.freemarker.manager.classname" value=""/>
    该属性指定Struts 2使用的FreeMarker管理器。该属性的默认值是org.apache.struts2.views.freemarker.FreemarkerManager,这是 Struts 2内建的FreeMarker管理器。

    27.<constant name="struts.freemarker.wrapper.altMap" value="true"/>
    该属性只支持true和false两个属性值,默认值是true。通常无需修改该属性值。

    28.<cosntant name="struts.freemarker.templatesCache" value="false" />
    设置是否对freemarker的模板设置缓存,效果相当于把template拷贝到 WEB_APP/templates.

    29.<constant name="struts.xslt.nocache" value="false"/>
    该属性指定XSLT Result是否使用样式表缓存。当应用处于开发阶段时,该属性通常被设置为true;当应用处于产品使用阶段时,该属性通常被设置为false。

    30.<constant name="struts.custom.properties" value="application,org/apache/struts2/extension/custom
"/>
    指定Struts2应用加载用户自定义的属性文件,该自定义属性文件指定的属性不会覆盖struts.properties文件中指定的属性。如果需要加载多个自定义属性文件,多个自定义属性文件的文件名以英文逗号(,)隔开。(也就是说不要改写struts.properties!)
    31.<constant name="struts.locale" value="zh_CN"/>
    默认的国际化地区信息。

    32.<constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper"/>
    指定请求url与action映射器,默认为org.apache.struts2.dispatcher.mapper.DefaultActionMapper

    33.<cosntant name="struts.mapper.alwaysSelectFullNamespace" value="false" />
    设定是否一直在最后一个slash之前的任何位置选定namespace

    34.<constant name="struts.multipart.maxSize" value="2097152"/>
    multipart请求信息的最大尺寸(文件上传用,该属性指定Struts 2文件上传中整个请求内容允许的最大字节数)。

    35.<constant name="struts.multipart.parser" value="cos"/>
    该属性指定处理 MIME-type multipart/form-data,文件上传(cos、pell、jakarta)
    专为multipart请求信息使用的org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器接口(文件上传用)。

    36.<constant name="struts.multipart.saveDir" value="/tmpuploadfiles"/>
    指定上传文件时的临时目录,默认使用 javax.servlet.context.tempdir。

    37.<constant name="struts.objectFactory" value="spring" />
    该属性指定Struts 2中的Action由Spring容器创建。

    38.<constant name="struts.objectFactory.spring.autoWire" value="name"/>
     指定spring框架的装配模式,装配方式有: name, type, auto, and constructor (name 是默认装配模式)

    39.<constant name="struts.objectFactory.spring.useClassCache" value="true"/>
    该属性指定整合spring时,是否对bean进行缓存,值为true or false,默认为true。

    40.<cosntant name="struts.objectTypeDeterminer" value="tiger" />
    指定类型检查,包含tiger和notiger
3、<package>
package节点是整个配置的核心部分。每个package,从语义上讲,其实代表了每一个独立的模块。
在这个模块中,你可以定义隶属于这个模块的行为方式,而与其他的模块没有关系。
所以,每个package都有独立的interceptor、result-type和action的定义,绝大多数的Runtime配置定义都是通过package节点实现的。
接下来我们就来详细讨论一下package中的属性和子节点。
1. name
name属性为每个package设置一个唯一的标识,这个标识在所有的package定义中不能重复。
2. abstract
标识这个package的定义是一个抽象定义,也就是允许他仅包含声明式的定义,而不需要在package定义中包含action的定义。
3. extends
通过使用extends,你可以指定本package继承另外一个package的所有的配置。
当某个package继承了另外一个package的所有配置,那么你就无需对父package中已经声明过的配置定义做再次的定义。
同时,如果重复定义父package中已声明过的配置定义,那么这些重复定义声明将覆盖父package中的相关定义。
4. namespace
作用:对于action配置进行逻辑划分。
如果我们不为package节点指定namespace,Struts2默认使用一个空字符串作为默认的namespace。
当然,也可以使用"/"等字符串来表示namespace。 定义package命名空间 该命名空间影响到url的地址。
例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
Struts2在根据URL进行寻址的时候,使用以下的步骤:
1) 根据URL进行Namespace和ActionName的计算
2) 根据计算的得到的Namespace和ActionName查找package节点中相应配置
3) 如果查找失败,则查找Namespace为空,ActionName为整个URL的配置
4、<action>与<result>
Struts2的核心功能是action,对于开发人员来说,使用Struts2主要就是编写action,action类通常都要实现com.opensymphony.xwork2.Action接口,并实现该接口中的execute()方法。
Struts2并不是要求所有编写的action类都要实现Action接口,也可以直接编写一个普通的Java类作为action,只要实现一个返回类型为String的无参的public方法即可。
在实际开发中,action类很少直接实现Action接口,通常都是从com.opensymphony.xwork2.ActionSupport类继承,ActionSupport实现了Action接口和其他一些可选的接口,提供了输入验证,错误信息存取,以及国际化的支持,选择从ActionSupport继承,可以简化action的定义。
开发好action之后,好需要对action进行配置,以告诉Struts2框架,针对某个URL的请求应该交由哪个action进行处理。
1.Action映射:
  action映射是Struts2框架中的基本工作单元,action映射就是将一个请求URL(即action的名字)映射到一个action类,
  当一个请求匹配某个action的名字时,框架就使用这个映射来确定如何处理请求。
1.name action的名字,用于匹配URL(必须有)
2.class Action实现类的完整类名(非必须有)
3.method 执行Action类时调用的方法(非必须有)
4.convert 应用于action的类型转换的完整类名(非必须有)
        例如:
<action name="user" class="org.lesson05.UserAction">
<result name="success">/user.jsp</result>
</action>
2. method属性
在配置action时,我们可以通过action元素的method属性来指定action调用的方法,
所指定的方法,必须遵循与execute方法相同的格式。
在Struts2.xml文件中,我们可以为同一个action类配置不同的别名,并使用method属性。
在Struts.xml文件中为同一个Action类配置不同的别名
    <!-- 使用method属性 -->
<package name="methods" namespace="/" extends="struts-default">
<!-- 对应着MethodAction里面的execute方法 -->
<action name="list" class="org.lesson05.MethodAction">
    <result name="success">/Methods/list.jsp</result>
</action>
<!-- 对应着MethodAction里面的add方法 -->
<action name="add" class="org.lesson05.MethodAction" method="add">
    <result name="success">/Methods/add.jsp</result>
</action>
<!-- 对应着MethodAction里面的edit方法 -->
<action name="edit" class="org.lesson05.MethodAction" method="edit">
    <result name="success">/Methods/edit.jsp</result>
</action>
<!-- 对应着MethodAction里面的delete方法 -->
<action name="delete" class="org.lesson05.MethodAction" method="delete">
    <result name="success">/Methods/delete.jsp</result>
</action>
</package>
对应的MethodAction类,代码如下:
    importcom.opensymphony.xwork2.ActionSupport;
public class MethodAction extends ActionSupport
{

    @Override
    public String execute() throws Exception
    {
       return SUCCESS;
    }
  
    public String add() throws Exception
    {
       return SUCCESS;
    }
  
    public String edit() throws Exception
    {
       return SUCCESS;
    }
  
    public String delete() throws Exception
    {
       return SUCCESS;
    }
}
使用action的method属性可以任意指定处理请求的方法(只要该方法和execute方法具有相同的格式),
这样就可以在同一个类中完成相关的任务,而不需要去编写不同的Action类。
注意:Struts2在根据action元素的method属性查找方法时有两种途径:
1.查找与method属性值完全一致的方法.
2.查找doMethod()形式的方法.
3.动态方法调用:
另外一种无需配置就可以直接调用Action中的非execute方法的方式,是使用Struts2的动态方法调用。
动态方法调用是在action的名字中使用感叹号(!)来标识要调用的方法名,其语法格式为 actionName!methodName.action
   例如,我们配置了如下的action
   <action name="user" class="org.lesson05.UserAction">
    <result name="success">/Methods/list.jsp</result>
   </action>
当请求/user!delete.action时,就会自动调用UserAction中的delete()方法
提示,这种调用方式会带来安全隐患!

4.模拟Struts1中的ForwardAction
     <action name="user">
       <result>/index.jsp</result>
      </action>
      这样写就可以了.

5.默认的action
如果请求一个不存在的action,结果将是HTTP404错误。
在Struts2中,可以指定一个默认的action,如果一个请求没有其他的action匹配,那么默认的action将被执行。
默认的action使用default-action-ref元素来声明,如下所示:
  <!-- 默认action -->
<package name="defaultAction" namespace="/default" extends="struts-default">
<default-action-ref name="error"></default-action-ref>   
<action name="defaultaction" class="org.lesson05.DefaultAction">
    <result name="success">/defaultAction.jsp</result>
</action>
<action name="error">
    <result>/error.jsp</result>
</action>
</package>
   注意:根据struts-2.0.dtd中定义的package元素的内容模型,default-acion-ref必须在action元素之前使用。
         如果请求的是/default/defaultaction1.action,框架找不到映射到defaultaction1的action,那么名为error的action将被调用。
   注意:每个包中都可以有它自己默认的action,但是每一个名称空间应该只有一个默认action。如果具有相同名称空间的多个包中都声明了默认action,那么哪一个action才是默认的将无法保证。
   注意:默认action只对action的访问有效。如果你访问一个非action的资源,例如/user.jsp,而该页面不存在,这时仍会看到HTTP404错误。如果想为整个Web应用程序指定默认页面,需要在web.xml文件中对HTTP404错误指定相应的错误处理页面。

6.通配符映射
      随着Web应用程序的增加,所需的Action也会更多,从而导致大量的action映射,使用通配符可以减少action配置的数量,使一些具有类似行为的Action或者Action方法可以使用通用的样式来配置。
      通配符即星号(*),用于匹配0个或多个字符,在配置action时,可以在action元素的name属性中使用星号(*)来匹配任意的字符。
     以下是在action映射中使用通配符:
       <action name="news*" class="org.struts2.lesson05.News{1}Action">
    <result name="success">/WEB-INF/News/{1}.jsp</result>
       </action>
      我们在action元素的name属性中使用了通配符(*),允许这个映射匹配所有以/news开始的URL,例如/newsAdd,/newsEdit,/newsDelete,但是,如果请求的是/newsEdit/add,那么这个映射就不会被匹配。
      在上面,有一个特殊的记号{1},这是作为占位符使用的,它将被通配符所匹配的值替换,例如访问/newsEdit,通配符(*)匹配的部分是Edit,那么,这个值将替换{1},最终调用的类是org.struts2.lesson05.NewsEditAction,Action
   执行成功后导向的结果页面是/WEB-INF/News/Edit.jsp。
      在action映射和action结果中,通配符匹配的值可以用记号{N}来访问,N是从1到9的数字,指出替换的是哪一个通配符匹配的值。整个请求URL可以用记号{0}来访问。例如如下的action映射:
     <action name="*_*" class="org.struts2.lesson05.{1}Action"  method="{2}">
    <result>/WEB-INF/News/{0}.jsp</result>
     </action>
      当访问/News_delete时,name属性中的第一个”*”匹配News,第二个”*”匹配delete,class属性中使用的记号是{1},所以被News所替换,method属性中使用的记号是{2},于是被delete所替换。结果映射中使用的记号是{0},于是被整个URL替换,即News_delete所替换。整个替换后的结果是:当请求/News_delete时,框架调用NewsAction实例的delete方法对请求进行处理。执行成功后,请求被导向到/WEB-INF/News/News_delete.jsp页面。
      通配符方法设置的另一种常见方式是使用后缀通配符,即将”*”放在action名字的后面,在”*”和名字前缀之间使用一个特殊字符作为分隔,常用的特殊字符是下划线(_),当然也可以使用其他字符。例如:
       <action name="News_*" class="org.struts2.lesson05.NewsAction" method="{1}">
    <result>/WEB-INF/News/{0}.jsp</result>
       </action>
      当请求/News_delete时,调用的是NewsAction实例的delete方法,当请求/News_edit的时候,调用的是NewsAction实例的edit方法。
5、<exception-mapping>与<global-exception-mapping>
这两个标签都是用来配置发生异常时对应的视图信息的,只不过一个是Action范围的,一个是包范围的,当同一类型异常在两个范围都被配置时,Action范围的优先级要高于包范围的优先级.这两个标签包含的属性也是一样的:
因为在Action的execute方法声明时就抛出了Exception异常,所以我们无需再execute方法中捕捉异常,仅需在struts.xml 中配置异常处理。
为了使用Struts2的异常处理机制,必须打开Struts2的异常映射功能,这需要exception拦截器。在struts-default.xml文件中已经开启了exception拦截器。

声明式异常捕捉
Struts2的异常处理机制是通过在struts.xml文件中配置<exception-mapping……/>元素完成的,配置该元素时,需要指定两个属性:
exception:指定该异常类型的完全限定名。
result:指定逻辑视图名。

根据<exception-mapping…../>元素出现位置的不同,异常映射又可分为两种:
局部异常映射:将<exception-mapping… />元素作为<action…/>元素的子元素配置;
全局异常映射:将<exception-mapping… />元素作为<global-exception-mappings… />元素的子元素配置;

全局异常映射对所有的Action都有效,但局部异常映射仅对该异常映射所在的Action有效。
如果局部异常映射和全局异常映射配置了同一个异常类型,在<action…./>元素内的局部异常映射将覆盖全局异常映射。

Struts.xml
  <package name="ssh2" extends="struts-default">
     <global-results>
   <result name="sql">/exception.jsp</result>
   <result name="root">/exception.jsp</result>
     </global-results>
     <global-exception-mappings>
   <exception-mapping exception="java.sql.SQLException" result="sql"/>
   <exception-mapping exception="java.lang.Exception" result="root"/>
     </global-exception-mappings>
     <action name="login" class="loginAction">
<result>/welcome.jsp</result>
<result name="nullPointer">/nullPointer.jsp</result>
<exception-mapping exception="java.lang.NullPointerException" result="nullPointer"/>
      </action>
  </package>

Action
   public class loginAction extends ActionSupport
   {
public String add() throws SQLException
{
     return "toadd";
}
   }
 
有异常往外抛即可。你也可以在方法里面抛,比如throw SQLException。

我们可以使用Struts2的标签输出异常信息:
输出异常的message属性信息:<s:property value="exception.message" />
输出异常堆栈信息:<s:property value="exceptionStack" />。

有了处理系统异常的基础,我们来看一看自定义异常:
package com.exception ;
public class MyException extends Exception
{

    private String message;

    public MyException(String message)
    {
   super(message);
   this.message = message ;
    }
    public String getMessage() {
  return message;
    }
    public void setMessage(String message) {
   this.message = message;
    }
}

public String execute() throws Exception
{
    if(!"hello".equals(usename) || !"world".equals(password))
    {
     throw new MyException("用户名或密码错误,您发现了吧!");
    }
    return "success" ;
}

在action配置中的异常处理
   
<struts>
   <package name="struts2" extends="struts-default">      
      <action name="login" class="com.struts2.LoginAction">
    <exception-mapping result="myex" exception="com.exception.MyException">         
    </exception-mapping>
    <result name="myex">/error.jsp</result>
    <result name="success">/result.jsp</result>
      </action>
   </package>
</struts>

在全局配置中的异常处理
<struts>
   <package name="struts2" extends="struts-default">
      <global-results>
  <result name="myexception1">/error.jsp</result>
      </global-results>
     
      <global-exception-mappings>
  <exception-mapping result="myexception1"
       exception="com.exception.MyException">          
  </exception-mapping>
      </global-exception-mappings>
    
      <action name="login" class="com.struts2.LoginAction">
    <result name="success">/result.jsp</result>
      </action>
   </package>
</struts>

错误页面error.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s"  uri="/struts-tags"%> 
<html>
  <body>
    <!-- 这个exception 是 exception="com.exception.MyException" -->
    <s:property value="exception.message"/>
  </body>
</html>

局部异常处理比全局异常处理高,并且可覆盖全局异常处理,如果定义了全局异常映射,那么会对所有的Action生效,反之定义了局部异常映射则会对当前Action生效,
如果在全局区域和局部区域定义了相同的异常映射,首先去局部异常区域找result结果页面,如果找到了,则直接跳转到错误结果页面,不管全局有没有相同的结果,都被局部所覆盖,如果在局部区域没找到,则去全局区域找。
6、<default-class-ref>
当我们在配置Action的时候,如果没有为某个Action指定具体的class值时,系统将自动引用<default-class-ref>标签中所指定的类。在Struts2框架中,系统默认的class为ActionSupport,该配置我们可以在xwork的核心包下的xwork-default.xml文件中找到。
有特殊需要时,可以手动指定默认的class
package wwfy.action;

public class DefaultClassRef {
    public void execute(){
System.out.println("默认class开始执行……");
    }
}
在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="wwfy" extends="struts-default">
<!-- 指定默认class为Test -->
<default-class-ref class="wwfy.action.DefaultClassRef"/>
<action name="test1">
    <result>/index.jsp</result>
</action>
    </package>
</struts>
7、<default-action-ref>
当在struts.xml中配置default-action-ref时,如下:
<package name="front" namespace="/" extends="struts-default" > 
    <default-action-ref name="index"></default-action-ref> 
    <action name="index" class="com.chen.action.Abc" method="def"> 
    <result>/index.jsp</result> 
    </action> 
</package> 
1.当在浏览器中敲http://localhost:8080/apps/index时,这时候访问的是apps应用下的/命名空间下的index这个action,这个action会被com.chen.action.Abc类中的def方法处理,这个时候当然会new一个Abc类的对象。
2.若http://localhost:8080/apps/jflakjdflakj后面随便敲的时候,default-action-ref就起作用了,这时候默认的action是index,处理还会交给下面的index的action。
3.若http://localhost:8080/apps/,这时候需要注意的是不会默认访问default-action-ref定义的action,而是优先访问,web.xml中的welcome-file定义的视图
<welcome-file-list> 
  <welcome-file>index.jsp</welcome-file> 
</welcome-file-list> 
若想不敲的时候也通过index那个action,有两种方法:
(1)将welcome-file中不写任何视图,这时候还是会走default-action-ref
(2)经过实验,不必在WebContent下建立一个和welcome-file中定义的同名的文件。也就是说只要welcome-file中定义的文件找不到,就会交给default-action-ref处理。
需要注意的是,在default-action-ref中定义的action最终返回的视图若和welcome-file定义的视图是“同一”视图的话,可能会引起逻辑错误,这里看似同一个视图,但是default-action-ref定义的是经过action处理过的,走后面溜了一圈,而welcome-file直接返回了一个前台页面,若在这个默认视图中进行数据处理的话一定要注意。
如果在请求一个没有定义过的Action资源时,系统就会抛出404错误。这种错误不可避免,但这样的页面并不友好。我们可以使用<default-action-ref>来指定一个默认的Action,如果系统没有找到指定的Action,就会指定来调用这个默认的Action。
<?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="wwfy" extends="struts-default">

<default-action-ref name="acctionError"></default-action-ref>
<action name="acctionError">
    <result>/jsp/actionError.jsp</result>
</action>
    </package>
</struts>
8、<default-interceptor-ref>
该标签用来设置整个包范围内所有Action所要应用的默认拦截器信息。事实上我们的包继承了struts-default包以后,使用的是Struts的默认设置。我们可以在struts-default.xml中找到相关配置:
<default-interceptor-ref name="defaultStack"/>
在实际开发过程中,如果我们有特殊的需求是可以改变默认拦截器配置的。当时一旦更改这个配置,“defaultStack”将不再被引用,需要手动最加。
9、<interceptors>
通过该标签可以向Struts2框架中注册拦截器或者拦截器栈,一般多用于自定义拦截器或拦截器栈的注册。该标签使用方法如下:
<interceptors>
    <interceptor name="拦截器名" class="拦截器类"/>
    <interceptor-stack name="拦截器栈名">
<interceptor-ref name="拦截器名">
    </interceptor-stack>
</interceptors>
10、<interceptor-ref>
通过该标签可以为其所在的Action添加拦截器功能。
当为某个Action单独添加拦截器功能后,<default-interceptor-ref>中所指定的拦截器将不再对这个Action起作用。
11、<global-results>
该标签用于设置包范围内的全局结果集。在多个Action返回相同逻辑视图的情况下,可以通过<global-results>标签统一配置这些物理视图所对应的逻辑视图。
<?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="wwfy" extends="struts-default">
<global-results>
    <result name="test">/index.jsp</result>
</global-results>
    </package>
</struts>
注:鉴于拦截器部分比较抽象,下面做了详细介绍,希望有所收货。
Struts 2的基石——拦截器(Interceptor)
Interceptor(以下译为拦截器)是Struts 2的一个强有力的工具,有许多功能(feature)都是构建于它之上,如国际化、转换器,校验等。
1.什么是拦截器
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
2.实现原理
Struts 2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器,
3.已有的拦截器
Struts 2已经为您提供丰富多样的,功能齐全的拦截器实现。大家可以到struts2-all-2.0.1.jar或struts2-core-2.0.1.jar包的struts-default.xml查看关于默认的拦截器与拦截器链的配置。
在本文使用是Struts 2的最新发布版本2.0.1。需要下载的朋友请点击以下链接:
http://apache.justdn.org/struts/binaries/struts-2.0.1-all.zip
以下部分就是从struts-default.xml文件摘取的内容:

< 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 ="createSession" class ="org.apache.struts2.interceptor.CreateSessionInterceptor" />
< interceptor name ="debugging" class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
< interceptor name ="external-ref" 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 ="model-driven" class ="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" />
< interceptor name ="scoped-model-driven" class ="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor" />
< interceptor name ="params" class ="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />
< interceptor name ="prepare" class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor" />
< interceptor name ="static-params" class ="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor" />
< interceptor name ="scope" class ="org.apache.struts2.interceptor.ScopeInterceptor" />
< interceptor name ="servlet-config" 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 ="token-session" class ="org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />
< interceptor name ="validation" class ="com.opensymphony.xwork2.validator.ValidationInterceptor" />
< 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" />
4.配置和使用拦截器
在struts-default.xml中已经配置了以上的拦截器。如果您想要使用上述拦截器,只需要在应用程序struts.xml文件中通过“<include file="struts-default.xml" />”将struts-default.xml文件包含进来,并继承其中的struts-default包(package),最后在定义Action时,使用“<interceptor-ref name="xx" />”引用拦截器或拦截器栈(interceptor stack)。一旦您继承了struts-default包(package),所有Action都会调用拦截器栈 ——defaultStack。当然,在Action配置中加入“<interceptor-ref name="xx" />”可以覆盖defaultStack。
下面是关于拦截器timer使用的例子。首先,新建Action类tuotrial/TimerInterceptorAction.java,内容如下:
package tutorial;

import com.opensymphony.xwork2.ActionSupport;

public class TimerInterceptorAction extends ActionSupport {
    @Override
     public String execute() {
try {
     // 模拟耗时的操作
    Thread.sleep( 500 );
} catch (Exception e) {
    e.printStackTrace();
}
return SUCCESS;
    }
}
配置Action,名为Timer,配置文件如下:
<! DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
    < include file ="struts-default.xml" />   
    < package name ="InterceptorDemo" extends ="struts-default" >
< action name ="Timer" class ="tutorial.TimerInterceptorAction" >
    < interceptor-ref name ="timer" />
    < result > /Timer.jsp </ result >
</ action >
    </ package >
</ struts >
至于Timer.jsp可以随意写些什么到里面。
发布运行应用程序,在浏览器的地址栏键入http://localhost:8080/Struts2_Interceptor/Timer.action,在出现Timer.jsp页面后,查看服务器的后台输出。
2006 - 12 - 6 14 : 27 : 32 com.opensymphony.xwork2.interceptor.TimerInterceptor doLog
信息: Executed action [ //Timer!execute ] took 2859 ms.
在您的环境中执行Timer!execute的耗时,可能上述的时间有些不同,这取决于您PC的性能。但是无论如何,2859 ms与500 ms还是相差太远了。这是什么原因呢?其实原因是第一次加载Timer时,需要进行一定的初始工作。当你重新请求Timer.action时,以上输出会变为:
2006 - 12 - 6 14 : 29 : 18 com.opensymphony.xwork2.interceptor.TimerInterceptor doLog
信息: Executed action [ //Timer!execute ] took 500 ms.
OK,这正是我们期待的结果。上述例子演示了拦截器timer的用途——用于显示执行某个action方法的耗时,在我们做一个粗略的性能调试时,这相当有用。
6.自定义拦截器
作为“框架(framework)”,可扩展性是不可或缺的,因为世上没有放之四海而皆准的东西。虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在Struts 2自定义拦截器是相当容易的一件事。
大家在开始着手创建自定义拦截器前,切记以下原则:
拦截器必须是无状态的,不要使用在API提供的ActionInvocation之外的任何东西。
要求拦截器是无状态的原因是Struts 2不能保证为每一个请求或者action创建一个实例,所以如果拦截器带有状态,会引发并发问题。
所有的Struts 2的拦截器都直接或间接实现接口com.opensymphony.xwork2.interceptor.Interceptor。除此之外,大家可能更喜欢继承类com.opensymphony.xwork2.interceptor.AbstractInterceptor。

以下例子演示通过继承AbstractInterceptor,实现授权拦截器。
首先,创建授权拦截器类tutorial.AuthorizationInterceptor,代码如下:

package tutorial;

import java.util.Map;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class AuthorizationInterceptor extends AbstractInterceptor {

    @Override
     public String intercept(ActionInvocation ai) throws Exception {
        Map session = ai.getInvocationContext().getSession();
        String role = (String) session.get( " ROLE " );
         if ( null != role) {
            Object o = ai.getAction();
             if (o instanceof RoleAware) {
                RoleAware action = (RoleAware) o;
                action.setRole(role);
            }
             return ai.invoke();
        } else {
             return Action.LOGIN;
        }       
    }

}
以上代码相当简单,我们通过检查session是否存在键为“ROLE”的字符串,判断用户是否登陆。如果用户已经登陆,将角色放到Action中,调用Action;否则,拦截直接返回Action.LOGIN字段。为了方便将角色放入Action,我定义了接口tutorial.RoleAware,代码如下:

package tutorial;

public interface RoleAware {
     void setRole(String role);
}
接着,创建Action类tutorial.AuthorizatedAccess模拟访问受限资源,它作用就是通过实现RoleAware获取角色,并将其显示到ShowUser.jsp中,代码如下:

package tutorial;

import com.opensymphony.xwork2.ActionSupport;

public class AuthorizatedAccess extends ActionSupport implements RoleAware {
     private String role;
   
     public void setRole(String role) {
         this .role = role;
    }
   
     public String getRole() {
         return role;
    }

    @Override
     public String execute() {
         return SUCCESS;
    }
}
以下是ShowUser.jsp的代码:

<% @ page  contentType = " text/html; charset=UTF-8 " %>
<% @taglib prefix = " s " uri = " /struts-tags " %>
< html >
< head >
    < title > Authorizated User </ title >
</ head >
< body >
    < h1 > Your role is: < s:property value ="role" /></ h1 >
</ body >
</ html >
然后,创建tutorial.Roles初始化角色列表,代码如下:

package tutorial;

import java.util.Hashtable;
import java.util.Map;


public class Roles {
     public Map < String, String > getRoles() {
        Map < String, String > roles = new Hashtable < String, String > ( 2 );
        roles.put( " EMPLOYEE " , " Employee " );
        roles.put( " MANAGER " , " Manager " );
         return roles;
    }
}
接下来,新建Login.jsp实例化tutorial.Roles,并将其roles属性赋予<s:radio>标志,代码如下:

<% @ page  contentType = " text/html; charset=UTF-8 " %>
<% @taglib prefix = " s " uri = " /struts-tags " %>
< html >
< head >
    < title > Login </ title >
</ head >
< body >
    < h1 > Login </ h1 >
    Please select a role below:
    < s:bean id ="roles" name ="tutorial.Roles" />
    < s:form action ="Login" >
        < s:radio list ="#roles.roles" value ="'EMPLOYEE'" name ="role" label ="Role" />
        < s:submit />
    </ s:form >
</ body >
</ html >
创建Action类tutorial.Login将role放到session中,并转到Action类tutorial.AuthorizatedAccess,代码如下:

package tutorial;

import java.util.Map;

import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

public class Login extends ActionSupport implements SessionAware {
     private String role;   
     private Map session;

     public String getRole() {
         return role;
    }

     public void setRole(String role) {
         this .role = role;
    }
   
     public void setSession(Map session) {
         this .session = session;
    }

    @Override
     public String execute() {
        session.put( " ROLE " , role);
         return SUCCESS;
    }   
}
最后,配置struts.xml文件,内容如下:

<! DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
    < include file ="struts-default.xml" />   
    < package name ="InterceptorDemo" extends ="struts-default" >
        < interceptors >
            < interceptor name ="auth" class ="tutorial.AuthorizationInterceptor" />
        </ interceptors >
        < action name ="Timer" class ="tutorial.TimerInterceptorAction" >
            < interceptor-ref name ="timer" />
            < result > /Timer.jsp </ result >
        </ action >
        < action name ="Login" class ="tutorial.Login" >
            < result type ="chain" > AuthorizatedAccess </ result >
        </ action >
        < action name ="AuthorizatedAccess" class ="tutorial.AuthorizatedAccess" >
            < interceptor-ref name ="auth" />
            < result name ="login" > /Login.jsp </ result >
            < result name ="success" > /ShowRole.jsp </ result >
        </ action >
    </ package >
</ struts >
发布运行应用程序,在浏览器地址栏中输入:http://localhost:8080/Struts2_Interceptor/AuthorizatedAccess.action。由于此时,session还没有键为“ROLE”的值,所以返回Login.jsp页面,
选中Employee,点击Submit,出现ShowRole.jsp页面
总之,拦截器是Struts 2比较重要的一个功能。通过正确地使用拦截器,我们可以编写高可复用的代码。

看有所获的朋友,多多支持。

猜你喜欢

转载自1034806625.iteye.com/blog/2184013