struts.xml文件的常用配置解析

1.使用<include>标签重用配置文件

在Struts2中提供了一个默认的struts.xml文件,但如果package、action、interceptors等配置比较多时,都放到一个struts.xml文件不太容易维护。

因此,就需要将struts.xml文件分成多个配置文件,然后在struts.xml文件中使用<include>标签引用这些配置文件。这样做的优点如下:
a. 结构更清晰,更容易维护配置信息。
b. 配置文件可以复用。

如果在多个Web程序中都使用类似或相同的配置文件,那么可以使用<include>标签来引用这些配置文件,这样可以减少工作量。

假设有一个配置文件,文件名为newstruts.xml,代码如下:

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <packagename="demo"extends="struts-default">
  7. <actionname="submit"class="action.MoreSubmitAction">
  8. <resultname="save">
  9. /result.jsp
  10. </result>
  11. <resultname="print">
  12. /result.jsp
  13. </result>
  14. </action>
  15. </package>
  16. </struts>
<?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="demo" extends="struts-default" >
        <action name="submit"  class="action.MoreSubmitAction">
            <result name="save" >
                /result.jsp
            </result>
            <result name="print">
                /result.jsp
            </result>
        </action>            
    </package>    
</struts>


struts.xml引用newstruts.xml文件的代码如下:

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <includefile="newstruts.xml"/>
  7. <packagename="test"extends="struts-default">
  8. </package>
  9. </struts>
<?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>
    <include file="newstruts.xml"/>
    <package name="test" extends="struts-default">
     
    </package>    
</struts>

大家要注意一下,用<include>引用的xml文件也必须是完成的struts2的配置。实际上<include>在引用时是单独解析的xml文件,而不是将被引用的文件插入到struts.xml文件中。

2.常量配置

通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成。

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <!--指定Web应用的默认编码集,相当于调用 HttpServletRequest的setCharacterEncoding方法。-->
  7. <constantname="struts.i18n.encoding"value="UTF-8"/>
  8. <!--该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发, 但在产品发布阶段应将该属性设置为false。 -->
  9. <constantname="struts.i18n.reload"value="false"/>
  10. <!--该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开。 -->
  11. <constantname="struts.custom.i18n.resources"value="applicationResource"/>
  12. <!--该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。-->
  13. <constantname="struts.action.extension"value="action, do"/>
  14. <!--设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭。-->
  15. <constantname="struts.serve.static.browserCache "value="true"/>
  16. <!--当struts 2的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开。-->
  17. <constantname="struts.configuration.xml.reload"value="false"/>
  18. <!--该属性指定Struts 2框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,)隔开。
  19. 该属性的默认值为struts- default.xml,struts-plugin.xml, struts.xml,看到该属性值,读者应该明白为什么Struts 2框架默认加载struts.xml文件了。 -->
  20. <constantname="struts.configuration.files"value="struts-default.xml,struts-plugin.xml,struts.xml"/>
  21. <!--指定加载struts2配置文件管理器,默认为org.apache.struts2.config.DefaultConfiguration,开发者可以自定义配置文件管理器,该类要实现Configuration接口,可以自动加载struts2配置文件。 -->
  22. <constantname="struts.configuration"value="org.apache.struts2.config.DefaultConfiguration"/>
  23. <!--含有Actions的完整连续的package名称。 -->
  24. <constantname="struts.continuations.package"value=""/>
  25. <!-- 应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。
  26. 该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。 -->
  27. <constantname="struts.devMode"value="true"/>
  28. <!--该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。-->
  29. <constantname="struts.enable.DynamicMethodInvocation"value="false"/>
  30. <!--该属性指定视图标签默认的视图主题,该属性的默认值是xhtml,可以为simple,xhtml或ajax。 -->
  31. <constantname="struts.ui.theme"value="xhtml"/>
  32. <packagename="test"extends="struts-default">
  33. </package>
  34. </struts>
<?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>     
	<!--指定Web应用的默认编码集,相当于调用 HttpServletRequest的setCharacterEncoding方法。-->
	<constant name="struts.i18n.encoding" value="UTF-8" />   
   
	<!--该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发, 但在产品发布阶段应将该属性设置为false。 -->
    <constant name="struts.i18n.reload" value="false"/>  
     
    <!--该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开。 -->
    <constant name="struts.custom.i18n.resources" value="applicationResource"/>  
     
    <!--该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。-->
    <constant name="struts.action.extension" value="action, do" />   
   
    <!--设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭。-->
    <constant name="struts.serve.static.browserCache " value="true" />   
   
    <!--当struts 2的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开。-->
    <constant name="struts.configuration.xml.reload" value="false" />   
     
    <!--该属性指定Struts 2框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,)隔开。
        该属性的默认值为struts- default.xml,struts-plugin.xml, struts.xml,看到该属性值,读者应该明白为什么Struts 2框架默认加载struts.xml文件了。 -->
   
   <constant name="struts.configuration.files" value="struts-default.xml,struts-plugin.xml,struts.xml"/>  
    <!--指定加载struts2配置文件管理器,默认为org.apache.struts2.config.DefaultConfiguration,开发者可以自定义配置文件管理器,该类要实现Configuration接口,可以自动加载struts2配置文件。 -->
    
    <constant name="struts.configuration" value="org.apache.struts2.config.DefaultConfiguration"/>  
     
    <!--含有Actions的完整连续的package名称。 -->
    <constant name="struts.continuations.package" value=""/>  
     
    <!-- 应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。
        该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。 -->
    <constant name="struts.devMode" value="true" />   
    
    <!--该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。-->
    <constant name="struts.enable.DynamicMethodInvocation" value="false"/>  
    
    <!--该属性指定视图标签默认的视图主题,该属性的默认值是xhtml,可以为simple,xhtml或ajax。 -->
    <constant name="struts.ui.theme" value="xhtml"/>  
   
    <package name="test" extends="struts-default">
     
    </package>  
</struts>  

这里只是列出一部分常用的,其他常量如果有需要可以查看官方文档。

3.包(Package)配置

Struts2框架中核心组件就是Action、拦截器等,Struts2框架使用包来管理Action和拦截器等。每个包就是多个Action、多个拦截器、多个拦截器引用的集合。

Package的名字必须是唯一的。 package可以扩展, 当一个package扩展自另一个package时该package会在本身配置的基础上加入扩展的package 的配置。 父package必须在子package前配置。

name:package名称
extends: 继承的父package名称
abstract: 设置package的属性为抽象的 抽象的package不能定义action 值true:false
namespace: 定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action

3.1 命名空间配置

考虑到同一个Web应用中需要同名的Action,Struts2以命名空间的方式来管理Action,同一个命名空间不能有同名的Action。
Struts2通过为包指定namespace属性来为包下面的所有Action指定共同的命名空间。

  1. <!DOCTYPE struts PUBLIC
  2. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  3. "http://struts.apache.org/dtds/struts-2.0.dtd">
  4. <struts>
  5. <!-- struts2的action必须放在一个指定的包空间下定义 -->
  6. <packagename="default"extends="struts-default">
  7. <!-- 定义处理请求URL为login.action的Action -->
  8. <actionname="login"class="org.qiujy.web.struts2.action.LoginAction">
  9. <!-- 定义处理结果字符串和资源之间的映射关系 -->
  10. <resultname="success">/success.jsp</result>
  11. <resultname="error">/error.jsp</result>
  12. </action>
  13. </package>
  14. <packagename="my"extends="struts-default"namespace="/manage">
  15. <!-- 定义处理请求URL为login.action的Action -->
  16. <actionname="backLogin"class="org.qiujy.web.struts2.action.LoginAction">
  17. <!-- 定义处理结果字符串和资源之间的映射关系 -->
  18. <resultname="success">/success.jsp</result>
  19. <resultname="error">/error.jsp</result>
  20. </action>
  21. </package>
  22. </struts>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <!-- struts2的action必须放在一个指定的包空间下定义 -->
    <package name="default" extends="struts-default">
    <!-- 定义处理请求URL为login.action的Action -->
        <action name="login" class="org.qiujy.web.struts2.action.LoginAction">
        <!-- 定义处理结果字符串和资源之间的映射关系 -->
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
   
    <package name="my" extends="struts-default" namespace="/manage">
    <!-- 定义处理请求URL为login.action的Action -->
        <action name="backLogin" class="org.qiujy.web.struts2.action.LoginAction">
        <!-- 定义处理结果字符串和资源之间的映射关系 -->
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
</struts>

如上配置了两个包:default和my,配置my包时指定了该包的命名空间为/manage。
对于包default:没有指定namespace属性。如果某个包没有指定namespace属性,即该包使用默认的命名空间,默认的命名空间总是""。它处理的URL为:

http://localhost:8080/userlogin_struts2/login.action
对于包my:指定了命名空间/manage,则该包下所有的Action处理的URL应该是“命名空间/Action名”。如上名为backLogin的Action,它处理的URL为:
http://localhost:8080/userlogin_struts2/manage/backLogin.action

 

3.2.Action配置

(1)Action别名

A. 在默认情况下,Struts2会调用动作类的execute方法。但有些时候,我们需要在一个动作类中处理不同的动作。也就是用户请求不同的动作时,执行动作类中的不同的方法。

为了达到这个目的,可以在<action>标签中通过method方法指定要指行的动作类的方法名,并且需要为不同的动作起不同的名子(也称为别名)。如下面代码所示:

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC
  3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  4. "http://struts.apache.org/dtds/struts-2.0.dtd">
  5. <struts>
  6. <packagename="demo"extends="struts-default">
  7. <actionname="test"class="action.MyAction">
  8. </action>
  9. <actionname="my"class="action.MyAction"method="my">
  10. </action>
  11. </package>
  12. </struts>
<?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="demo" extends="struts-default" >
    <action name="test"  class="action.MyAction">
        
    </action>            
    <action name="my"  class="action.MyAction" method="my">
         
    </action>            
</package>    
</struts>

上面代码的两个动作的class属性都指向同一个类,name为这个类起了两个动作别名:test和my。在动作my中,使用了method属性指定要要运行的方法名为my。

MyAction类中必须要有my方法,代码如下:

  1. <preclass="java"name="code">package action;
  2. import com.opensymphony.xwork2.ActionSupport;
  3. public class MyAction extends ActionSupport
  4. {
  5. public String execute() throws Exception
  6. {
  7. // 处理test动作的代码
  8. }
  9. public String my() throws Exception
  10. {
  11. // 处理my动作的代码
  12. }
  13. }</pre>
  14. <pre></pre>
  15. <pre></pre>
  16. <pre></pre>
  1. package action;
  2. import com.opensymphony.xwork2.ActionSupport;
  3. publicclass MyAction extends ActionSupport
  4. {
  5. public String execute() throws Exception
  6. {
  7. // 处理test动作的代码
  8. }
  9. public String my() throws Exception
  10. {
  11. // 处理my动作的代码
  12. }
  13. }
package action;

import com.opensymphony.xwork2.ActionSupport;

public class MyAction extends ActionSupport
{
     
    public String execute() throws Exception
    {
        // 处理test动作的代码
    }
    public String my() throws Exception
    {
          // 处理my动作的代码
    }
     
}

 

除了在struts.xml中配置别名,还可以通过请求参数来描述指定动作(并不需要在struts.xml中配置)。请求参数的格式如下:

http://localhost:8080/contextPath/actionName!method.action

比如请求MyAction的my方法URL为:http://localhost:8080/contextPath/my!my.action

(2) Action 通配符

假设有有配置如下:

  1. <package name="actions"extends="struts-default" namespace="/actions">
  2. <action name="Student*"class="com.bjsxt.struts2.action.StudentAction" method="{1}">
  3. <result>/Student{1}_success.jsp</result>
  4. </action>
  5. <action name="*_*"class="com.bjsxt.struts2.action.{1}Action" method="{2}">
  6. <result>/{1}_{2}_success.jsp</result>
  7. <!-- {0}_success.jsp -->
  8. </action>
  9. </package>
<package name="actions" extends="struts-default" namespace="/actions">
        <action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">
            <result>/Student{1}_success.jsp</result>
        </action>
        
        <action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
            <result>/{1}_{2}_success.jsp</result>
            <!-- {0}_success.jsp -->
        </action>
    </package> 

{1}、{2}表示第一第二个占位符 , *为通配符
总结:使用通配符,将配置量降到最低。
<a href="<%=context %>/actions/Studentadd">添加学生</a> Result: /Studentadd_success.jsp
<a href="<%=context %>/actions/Studentdelete">删除学生</a>Result: /Studentdelete_success.jsp
不过,一定要遵守"约定优于配置"的原则。
<a href="<%=context %>/actions/Teacher_add">添加老师</a>Result: /Teacher_add_success.jsp
<a href="<%=context %>/actions/Teacher_delete">删除老师</a>Result: /Teacher_delete_success.jsp
<a href="<%=context %>/actions/Course_add">添加课程</a>Result: /Course_add_success.jsp
<a href="<%=context %>/actions/Course_delete">删除课程</a>Result: /Course_delete_success.jsp

通过action name的通配匹配,获得占位符,可以使用占位符放在result和method、class中替代匹配的字符。

(3)为action指定参数

struts2中还可以为action指定一个或多个参数。大家还记着struts1.x是如何设置的action参数不?

在struts1.x中可以使用<action>标签的parameter属性为其指定一个action参数,如果要指定多个,就只能通过逗号(,)或其他的分隔符将不同的参数隔开。

而在struts2中可以通过<param>标签指定任意多个参数。代码如下:

  1. <actionname="submit"class="action.MyAction">
  2. <paramname="param1">value1</param>
  3. <paramname="param2">value2</param>
  4. <resultname="save">
  5. /result.jsp
  6. </result>
  7. </action><spanstyle='font-family: "Microsoft YaHei"; background-color: rgb(255, 255, 255);'></span>
<action name="submit"  class="action.MyAction">
<param name="param1">value1</param>
<param name="param2">value2</param>
    <result name="save" >
        /result.jsp
    </result>
     
</action>

 

当然,在action中读这些参数也非常简单,只需要象获取请求参数一样在action类中定义相应的setter方法即可(一般不用定义getter方法)。

如下面的代码将读取param1param2参数的值:

  1. package action;
  2. import com.opensymphony.xwork2.ActionSupport;
  3. publicclass MyAction extends ActionSupport
  4. {
  5. private String param1;
  6. private String param2;
  7. public String execute() throws Exception
  8. {
  9. System.out.println(param1 + param2);
  10. }
  11. publicvoid setParam1(String param1)
  12. {
  13. this.param1 = param1;
  14. }
  15. publicvoid setParam2(String param2)
  16. {
  17. this.param2 = param2;
  18. }
  19. }
package action;

import com.opensymphony.xwork2.ActionSupport;

public class MyAction extends ActionSupport
{
    private String param1;
    private String param2;

    public String execute() throws Exception
    {
        System.out.println(param1 + param2);
    }
    public void setParam1(String param1)
    {
        this.param1 = param1;
    }
    public void setParam2(String param2)
    {
        this.param2 = param2;
    }
     
}

 

当struts2在调用execute之前,param1和param2的值就已经是相应参数的值了,因此,在execute方法中可以直接使用param1和param2。

3.3 选择result类型

在默认时,<result>标签的type属性值是“dispatcher”(实际上就是转发,forward)。开发人员可以根据自己的需要指定不同的类型,如redirect、stream等。如下面代码所示:

这此result-type可以在struts2-core-2.0.11.1.jar包或struts2源代码中的struts-default.xml文件中找到,在这个文件中找到<result-types>标签,所有的result-type都在里面定义了。代码如下:

 

  1. <resultname="save"type="redirect">/result.jsp</result>
<result name="save" type="redirect">/result.jsp</result>
  1. <result-types>
  2. <!--用来处理Action链, 处理的结果值为下一个转向的action-->
  3. <result-typename="chain"
  4. class="com.opensymphony.xwork2.ActionChainResult"/>
  5. <!--用来转向页面,通常处理JSP,默认是dispatcher-->
  6. <result-typename="dispatcher"
  7. class="org.apache.struts2.dispatcher.ServletDispatcherResult"
  8. default="true"/>
  9. <!--处理FreeMarker模板-->
  10. <result-typename="freemarker"
  11. class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
  12. <!--用来控制特殊的Http行为-->
  13. <result-typename="httpheader"
  14. class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
  15. <!--重定向到一个URL-->
  16. <result-typename="redirect"
  17. class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
  18. <!--重定向到一个Action-->
  19. <result-typename="redirectAction"
  20. class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
  21. <!--向浏览器发送InputSream对象,通常用来处理文件下载-->
  22. <result-typename="stream"
  23. class="org.apache.struts2.dispatcher.StreamResult"/>
  24. <!--处理Velocity模板-->
  25. <result-typename="velocity"
  26. class="org.apache.struts2.dispatcher.VelocityResult"/>
  27. <!--处理XML/XLST模板-->
  28. <result-typename="xslt"
  29. class="org.apache.struts2.views.xslt.XSLTResult"/>
  30. <!--显示原始文件内容,例如文件源代码-->
  31. <result-typename="plainText"
  32. class="org.apache.struts2.dispatcher.PlainTextResult"/>
  33. </result-types>
<result-types>
    <!--用来处理Action链, 处理的结果值为下一个转向的action-->
    <result-type name="chain"
             class="com.opensymphony.xwork2.ActionChainResult"/>
    <!--用来转向页面,通常处理JSP,默认是dispatcher-->
    <result-type name="dispatcher"
             class="org.apache.struts2.dispatcher.ServletDispatcherResult"
             default="true"/>
    <!--处理FreeMarker模板-->
    <result-type name="freemarker"
             class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
    <!--用来控制特殊的Http行为-->
    <result-type name="httpheader"
             class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
    <!--重定向到一个URL-->        
    <result-type name="redirect"
             class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
    <!--重定向到一个Action-->
    <result-type name="redirectAction"
             class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
    <!--向浏览器发送InputSream对象,通常用来处理文件下载-->
    <result-type name="stream"
             class="org.apache.struts2.dispatcher.StreamResult"/>
    <!--处理Velocity模板-->
    <result-type name="velocity"
             class="org.apache.struts2.dispatcher.VelocityResult"/>
    <!--处理XML/XLST模板-->
    <result-type name="xslt"
             class="org.apache.struts2.views.xslt.XSLTResult"/>
    <!--显示原始文件内容,例如文件源代码-->
    <result-type name="plainText"
             class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>

 

3.4全局results

有很多时候一个<result>初很多<action>使用,这时可以使用<global-results>标签来定义全局的<result>,代码如下:

  1. <struts>
  2. <packagename="demo"extends="struts-default">
  3. <global-results>
  4. <resultname="print">/result.jsp</result>
  5. <resultname="input">/error.jsp</result>
  6. </global-results>
  7. <actionname="submit"class="action.MoreSubmitAction">
  8. </action>
  9. <actionname="my"class="action.MoreSubmitAction"method="my">
  10. </action>
  11. </package>
  12. </struts>
<struts>
    <package name="demo" extends="struts-default">
        <global-results>
            <result name="print">/result.jsp</result>
	    <result name="input">/error.jsp</result>
        </global-results>
        <action name="submit" class="action.MoreSubmitAction">
         
        </action>
        <action name="my" class="action.MoreSubmitAction" method="my">
         
        </action>
    </package>
</struts>

如果<action>中没有相应的<result>Struts2就会使用全局的<result>。

3.5.拦截器配置

Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

(1)实现拦截器类

假设当浏览者需要请求执行某个操作时,应用需要先检查浏览者是否登录,以及是否有足够的权限来执行该操作,拦截器类如下:

  1. package org.qiujy.common;
  2. import java.util.Map;
  3. import com.opensymphony.xwork2.Action;
  4. import com.opensymphony.xwork2.ActionInvocation;
  5. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
  6. /**
  7. * 权限检查拦截器
  8. *
  9. * @author qiujy
  10. * @version 1.0
  11. */
  12. public class AuthorizationInterceptor extends AbstractInterceptor {
  13. /*
  14. * 拦截Action处理的拦截方法
  15. *
  16. */
  17. public String intercept(ActionInvocation invocation) throws Exception {
  18. Map session = invocation.getInvocationContext().getSession();
  19. String userName = (String) session.get("userName");
  20. if (null != userName && userName.equals("test")) {
  21. System.out.println("拦截器:合法用户登录---");
  22. return invocation.invoke();
  23. } else {
  24. System.out.println("拦截器:用户未登录---");
  25. return Action.LOGIN;
  26. }
  27. }
  28. }
package org.qiujy.common;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 
/**
 * 权限检查拦截器
 *
 * @author qiujy
 * @version 1.0
 */
public class AuthorizationInterceptor extends AbstractInterceptor {
 
    /*
     * 拦截Action处理的拦截方法
     *
     */
    public String intercept(ActionInvocation invocation) throws Exception {
       
        Map session = invocation.getInvocationContext().getSession();
        String userName = (String) session.get("userName");
       
        if (null != userName && userName.equals("test")) {
            System.out.println("拦截器:合法用户登录---");
            return invocation.invoke();
        } else {
            System.out.println("拦截器:用户未登录---");
            return Action.LOGIN;
        }
    }
}

(2)定义拦截器,拦截器栈:

  1. <packagename="my"extends="struts-default"namespace="/manage">
  2. <interceptors>
  3. <!-- 定义拦截器 -->
  4. <interceptorname="拦截器名"class="拦截器实现类"/>
  5. <!-- 定义拦截器栈 -->
  6. <interceptor-stackname="拦截器栈名">
  7. <interceptor-refname="拦截器一"/>
  8. <interceptor-refname="拦截器二"/>
  9. </interceptor-stack>
  10. </interceptors>
  11. ......
  12. </package>
<package name="my" extends="struts-default" namespace="/manage">
        <interceptors>
        <!-- 定义拦截器 -->
        <interceptor name="拦截器名" class="拦截器实现类"/>
        <!-- 定义拦截器栈 -->
        <interceptor-stack name="拦截器栈名">
             <interceptor-ref name="拦截器一"/>
             <interceptor-ref name="拦截器二"/>
        </interceptor-stack>
        </interceptors>
        ......
</package>

(3)使用拦截器:

定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了。拦截器的拦截行为将会在Actionexceute方法执行之前被执行:
  1. <palign="left"><spanstyle="color: teal;"></span></p><preclass="html"name="code"><palign="left"><spanstyle="color: teal;"></span></p><preclass="html"name="code"><!DOCTYPE struts PUBLIC
  2. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  3. "http://struts.apache.org/dtds/struts-2.0.dtd">
  4. <struts>
  5. <packagename="my"extends="struts-default">
  6. <interceptors>
  7. <!-- 定义权限控制拦截器 -->
  8. <interceptorname="authority"class="org.qiujy.common.AuthorizationInterceptor"/>
  9. </interceptors>
  10. <!-- 定义全局处理结果 -->
  11. <global-results>
  12. <!-- 逻辑名为login的结果,映射到/login.jsp页面 -->
  13. <resultname="login">/login.jsp</result>
  14. </global-results>
  15. <actionname="listall"class="org.qiujy.web.struts2.action.UserAction" method="listAllUser">
  16. <resultname="success">/listall.jsp</result>
  17. <!-- 使用拦截器 -->
  18. <interceptor-refname="defaultStack"/>
  19. <interceptor-refname="authority"/>
  20. </action>
  21. </package>
  22. </struts></pre><br>
  23. <p><spanstyle="color: teal;"></span></p>
  24. <pre></pre>
  25. <pre></pre>
  26. <p><spanstyle="background-color: rgb(255, 255, 255);"><spanstyle="font-family: Microsoft YaHei; font-size: 12px;"><spanstyle="line-height: 19px;"></span></span></span></p>
  27. <pre></pre>
  28. <div></div>
  29. <div></div>
  30. </pre>
  31. <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
    <struts>

    <!-- include节点是struts2中组件化的方式 可以将每个功能模块独立到一个xml配置文件中 然后用include节点引用 -->
    <include file="struts-default.xml"></include>


    <!-- package提供了将多个Action组织为一个模块的方式
    package的名字必须是唯一的 package可以扩展 当一个package扩展自
    另一个package时该package会在本身配置的基础上加入扩展的package
    的配置 父package必须在子package前配置
    name:package名称
    extends:继承的父package名称
    abstract:设置package的属性为抽象的 抽象的package不能定义action 值true:false
    namespace:定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
    -->
    <package name="com.kay.struts2" extends="struts-default" namespace="/test">
    <interceptors>
    <!-- 定义拦截器
    name:拦截器名称
    class:拦截器类路径
    -->
    <interceptor name="timer" class="com.kay.timer"></interceptor>
    <interceptor name="logger" class="com.kay.logger"></interceptor>
    <!-- 定义拦截器栈 -->
    <interceptor-stack name="mystack">
    <interceptor-ref name="timer"></interceptor-ref>
    <interceptor-ref name="logger"></interceptor-ref>
    </interceptor-stack>
    </interceptors>

    <!-- 定义默认的拦截器 每个Action都会自动引用
    如果Action中引用了其它的拦截器 默认的拦截器将无效
    -->
    <default-interceptor-ref name="mystack"></default-interceptor-ref>


    <!-- 全局results配置 -->
    <global-results>
    <result name="input">/error.jsp</result>
    </global-results>

    <!-- Action配置 一个Action可以被多次映射(只要action配置中的name不同)
    name:action名称
    class: 对应的类的路径
    method: 调用Action中的方法名
    -->
    <action name="hello" class="com.kay.struts2.Action.LoginAction">
    <!-- 引用拦截器
    name:拦截器名称或拦截器栈名称
    -->
    <interceptor-ref name="timer"></interceptor-ref>

    <!-- 节点配置
    name : result名称 和Action中返回的值相同
    type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
    -->
    <result name="success" type="dispatcher">/talk.jsp</result>
    <!-- 参数设置
    name:对应Action中的get/set方法
    -->
    <param name="url">http://www.sina.com</param>
    </action>
    </package>
    </struts>
  32. struts2.1开始,struts2不再推荐使用Codebehind作为零配置插件,而是改为使用Convention插件来支持零配置,Codebehind相比,Convention插件更彻底,该插件完全抛弃配置信息,不仅不需要是使用struts.xml文件进行配置,甚至不需要使用Annotation进行配置,而是由struts2根据约定自动配置。零配置并不是没有配置,而是通过约定大于配置的方式,大量通过约定来调度页面的跳转而使得配置大大减少。所以,首先应该了解下convention-plugin的约定:

    1. <spanstyle="font-family: Microsoft YaHei;"><!--设置Convention插件定位视图资源的根路径,默认为/WEB-INFO/content -->
    2. <constantname="struts.convention.result.path"value="/WEB-INF/content/"/>
    3. <!--如果设置为false,则可以将视图页面放置Action对应的目录(无需放入WEB-INFO/content) -->
    4. <constantname="struts.convention.result.flatLayout"value="true"/>
    5. <!--Convention搜索Action类的类名后缀,默认为Action -->
    6. <constantname="struts.convention.action.suffix"value="Action"/>
    7. <!--是否禁止通过包扫描Action,默认是false -->
    8. <constantname="struts.convention.action.disableScanning"value="false"/>
    9. <!--设置即使没有@Action注释,是否依然创建Action映射。默认值为false -->Create action mappings, even if no @Action is found
    10. <constantname="struts.convention.action.mapAllMatches"value="false"/>
    11. <!--设置是否所有实现com.opensymphony.xwork2.Action的Action都创建Action映射,默认是true -->
    12. <constantname="struts.convention.action.checkImplementsAction"value="true"/>
    13. <!--设置Convention映射的Action所在包的默认父包。默认值是convention-default -->
    14. <constantname="struts.convention.default.parent.package"value="convention-default"/>
    15. <!--设置映射Action时,是否将Action的name属性值转换为所有字母小写,默认值是true -->
    16. <constantname="struts.convention.action.name.lowercase"value="true"/>
    17. <!--设置映射Action时指定name属性值各单词之间的分隔符。默认值为中画线(“-”) -->
    18. <constantname="struts.convention.action.name.separator"value="-"/>
    19. <!--默认包路径包含action,actions,struts,struts2的所有包都会被struts作为含有Action类的路径来搜索 -->
    20. <constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/>
    21. <!--指定禁止从Action的根包里搜索Action。默认值为false -->
    22. <constantname="struts.convention.package.locators.disable"value="false"/>
    23. <!--如果指定了该常量,Convention只会以该常量值开始的包中搜索Action类 -->
    24. <constantname="struts.convention.package.locators.basePackage"value=""/>
    25. <!--指定排除在搜索Action之外的包。默认值为org.hibernate.* ... -->
    26. <constantname="struts.convention.exclude.packages"value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
    27. <!--指定Convention映射的Result时默认支持的结果类型。默认值为dispatcher,velocity,freemarker -->
    28. <constantname="struts.convention.relative.result.types"value="dispatcher,velocity,freemarker"/>
    29. <!--设置是否重定向到斜线(/)。例如用户请求/foo,但/foo不存在时,如果设置该常量为可重定向到/foo/。默认值是true -->
    30. <constantname="struts.convention.redirect.to.slash"value="true"/></span>
          <!--设置Convention插件定位视图资源的根路径,默认为/WEB-INFO/content -->
          <constant name="struts.convention.result.path" value="/WEB-INF/content/"/>
          <!--如果设置为false,则可以将视图页面放置Action对应的目录(无需放入WEB-INFO/content) -->
          <constant name="struts.convention.result.flatLayout" value="true"/>
          <!--Convention搜索Action类的类名后缀,默认为Action -->
          <constant name="struts.convention.action.suffix" value="Action"/>
          <!--是否禁止通过包扫描Action,默认是false -->
          <constant name="struts.convention.action.disableScanning" value="false"/>
          <!--设置即使没有@Action注释,是否依然创建Action映射。默认值为false -->Create action mappings, even if no @Action is found
          <constant name="struts.convention.action.mapAllMatches" value="false"/>
          <!--设置是否所有实现com.opensymphony.xwork2.Action的Action都创建Action映射,默认是true -->
          <constant name="struts.convention.action.checkImplementsAction" value="true"/>
          <!--设置Convention映射的Action所在包的默认父包。默认值是convention-default -->
          <constant name="struts.convention.default.parent.package" value="convention-default"/>
          <!--设置映射Action时,是否将Action的name属性值转换为所有字母小写,默认值是true -->
          <constant name="struts.convention.action.name.lowercase" value="true"/>
          <!--设置映射Action时指定name属性值各单词之间的分隔符。默认值为中画线(“-”) -->
          <constant name="struts.convention.action.name.separator" value="-"/>
          <!--默认包路径包含action,actions,struts,struts2的所有包都会被struts作为含有Action类的路径来搜索 -->
          <constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>
          <!--指定禁止从Action的根包里搜索Action。默认值为false -->
          <constant name="struts.convention.package.locators.disable" value="false"/>
          <!--如果指定了该常量,Convention只会以该常量值开始的包中搜索Action类 -->
          <constant name="struts.convention.package.locators.basePackage" value=""/>
          <!--指定排除在搜索Action之外的包。默认值为org.hibernate.* ... -->
          <constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
          <!--指定Convention映射的Result时默认支持的结果类型。默认值为dispatcher,velocity,freemarker -->
          <constant name="struts.convention.relative.result.types" value="dispatcher,velocity,freemarker"/>
          <!--设置是否重定向到斜线(/)。例如用户请求/foo,但/foo不存在时,如果设置该常量为可重定向到/foo/。默认值是true -->
          <constant name="struts.convention.redirect.to.slash" value="true"/>

    下面开始了解一下Convention如何使用

    1.struts-Convention-plugin-2.1.6.jar文件复制到WEB-INF/lib路径下

    2. struts-Convention-plugin如何扫描我们的Action类的呢

    1)对于Convention插件而言,它会自动搜索位于actionactionsstrutsstruts2包下的所有java类,对于所有实现了com.opensymphony.xwork2.Actionjava类以及所有类名以Action结尾的java类都会当成Action类来处理。

    1. <spanstyle="font-family: Microsoft YaHei;"><constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/>
    2. 可以通过设置struts.convention.package.locators属性来修改这个配置。如:
    3. <constantname="struts.convention.package.locators"value="web,action"/></span>
    <constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>	
    可以通过设置struts.convention.package.locators属性来修改这个配置。如:
    <constant name="struts.convention.package.locators" value="web,action" /> 
    则定义了在项目中,包路径包含web和action的将被视为Action存在的路径来进行搜索。
    Com.ustb.web.* 或者 com.ustb.action.*都将被视为含有Action的包路径而被搜索。
    2)struts.Convention.exclude.packges::指定不扫描哪些包下的java类,位于这些包结构下的java类将不会自动映射成Action
    3) struts.convention.action.packages:Convention插件以该常量指定包作为根包来搜索Action类。Convention插件除了扫描action,actions,struts,struts2四个包的类以外,还会扫描该常量指定的一个或多个包,Convention会试图从中发现Action类。

    4) struts.convention.package.locators.basePackag: 扫描的基包,也即是,只有这个包的子包才被Struts2 Convention Plugin扫描。

    4.映射Actionname时,遵循如下两步规则:

    1)如果该Action类名包含Action后缀,将该Action类名的Action后缀去掉。否则不做任何处理。
    2)Action类名的驼峰写法(每个单词首字母大写、其他字母小写的写法)转成中画线写法(所有字母小写,单词与单词之间以中画线隔开)
    如:LoginAction映射的Acionname属性为loginGetBooks映射的Actionname的属性为get-booksAddEmployeeAction映射的Actionname属性为add-employee

    5. Convention如何确定URL的具体资源

    1)默认情况下,Convention总会到WEB应用的WEB-INF/content路径下定位物理资源,定位资源的约定是:actionRUL+resultCODE+suffix。当某个逻辑视图找不到对应的试图资源时,Convention会自动视图使用ActionURL+suffix作为物理视图资源。

    如:actions.fore.LoginAction 返回success字符串时,Convention优先考虑使用WEB-INF/content/fore目录下的login-success.jsp作为视图资源。如果找不到该文件,login.jsp也可作为对应的试图资源。如果返回input字符串,Convention会将WEB-INF/content/fore里面查找login-input.jsp

    2) 去掉类名的Action部分,然后将将每个分部的首字母转为小写,用’-’分割。
    如:UserAction->user UserDetailAction ->user-detail。结合上面的。对于com.ustb.web.user.detail.UserDetailAction,映射的 url就是/WEB-INF/content/user/detail/user-detail.jsp

     

    3)struts支持.jsp .html .htm .vm格式的文件。下面是actiong和结果模版的映射关系:

     

    URL Result
    File that could match Result Type
    /hello success /WEB-INF/content/hello.jsp Dispatcher
    /hello success /WEB-INF/content/hello-success.htm Dispatcher
    /hello success /WEB-INF/content/hello.ftl FreeMarker
    /hello-world input /WEB-INF/content/hello-world-input.vm Velocity
    /test1/test2/hello error /WEB-INF/content/test/test2/hello-error.html Dispatcher

     

     

     

     

     

     

     

    当然,简单的通过默认的方式来进行配置不能完全满足实际项目的需要。所幸,convention的零配置是非常灵活的。

    通过@Action注释
    对如下例子:

    1. package com.example.web;
    2. import com.opensymphony.xwork2.Action;
    3. import com.opensymphony.xwork2.ActionSupport;
    4. publicclass HelloAction extends ActionSupport {
    5. @Action("action1")
    6. public String method1() {
    7. return SUCCESS;
    8. }
    9. @Action("/user/action2")
    10. public String method2() {
    11. return SUCCESS;
    12. }
    13. }
    方法名 默认调用路径 默认映射路径
    method1 /hello!method1.action . /WEB-INF/content/hello.jsp
    method2 /hello!method2.action. /WEB-INF/content/hello.jsp

    通过@Action注释后

    方法名 @Action注释后调用路径 @Action注释 后映射路径
    method1 /action1!method1.action. /WEB-INF/content/action1.jsp
    method1 /user/action2!method2.action /WEB-INF/content/user/action2.jsp


    通过@Actions注释

    1. package com.example.web;
    2. import com.opensymphony.xwork2.ActionSupport;
    3. import org.apache.struts2.convention.annotation.Action;
    4. import org.apache.struts2.convention.annotation.Actions;
    5. publicclass HelloAction extends ActionSupport {
    6. @Actions({
    7. @Action("/different/url"),
    8. @Action("/another/url")
    9. })
    10. public String method1() {
    11. return “error”;
    12. }

    我们可以通过:/different/url!method1.action /another/url!method1.action 来调用method1 方法。
    对应的映射路径分别是/WEB-INF/content/different/url-error.jsp; /WEB-INF/content/another/url-error.jsp

    可能误导了大家,一个方法被@Action注释后,只是多了一种调用方式,而不是说覆盖了原来的调用方式。比如对于如下例子:

    1. package com.example.web;
    2. import com.opensymphony.xwork2.ActionSupport;
    3. import org.apache.struts2.convention.annotation.Action;
    4. import org.apache.struts2.convention.annotation.Actions;
    5. publicclass HelloAction extends ActionSupport {
    6. @Action("/another/url")
    7. public String method1() {
    8. return “error”;
    9. }

    我们调用method1方法可以通过两种方式:
    1 /hello!method1.action 映射 url:/WEB-INF/content/hello-error.jsp
    2
    /another/url!method1.action 映射 url:/WEB-INF/content/another/url-error.jsp
    可见,两种方式均可对method1方法进行调用,唯一的区别就是,两种调用的映射是不一样的,所以,想跳转到不同的界面,这是一个非常好的选择。


    通过@Namespace 注释

    1. package com.example.web;
    2. import com.opensymphony.xwork2.ActionSupport;
    3. import org.apache.struts2.convention.annotation.Action;
    4. import org.apache.struts2.convention.annotation.Actions;
    5. @Namespace("/other")
    6. publicclass HelloWorld extends ActionSupport {
    7. public String method1() {
    8. return “error”;
    9. }
    10. @Action("url")
    11. public String method2() {
    12. return “error”;
    13. }
    14. @Action("/different/url")
    15. public String method3() {
    16. return “error”;
    17. }
    18. }


    通过 /other/hello-world!method1.action 访问method1 方法。
    通过
    /other/url!method2.action 访问method2 方法
    通过
    /different /url!method3.action 访问method3 方法
    与@Action 注释不同的是,该注释覆盖了默认的namespace(这里是’/’),此时再用hello!method1.action 已经不能访问method1 了.
    @Results和@Result
    1 全局的(global)。

    全局results可以被action类中所有的action分享,这种results在action类上使用注解进行声明。

    1. package com.example.actions;
    2. import com.opensymphony.xwork2.ActionSupport;
    3. import org.apache.struts2.convention.annotation.Action;
    4. import org.apache.struts2.convention.annotation.Actions;
    5. import org.apache.struts2.convention.annotation.Result;
    6. import org.apache.struts2.convention.annotation.Results;
    7. @Results({
    8. @Result(name="failure", location="/WEB-INF/fail.jsp")
    9. })
    10. publicclass HelloWorld extends ActionSupport {
    11. public String method1() {
    12. return “failure”;
    13. }
    14. @Action("/different/url")
    15. public String method2() {
    16. return “failure”;
    17. }
    18. }

    当我们访问 /hello -world !method1.action 时,返回 /WEB-INF/fail.jsp
    当我们访问 /hello
    -world
    !method2.action 时,返回 /WEB-INF/fail.jsp
    当我们访问 /different/url!method2.action 时,返回 /WEB-INF/fail.jsp


    2 本地的(local)。
    本地results只能在action方法上进行声明。

      1. package com.example.actions;
      2. import com.opensymphony.xwork2.ActionSupport;
      3. import org.apache.struts2.convention.annotation.Action;
      4. import org.apache.struts2.convention.annotation.Actions;
      5. import org.apache.struts2.convention.annotation.Result;
      6. import org.apache.struts2.convention.annotation.Results;
      7. publicclass HelloWorld extends ActionSupport {
      8. @Action(value="/other/bar",results={@Result(name = "error", location = "www.baidu.com",type="redirect")})
      9. public String method1() {
      10. return “error”;
      11. }
      12. }
原文地址:https://www.cnblogs.com/jichunhu/p/2887013.html