Struts2中struts.xml的Action配置详解(一)===》 struts2.0中struts.xml配置文件详解 (二)==》Struts2_struts.xml配置及例程三

90 篇文章 0 订阅

struts2.0中struts.xml配置文件详解一, 二,三


struts.xml文件结构
struts.xml文件是整个Struts2框架的核心。
struts.xml文件内定义了Struts2的系列Action,定义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="example" namespace="/example" extends="struts-default">
<!-- 定义一个Action名称为HelloWorld,实现类为example.HelloWorld.java-->
<action name="HelloWorld" class="example.HelloWorld">
<!-- 任何情况下都转入到/example/HelloWorld.jsp -->
<result>/example/HelloWorld.jsp</result>
</action><action name="Login_*" method="{1}" class="example.Login">
<!-- 返回input时,转入到/example/login.jsp -->
<result name="input">/example/Login.jsp</result>
<!-- 重定向到Menu的Action -->
<result type="redirect-action">Menu</result>
</action><action name="*" class="example.ExampleSupport">
<result>/example/{1}.jsp</result>
</action>
</package>
</struts>*<result name="input">/example/Login.jsp</result>
以上表示当execute方法返回input的字符串时,跳转到/example/Login.jsp。定义rusult元素时,可以指定两个属 性:type和name。其中name指定了execute方法返回的字符串,而type指定转向的资源类型,此处转向的资源可以是JSP,也可以是 FreeMarker等,甚至是另一个Action。加载子配置文件
Struts2框架的核心配置文件就是struts.xml配置文件,该文件主要负责管理Struts2框架的业务控制器Action。
在默认情况下,Struts2框架将自动加载放在WEB-INF/classes路径下的struts.xml文件。为了避免随着应用规模的增加,而导致 的struts.xml文件过于庞大,臃肿,从而是该文件的可读性下降。我们可以将一个struts.xml配置文件分解成多个配置文件,然后在 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>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<!--通过include元素导入其他元素-->
<include file="example.xml"/>
</struts>
通过这种方式,Struts2提供了一种模块化的方式来管理struts.xml配置文件。
         使用package可以将逻辑上相关的一组Action,Result,Interceptor等组件分为一组,Package有些像对象,可以继承其他的Package,也可以被其他package继承,甚至可以定义抽象的Package。

Package的可以使用的属性: 属性
是否必须
说明

name 是 Package的表示,为了让其他的package引用

extends 否 从哪个package继承行为

namespace 否 参考Namespace配置说明

abstract 否
定义这个package为抽象的,这个package中不需要定义action


由于struts.xml文件是自上而下解析的,所以被继承的package要放在继承package的前边。
Namespace将action分成逻辑上的不同模块,每一个模块有自己独立的前缀。
使用namespace可以有效的避免action重名的冲突,例如每一个package都可以有自己独立的Menu和Help action,
但是事项方式各有不同。Struts2标签带有namespace选项,可以根据namespace的不同向服务器提交不同的package的action的请求。
   “/”表示根namespace,所有直接在应用程序上下文环境下的请求(Context)都在这个package中查找。
   “”表示默认namespace,当所有的namespace中都找不到的时候就在这个namespace中寻找。

   例如,有如下配置:
CODE:
<package name="default">
    <action name="foo" class="mypackage.simpleAction>
             <result name="success" type="dispatcher">
                  greeting.jsp
             </result>
</action>
<action name="bar" class="mypackage.simpleAction">
   <result name="success" type="dispatcher">bar1.jsp</result>
</action>
</package>

<package name="mypackage1" namespace="/">
<action name="moo" class="mypackage.simpleAction">
       <result name="success" type="dispatcher">moo.jsp</result>
</action>
</package>

<package name="mypackage2" namespace="/barspace">
<action name="bar" class="mypackage.simpleAction">
   <result name="success" type="dispatcher">bar2.jsp</result>
</action>
</package>1 如果请求为/barspace/bar.action
查找namespace:/barspace,如果找到bar则执行对应的action,否则将会查找默认的namespace,在上面的例子中,在 barspace中存在名字为bar的action,所以这个action将会被执行,如果返回结果为success,则画面将定为到bar2.jsp

2 如果请求为/moo.action
根namespace('/')被查找,如果moo action存在则执行,否则查询默认的namespace,上面的例子中,根namespace中存在moo action,所以该action被调用,返回success的情况下画面将定位到moo.jsp、

Action配置

   在struts2框架中每一个Action是一个工作单元。Action负责将一个请求对应到一个Action处理上去,每当一个Action类匹配一个请求的时候,这个Action类就会被Struts2框架调用。

   一个Action配置示例:
CODE:
<action name="Logon" class="tutorial.Logon">
   <result type="redirect-action">Menu</result>
   <result name="input">/tutorial/Logon.jsp</result>
</action>每一个Action可以配置多个result,多个ExceptionHandler,多个Intercepter,但是只能有一个name,这个name和package的namespace来唯一区别一个Action。

   每当struts2框架接受到一个请求的时候,它会去掉Host,Application和后缀等信息,得到Action的名字,例如如下的请求将得到Welcome这个Action。http://www.planetstruts.org/struts2-mailreader/Welcome.action

   在一个Struts2应用程序中,一个指向Action的链接通常有Struts Tag产生,这个Tag只需要指定Action的名字,Struts框架会自动添加诸如后缀等的扩展,例如:
CODE:
<s:form action="Hello">
<s:textfield label="Please enter your name" name="name"/>
<s:submit/>
</s:form将产生一个如下的链接的请求:
http://Hostname:post/appname/Hello.action
在定义Action的名字的时候不要使用.和/,最好使用英文字母和下划线。

Action中的方法

Action的默认入口方法由xwork2的Action接口来定义,代码清单为:
CODE:
public interface Action {

public String execute() throws Exception;

}有些时候我们想指定一个Action的多个方法,我们可以做如下两步:
  建立一些execute签名相同的方法,例如:
Public String forward() throws Exception

  在Action配置的时候使用method属性,例如:
<action name="delete" class="example.CrudAction" method="delete">

Action中的方法通配符

有些时候对Action中方法的调用满足一定的规律,例如edit Action对应edit方法,delete Action对应 delete方法,这个时候我们可以使用方法通配符,例如:
<action name="*Crud" class="example.Crud" method="{1}"> 这时,editCrud Action的引用将调用edit方法,同理,deleteCrud Action的引用将调用delete 方法。

另外一种比较常用的方式是使用下划线分割,例如:
<action name="Crud_*" class="example.Crud" method="{1}">
这样当遇到如下调用的时候可以找到对应的方法。
"action=Crud_input"   =>   input方法
"action=Crud_delete" =>   delete方法

通配符和普通的配置具有相同的地位,可以结合使用框架的所有其他功能。

默认的Action

当我们没有指定Action的class属性的时候,例如:
<action name="Hello">
我们默认使用com.opensymphony.xwork.ActionSupport
ActionSupport有两个方法input和execute,每个方法都是简单的返回SUCCESS。

通常情况下,请求的Action不存在的情况下,Struts2框架会返回一个 Error画面:“404 - Page not found”,有些时候或许我们不想出现一个控制之外的错误画面,我们可以指定一个默认的Action,在请求的Action不存在的情况下,调用默认的 Action,通过如下配置可以达到要求:
CODE:
<package name="Hello" extends="action-default">
<default-action-ref name="UnderConstruction">
<action name="UnderConstruction">
   <result>/UnderConstruction.jsp</result>
</action>默认通配符
CODE:
<action name="*" >
   <result>/{1}.jsp</result>
</action>每个Action将会被映射到以自己名字命名的JSP上。

struts2中动态方法的调用

可以采用DMI(Dynamic Method Invocation,动态方法)调用来处理这种请求,动态方法调用是指表单元素的action并不是直接等于某个Action的名字,而是以如下形式来指定Form的action属性:
<!-- action属性为actionName!methodName的形式 -->
action="ActionName!methodName.action"<!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>




转自:http://hi.baidu.com/deb_ug/blog/item/a5f92350c06db214377abe00.html

 

struts2.0中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节点是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>

补充:

struts.xml是我们在开发中利用率最高的文件,也是Struts2中最重要的配置文件。

一下分别介绍一下几个struts.xml中常用到的标签

1、<include>

利用include标签,可以将一个struts.xml配置文件分割成多个配置文件,然后在struts.xml中使用<include>标签引入其他配置文件。

比如一个网上购物程序,可以把用户配置、商品配置、订单配置分别放在3个配置文件user.xml、goods.xml和order.xml中,然后在struts.xml中将这3个配置文件引入:

struts.xml:

?
1
2
3
4
5
6
7
8
9
10
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< struts >
     < include file = "user.xml" />
     < include file = "goods.xml" />
     < include file = "order.xml" />
</ struts >

 

user.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< struts >
     < package name = "wwfy" extends = "struts-default" >
         < action name = "login" class = "wwfy.user.LoginAction" >
             <!--省略Action其他配置-->
         </ action >
         < action name = "logout" class = "wwfy.user.LogoutAction" >
             <!--省略Action其他配置-->
         </ action >
     </ package >
</ struts >

 

2、<constant>

在之前提到struts.properties配置文件的介绍中,我们曾经提到所有在struts.properties文件中定义的属性,都可以配置在struts.xml文件中。而在struts.xml中,是通过<constant>标签来进行配置的:

?
1
2
3
4
5
6
7
8
9
10
11
12
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< struts >
     <!--设置开发模式-->
     < constant name = "struts.devMode" value = "true" />
     <!--设置编码形式为GB2312-->
     < constant name = "struts.i18n.encoding" value = "GB2312" />
     <!--省略其他配置信息-->
</ struts >

 

3、<package>

1、包属性介绍

在Struts2框架中是通过包来管理action、result、interceptor、interceptor-stack等配置信息的。包属性如下:

属性

是否必需

描述

name包名,作为其它包应用本包的标记
extends设置本包继承其它包
namespace设置包的命名空间
abstact设置为抽象包

 

2、extends属性的详解

  • 当一个包通过配置extends属性继承了另一个包的时候,该包将会继承父包中所有的配置,包括action、result、interceptor等。
  • 由于包信息的获取是按照配置文件的先后顺序进行的,所以父包必须在子包之前被定义。
  • 通常我们配置struts.xml的时候,都继承一个名为“struts-default.xml”的包,这是struts2中内置的包。

 

3、namespace的详解

namespace主要是针对大型项目中Action的管理,更重要的是解决Action重名问题,因为不在同一个命名空间的Action可以使用相同的Action名的。

1)如果使用命名空间则URL将改变

比如我们有一下配置文件

?
1
2
3
4
5
< package name = "wwfy" extends = "struts-default" >
     < action name = "login" class = "wwfy.action.LoginAction" >
         < result >/success.jsp</ result >
     </ action >
</ package >

 

则此配置下的Action的URL为http://localhost:8080/login.action

 

假如为这个包指定了命名空间

?
1
2
3
4
5
< package name = "wwfy" extends = "struts-default" namespace = "/user" >
     < action name = "login" class = "wwfy.action.LoginAction" >
         < result >/success.jsp</ result >
     </ action >
</ package >

 

则此配置下的Action的URL为http://localhost:8080/user/login.action

2)默认命名空间

Struts2中如果没有为某个包指定命名空间,该包使用默认的命名空间,默认的命名空间总是""。

3)指定根命名空间

当设置了命名空间为“/”,即指定了包的命名空间为根命名空间时,此时所有根路径下的Action请求都会去这个包中查找对应的资源信息。

假若前例中路径为http://localhost:8080/login.action则所有http://localhost:8080/*.action都会到设置为根命名空间的包中寻找资源。

 

4、<action>与<result>

1、<action>属性介绍

属性名称

是否必须

功能描述

name请求的Action名称
classAction处理类对应具体路径
method指定Action中的方法名
converter指定Action使用的类型转换器

如果没有指定method则默认执行Action中的execute方法。

2、<result>属性介绍

属性名称

是否必须

功能描述

name对应Action返回逻辑视图名称,默认为success
type返回结果类型,默认为dispatcher

 

3、通配符的使用

随着result的增加,struts.xml文件也会随之变得越来越复杂。那么就可以使用通配符来简化配置:

例如下面这个案例:

Action为Test.Java

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
     public String test1(){
         return "result1" ;
     }
      
     public String test2(){
         return "result2" ;
     }
      
     public String test3(){
         return "result3" ;
     }
}

 

struts.xml中配置为

?
1
2
3
4
5
< package name = "wwfy" extends = "struts-default" >
     < action name = "test*" class = "wwfy.action.test{1}" >
         < result name = "result{1}" >/result{1}.jsp</ result >
     </ action >
</ package >

4、访问Action方法的另一种实现方式

在Struts2中如果要访问Action中的指定方法,还可以通过改变URL请求来实现,将原本的“Action名称.action”改为“Action名称!方法名称.action”在struts.xml中就不需要指定方法名了。

 

5、<exception-mapping>与<global-exception-mapping>

这两个标签都是用来配置发生异常时对应的视图信息的,只不过一个是Action范围的,一个是包范围的,当同一类型异常在两个范围都被配置时,Action范围的优先级要高于包范围的优先级.这两个标签包含的属性也是一样的:

属性名称

是否必须

功能描述

name用来表示该异常配置信息
result指定发生异常时显示的视图信息,这里要配置为逻辑视图
exception指定异常类型

 

两个标签的示例代码为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< struts >
     < package name = "default" extends = "struts-default" >
         < global-exception-mappings >
             < exception-mapping result = "逻辑视图" exception = "异常类型" />
         </ global-exception-mappings >
         < action name = "Action名称" >
             < exception-mapping result = "逻辑视图" exception = "异常类型" />
         </ action >
     </ package >
</ struts >

 

6、<default-class-ref>

当我们在配置Action的时候,如果没有为某个Action指定具体的class值时,系统将自动引用<default-class-ref>标签中所指定的类。在Struts2框架中,系统默认的class为ActionSupport,该配置我们可以在xwork的核心包下的xwork-default.xml文件中找到。

有特殊需要时,可以手动指定默认的class

?
1
2
3
4
5
6
7
package wwfy.action;
  
public class DefaultClassRef {
     public void execute(){
         System.out.println( "默认class开始执行……" );
     }
}

 

在struts.xml中配置

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< 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>

如果在请求一个没有定义过的Action资源时,系统就会抛出404错误。这种错误不可避免,但这样的页面并不友好。我们可以使用<default-action-ref>来指定一个默认的Action,如果系统没有找到指定的Action,就会指定来调用这个默认的Action。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< 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中找到相关配置:

?
1
< default-interceptor-ref name = "defaultStack" />

 

在实际开发过程中,如果我们有特殊的需求是可以改变默认拦截器配置的。当时一旦更改这个配置,“defaultStack”将不再被引用,需要手动最加。

 

9、<interceptors>

通过该标签可以向Struts2框架中注册拦截器或者拦截器栈,一般多用于自定义拦截器或拦截器栈的注册。该标签使用方法如下:

?
1
2
3
4
5
6
< 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>标签统一配置这些物理视图所对应的逻辑视图。

?
1
2
3
4
5
6
7
8
9
10
11
12
<? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE struts PUBLIC
     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  
< struts >
     < package name = "wwfy" extends = "struts-default" >
         < global-results >
             < result name = "test" >/index.jsp</ result >
         </ global-results >
     </ package >
</ struts >

 

Struts2_struts.xml配置及例程


struts.xml配置及例程


1.配置文件的优先级

在struts2中一些配置(比如常量)可以同时在struts-default.xml(只读性),strtus-plguin.xml(只读性),struts.xml,struts.properties和web.xml文件中配置,它们的优先级逐步升高,即是说后面的配置会覆盖掉前面相同的配置。

2.配置形式

下面以对struts.i18n.encoding=UTF-8的配置为例进行说明:

在struts.xml配置形式如下:


[html]  view plain  copy
  1. <constant name="struts.i18n.encoding" value="gbk"></constant>  

在struts.properties的配置形式如下:

[html]  view plain  copy
  1. struts.i18n.encoding=UTF-8  


在web.xml中配置如下:

[html]  view plain  copy
  1. <filter>  
  2.   
  3. <filter-name>struts2</filter-name>  
  4.   
  5. <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter  
  6.   
  7. </filter-class>  
  8.   
  9. <init-param>  
  10.   
  11. <param-name>struts.i18n.encoding</param-name>  
  12.   
  13. <param-value>UTF-8</param-value>  
  14.   
  15. </init-param>  
  16.   
  17. </filter>  


说明:官方声称配置了此常量可以解决中文乱码问题,但实事上并不能达到目的,在前面的三个项目中,如果我们在表单中输入中文,其结果是会出现乱码。解决此问题参看 [.7 的注意] 。这是 struts2.1.6 中的一 bug, 它的下一版 2.1.8 已解决此问题。

3.package配置相关

属性名

是否必须

说明

Name

Package的唯一标识,不允许同名

Extends 

指定要继承的包

Namespace

指定名称空间

Abstract

声明包为抽象否

下面我们建立struts2package项目来进行package相关测试:

说明:在上面的配置文件中所用到的Test1Action和Test2Action这两个Action都只是继承了com.opensymphony.xwork2.ActionSupport类,而ActionSupport默认返回的就是“success”,所以当点击上面的链接分别转到了forward目录下的test1.jsp和test2.jsp。下面重点来看这个package元素的namespace属性及action的name属性,它们共同定义了action所映射到的实质文件。上图展示了链接地址和action的对应关系,所以当我们要想访问一个action所关联到的jsp文件时,应该用namespace+action的name 关于它的内容测试可以参考struts2package项目。 
补充:通常情况下,action元素的name是属性值是不能出现“/”的,所以希望通过action中name属性来实现多级映射,需要在sturts.xml中增加如下属性:

[html]  view plain  copy
  1. <constant name="struts.enable.SlashesInActionNames" value="true"/> 这样配置后就可以再action的name元素中使用“/”了。比如:  
  2. <package name="tt3" extends="struts-default">  
  3.   
  4. <action name="test3/test3" class="com.asm.Test3Action">  
  5.   
  6. <result name="success">/forward/test3.jsp</result>  
  7.   
  8. </action>  
  9.   
  10. </package>  


然后输入<a href="<%=path%>/test3/test3.action">test3</a><br>链接地址就可以访问了

强调:namespace默认值“”,即不配置namespace属性。它的意思是:如果action不能进行完整路径匹配,则会来此namespace下进行匹配,比如:.../test/test/test.action,如果参照namespace及action的name不能找到也之完全对应的action,它会再到依次追溯到上级目录中查找,即是说它会以…/test/test.action这样的路径来对应namespace和action的name进行查找。如果返回到最终的目录仍找不到,它就会到namespace="/"对应的包下查找名为test的action,如果仍找不到,它就会去默认的namespace下查找名为test的action,如果找到则执行此action。另外,namespace也可以配置成namespace="/"。它代表配置为项目的根。 总结action的名称探索顺序:完全对应、逐步追溯到上级目录查找、"/"下查找、默认namespace下查找。

为什么要提出namespace,主要是避免多人共同开发项目出现名字冲突。如果不使用namespace,多个人所写的action中可能出现重名的现象,这样当项目合并时就会出现冲突。而有了namespace可以在项目开发时由项目经理给每一个人分不同的namespace,这样每个开发人员只需要保证自己所写的action不同名即可。
namespace引发的链接问题:当我们为action配置了namespace时,访问此action的形式总会是如下形式:.../webappname/xxx/yyy/ActionName.action 而当此action成功执行跳转到某个jsp页面时,如想在此jsp页面写链接,一定要写绝对路径,因为相对路径是相对.../webappname/xxx/yyy/,而如果以后我们修改了action的namespace时,相对路径又要变,所以链接不能写成相对路径。 以下介绍绝对路径的写法:通常用myeclipse开发时建立一个jsp文件,默认总会有如下内容:

[java]  view plain  copy
  1. <%  
  2.   
  3. String path = request.getContextPath();  
  4.   
  5. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  6.   
  7. %>  


我们写绝对路径可以参此内容。还可以参<head>下的<base href="<%=basePath%>"> 来完成绝对路径的书写。

4.分工合作include:指定多个配置文件

比如让jack来单独开发一个action,在jack.xml中的配置文件为:

[html]  view plain  copy
  1. <struts>  
  2.   
  3. <package name="jack" namespace="/jack" extends="struts-default">  
  4.   
  5. <action name="test4" class="com.asm.Test4Action">  
  6.   
  7. <result name="success">/forward/test4.jsp</result>  
  8.   
  9. </action>  
  10.   
  11. </package>  
  12.   
  13. </struts>  


然后在struts.xml文件中增加如下内容:<include file="jack.xml"></include> 它实质就是把jack.xml中的<package>及其内容写进struts.xml中的<struts>根元素下。

链接:<a href="<%=path %>/jack/test4.action">test4</a> 这样便可以访问到了forward目录下的test4.jsp了。

5.tomcat认证访问

接上例:namespce的作用除了在前面提到的避免协同开发名字冲突外,还为认证提供一个条件。比如jack开发的东西所关联到的页面需要权限才能被访问。由于多为tomcat中的内容,下面只列出步骤。
步骤一,tomcatconf目录下tomcat-users.xml内容如下:

[html]  view plain  copy
  1. <?xml version='1.0' encoding='utf-8'?>  
  2.   
  3. <tomcat-users>  
  4.   
  5.   <role rolename="manager"/>  
  6.   
  7.   <role rolename="admin"/>  
  8.   
  9.   <user username="jack" password="jack" roles="admin,manager"/>  
  10.   
  11.   <user username="tom" password="tom" roles="manager"/>  
  12.   
  13. </tomcat-users>  


步骤二,在web.xml中增加如下内容:

[html]  view plain  copy
  1. <security-constraint>  
  2.   
  3. <web-resource-collection>  
  4.   
  5. <web-resource-name>jack</web-resource-name>  
  6.   
  7. <url-pattern>/jack/*</url-pattern>  
  8.   
  9. <http-method>POST</http-method>  
  10.   
  11. <http-method>GET</http-method>  
  12.   
  13. </web-resource-collection>  
  14.   
  15. <auth-constraint>  
  16.   
  17. <role-name>admin</role-name>  
  18.   
  19. </auth-constraint>  
  20.   
  21. </security-constraint>  
  22.   
  23. <security-role>  
  24.   
  25. <role-name>admin</role-name>  
  26.   
  27. </security-role>  
  28.   
  29. <login-config>  
  30.   
  31. <auth-method>BASIC</auth-method>  
  32.   
  33. <realm-name>input authentication message</realm-name>  
  34.   
  35. </login-config>  


这样配置完成后,当我们访问.../jack中的任何内容都会要求输入密码认证信息,认证时输入tomcat-users.xml配置的admin权限的用户名和密码即可访问(这里就只有jack用户名可以访问)

6.初识拦截器

拦截器能在action被调用之前和被调用之后执行一些“代码”。Struts2框架的大部分核心功能都是通过拦截器来实现的,如防止重复提交、类型转换、对象封装、校验、文件上传、页面预装载等等,都是在拦截器的帮助下实现的。每一个拦截器都是独立装载的(pluggable),我们可以根据实际的需要为每一个action配置它所需要的拦截器。 

在myStruts2项目下,重新对配置文件作如下修改:

[html]  view plain  copy
  1. <package name="myFirst" namespace="/" extends="struts-default">  
  2.   
  3. <interceptors>  
  4.   
  5. <interceptor name="timer"  
  6.   
  7. class="com.opensymphony.xwork2.interceptor.TimerInterceptor" />  
  8.   
  9.   
  10. <interceptor name="params"                                                                               class="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />  
  11.   
  12. </interceptors>  
  13.   
  14. <action name="login" class="com.asm.LoginAction">  
  15.   
  16. <interceptor-ref name="timer"></interceptor-ref>  
  17.   
  18. <interceptor-ref name="params"></interceptor-ref>  
  19.   
  20. <result name="loginSuccess">/success.jsp</result>  
  21.   
  22. <result name="loginFailure">/failure.jsp</result>  
  23.   
  24. </action>  
  25.   
  26. </package>  


首先在package中定义了两个拦截器,然后在login action中引用了这两个拦截器,需要说明的是这里使用的拦截器都是系统自带的拦截器。其实在extends所继承的struts-default中就包含了很多拦截器,也包括我们这里所用的拦截器,但如果在此action中不使用params拦截器,将会报空指针错,因为params拦截器的作用是传递表单参数,如果不使用此拦截器就不能在action中得到表单参数,所以引用时会报空指针错。虽然extends继承的strust-default自带有params拦截器,但是当我们自己引用了拦截器时,继承struts-default将不会再为我们分配默认的拦截器(有点类似构造器),但是我们仍然可以通过<interceptor-ref name="defaultStack"/>来继续使用struts-defalut的拦截器。补充:由于上面的package继承于struts-default,而我们这里所用到的timer和params都是在struts-defalut中定义过,所以即使我们在<interceptors>中没有定义过这两个拦截器,也可以直接在action中引用。

使用</interceptor-stack>组合多个拦截器:比如我们想把上面的params和timer这两个拦截器组合:

[html]  view plain  copy
  1. <interceptor-stack name="timer_param">  
  2.   
  3. <interceptor-ref name="timer" />  
  4.   
  5. <interceptor-ref name="params" />  
  6.   
  7. </interceptor-stack>  


然后再在action引用<interceptor-ref name="timer_param"/>”,效果和分别引用两个是一样的。其实我们使用strtus-default中的<interceptor-ref name="defaultStack"/>也是使用interceptor-stack方式。

7.Action中的method属性

在struts1.x中我们知道通过继承DispatchAction可以实现把多个Action进行统一操作,在struts2中实现action的统一操作也很简单。我们以crud操作为例,把crud集中到一个Action中。
步骤一、建立CRUDAction,内容如下:

[java]  view plain  copy
  1. package com.asm;  
  2.   
  3. import com.opensymphony.xwork2.ActionSupport;  
  4.   
  5. public class CRUDAction extends ActionSupport {  
  6.   
  7. public String add() {  
  8.   
  9. return "success";  
  10.   
  11. }  
  12.   
  13. public String del() {  
  14.   
  15. return "success";  
  16.   
  17. }  
  18.   
  19. public String update() {  
  20.   
  21. return "success";  
  22.   
  23. }  
  24.   
  25. public String query() {  
  26.   
  27. return "success";  
  28.   
  29. }  
  30.   
  31. }  


步骤二、配置此Action,为了清晰明了,专为此Action,建立一个配置文件crud.xml,主要内容如下:

[html]  view plain  copy
  1. <struts>  
  2.   
  3. <package name="crud" extends="struts-default" namespace="/crud">  
  4.   
  5. <action name="add" class="com.asm.CRUDAction" method="add">  
  6.   
  7. <result name="success">/crud/addSuccess.jsp</result>  
  8.   
  9. </action>  
  10.   
  11. <action name="del" class="com.asm.CRUDAction" method="del">  
  12.   
  13. <result name="success">/crud/delSuccess.jsp</result>  
  14.   
  15. </action>  
  16.   
  17. <action name="update" class="com.asm.CRUDAction" method="update">  
  18.   
  19. <result name="success">/crud/updateSuccess.jsp</result>  
  20.   
  21. </action>  
  22.   
  23. <action name="query" class="com.asm.CRUDAction" method="query">  
  24.   
  25. <result name="success">/crud/querySuccess.jsp</result>  
  26.   
  27. </action>  
  28.   
  29. </package>  
  30.   
  31. </struts>  


分析:上面的method方法的值来源于CRUDAction中方法的名字,这样当我们访问上面的每一个Action时,它实质是和method指定的方法关联上。

步骤三、把crud.xml配置文件并入struts.xml中,只需增加如下代码:
<include file="jack.xml"></include>

步骤四、编写相应的jsp页面,在此略去crud文件夹下的四个跳转jsp页面(addSuccess.jsp等),重点是crud.jsp页面。内容如下:

[html]  view plain  copy
  1. <html>  
  2.   
  3. <%  
  4.   
  5. String path=request.getContextPath();  
  6.   
  7. %>  
  8.   
  9. <body>  
  10.   
  11. <a href="<%=path %>/crud/add.action">添加数据</a><br>  
  12.   
  13. <a href="<%=path %>/crud/del.action">删除数据</a><br>  
  14.   
  15. <a href="<%=path %>/crud/query.action">查询数据</a><br>  
  16.   
  17. <a href="<%=path %>/crud/update.action">修改数据</a><br>  
  18.   
  19. </body>  
  20.   
  21. </html>  


步骤五、发布测试。
补充扩展,动态调用DMI:不使用method实现统一.我们在crud.xml中增加如下内容:

[html]  view plain  copy
  1. <action name="op" class="com.asm.CRUDAction">  
  2.   
  3. <result name="success">/crud/op.jsp</result>  
  4.   
  5. </action>  


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

[html]  view plain  copy
  1. <a href="<%=path %>/crud/op!add.action">添加数据</a><br>  
  2.   
  3. <a href="<%=path %>/crud/op!del.action">删除数据</a><br>  
  4.   
  5. <a href="<%=path %>/crud/op!query.action">查询数据</a><br>  
  6.   
  7. <a href="<%=path %>/crud/op!update.action">修改数据</a><br>  


注意查看上面的链接地址,它们都是针对op action,然后再加地上“!+CRUDAction中相应的方法名”,最后再写上.action即可以访问到统一页面op.jsp。这样做虽然能减少页面,但是由于它们实质用到的是同一个Action,所以这就意味着我们要使用的拦截器相同,相同的跳转result。实际中这种方式很少使用,在此略作了解。如果不想使用动态方法调用,我们可以通过常量来关闭,即在struts.xml中增加如下配置:
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>

扩展2:在CRUDAction中使用do。举例:我们在CRUDAction中增加一个新的方法,内容如下:

[java]  view plain  copy
  1. public String doMain(){  
  2.   
  3. return "success";  
  4.   
  5. }  


然后再在在crud.xml中增加如下内容:

[html]  view plain  copy
  1. <action name="main" class="com.asm.CRUDAction" method="main">  
  2.   
  3. <result name="success">/crud/main.jsp</result>  
  4.   
  5. </action>  


注意:配置中method属性值是doMain中去掉do后M小写。然后再在crud.jsp中增加如下链接:
<a href="<%=path %>/crud/main.action">main页面</a><br>

随后便可以访问到.../crud/main.jsp页面了。

8.使用ForwardAction实现页面屏蔽。

我们在jsp页面之间写链接总会是.../xxx.jsp,而如果我们想屏蔽掉具体的jsp,只需要所jsp页面配置成一个ForwardAction即可实现。示例如下:在根目录下有一个index.jsp主页,我们strtus.xml中作如下配置:

[html]  view plain  copy
  1. <package name="def" extends="struts-default">  
  2.   
  3. <action name="forward">  
  4.   
  5. <result >/index.jsp</result>  
  6.   
  7. </action>  
  8.   
  9. </package>  


说明:如果没有未action指定class,默认就是ActionSupport类,如果没有为action指定method属性,则默认执行execute方法,如果没有指定result的name属性,默认值为success。知道了这些再结合ActionSupport的源码就不难理解实现转发的原理了。
随后再在前面第7点扩展中用到的op.jsp中增加如下代码:
<a href="<%=request.getContextPath()%>/forward.action">forward</a>

最后再测试访问op.jsp,在op.jsp中页面中直接点链接便可以跳到index.jsp,观察地址栏发现此时跳到index页面是进行的服务器跳转,如果我们在上面的配置中的result增加type属性变成<result type="redirect">/index.jsp</result>,实现的跳转就是客户端跳转。 补充:像这种forward形式的action实质是执行的ActionSupport 这个Action。因此配置它的result可以参看此类的api文档,比如它常用的result name有:success、login、input等。

8.使用default-Action配置统一访问

default-action-ref,当访问没有找到对应的action时,默认就会调用default-action-ref指定的action.同样在上面的package中增加如下内容:

[html]  view plain  copy
  1. <default-action-ref name="error"></default-action-ref>  
  2.   
  3. <action name="error">  
  4.   
  5. <result>/other/error.jsp</result>  
  6.   
  7. </action>  


上面一段内容就是说当我们访问的action不能被找到时便指向名为error的action中去,接着我们在下面配置了这个error Action。但是要注意,一个package内只配置一个<default-action-ref>,如果配置多个,就无法预测结果了. 此时我们只要输入.../myStruts2/luanFangWen.action这样的形式,它就会去访问这个默认的<default-action-ref>,通常我们会为它配置一个错误页面,以提示用户访问的页面不存在。 在web开发中,我们还可以把这个默认的action访问配置成主页,这样当用户访问一些不存在的action时,总会跳到主页上去。

通过此配置,只要是访问一个不存在的action便会转向到.../other目录下的error.jsp页面。但是如果访问是其它的不存在资源则仍是报tomcat所标识的404错误,我们可以在web.xml中作如下配置:

[html]  view plain  copy
  1. <error-page>  
  2.   
  3. <error-code>404</error-code>  
  4.   
  5. <location>/other/404error.jsp</location>  
  6.   
  7. </error-page>  


这样配置后,访问错误页面将跳到.../other/404error.jsp页面中去。补充说明:如果我们用ie访问时,如果选中了[工具][IE选项][高级][浏览][显示友好的http错误信息],则配置的错误页面将失效,因为找不到资源时会报HTTP404错误,而ie截取到此错误进行了它自身的友好处理,所以我们设置<error-page>就失效。

小结Action

在struts2中一个普通的Java类只要有public String execute()这样的方法都可以配置成一个Action,另外我们可以实现Action接口来使java类成为一个Action,但通常的做法是继承ActionSupport类,这也是以后的项目中惯用的方法,也是推荐的首选方法。 与struts1.x不同的是:在struts2中每一个Action被请求访问时都会new出这个Action对象,所以Action本身不存在线程安全的问题。

9.使用通配符

建立struts2wildcard项目,此实例基本仿照前面前面第7点的实例改写而成。为了使用通配符,只需要改写配置文件即可。此实例未使用通配时的配置文件如下:

[html]  view plain  copy
  1. <action name="addUser" class="com.asm.UserAction" method="addUser">  
  2.   
  3. <result name="success">/user/addUser.jsp</result>  
  4. </action>  
  5.   
  6. <action name="delUser" class="com.asm.UserAction" method="delUser">  
  7.   
  8. <result name="success">/user/delUser.jsp</result>  
  9.   
  10. </action>  
  11.   
  12. <action name="queryUser" class="com.asm.UserAction" method="queryUser">  
  13.   
  14. <result name="success">/user/queryUser.jsp</result>  
  15.   
  16. </action>  
  17.   
  18. <action name="updateUser" class="com.asm.UserAction" method="updateUser">  
  19.   
  20.     <result name="success">/user/updateUser.jsp</result>  
  21.   
  22. </action>  


我们注释掉上面的配置,使用通配符只需如下内容即可达到相同的效果:

[html]  view plain  copy
  1. <action name="*User" class="com.asm.UserAction" method="{1}User">  
  2.   
  3. <result name="success">/user/{1}User.jsp</result>  
  4.   
  5. </action>  

原理:当有.../addUser.action请求时,如果不能在当前应用中找到完全相同的addUser名字的Action时,通配符配置这时就起作用了,按通配原则,它便和上面的name="*User"相配成功,这里不难明了*此时代指的内容是add,再来看method恰恰是引用第一个*的内容,所以它的method此时的完整名为addUser,它刚好和com.asmUserAction中的addUser方法相对,所以它会去addUser方法,再来看下面的result配置所指代的页面,它也用到了{1},所以它的完整页面是/addUser.jsp。其实如果我们有良好的编程命名习惯,所有的Action我们都只需要进行一次配置。举例:规定所有的Action类都用XXXAction来命名,类中所有的CRUD方法都用add/del/update/query。Jsp页面也用add/del/update/query_XXX.jsp这样的形式。即配置文件可以写成如下形式:

[html]  view plain  copy
  1. <action name="*_*" class="com.asm.{2}Action" method="{1}">  
  2.   
  3. <result name="success">.../{1}_{2}.jsp</result>  
  4.   
  5. </action>  

Name中第一个*代表CRUD操作的名字,第二个*代表类的名字。所以访问链接地址举例如下:

.../del_User.action将访问到User类的del方法,成功后跳到del_User.jsp页面。补充说明{0}是代表name中所有的*组合。

10.使用0配置:ZERO Annotation





11.Result配置详解

说明:在前面的许多案例中我们所用到的Action基本都继承自ActionSupport这个类,而在这个类中我们定义了五个字段:SUCCESS,NONE,ERROR,INPUT,LOGING。我们可以直接返回这些字段值,这些字段值实质是被定义成:String SUCCESS=”success”这样的形式,所以我们只要在Result元素中用它们的小写即可。
<result>标准完整形式如下:

[html]  view plain  copy
  1. <result name="success" type="dispatcher">  
  2.   
  3. <param name="location">/default.jsp</param>  
  4.   
  5. </result>  


如果我们都采用默认的形式,最终可以简写成:<result>/default.jsp</result>

探讨type类型:

Type类型值

作用说明

对应类

chain

用来处理Action链

com.opensymphony.xwork2.ActionChainResult

dispatcher

用来转向页面,通常处理JSP

org.apache.struts2.dispatcher.ServletDispatcherResult

redirect

重定向到一个URL

org.apache.struts2.dispatcher.ServletRedirectResult

redirectAction

重定向到一个Action

org.apache.struts2.dispatcher.ServletActionRedirectResult 

plainText

显示源文件内容,如文件源码

org.apache.struts2.dispatcher.PlainTextResult

freemarker

处理FreeMarker模板

org.apache.struts2.views.freemarker.FreemarkerResult

httpheader

控制特殊http行为的结果类型

org.apache.struts2.dispatcher.HttpHeaderResult

stream

向浏览器发送InputSream对象,通常用来处理文件下载,还可用于返回AJAX数据。

org.apache.struts2.dispatcher.StreamResult

velocity

处理Velocity模板

org.apache.struts2.dispatcher.VelocityResult

xslt   

  处理XML/XLST模板

 org.apache.struts2.views.xslt.XSLTResult 

以上对type类型作简要的说明,下面来看实例:当一个Action处理后要返回的Result是另一个Action时,作如何配置,关键就是配置type类型。下面建立struts2result项目说明
步骤一:建立两个Action:TestAction、Test2Action
步骤二:web.xml配置省略。struts.xml主要配置内容如下:

[html]  view plain  copy
  1. <struts>  
  2.   
  3. <package name="resultTest" extends="struts-default">  
  4.   
  5. <action name="test" class="com.asm.TestAction">  
  6.   
  7. <result name="success" type="chain">  
  8.   
  9. <param name="actionName">test2</param>  
  10.   
  11. </result>  
  12.   
  13. </action>  
  14.   
  15. <action name="test2" class="com.asm.Test2Action">  
  16.   
  17. <result name="success">/test2Suc.jsp</result>  
  18.   
  19. </action>  
  20.   
  21. </package>  
  22.   
  23. </struts>  


[html]  view plain  copy
  1. <struts>  
  2.   
  3. <package name="resultTest" extends="struts-default">  
  4.   
  5. <action name="test" class="com.asm.TestAction">  
  6.   
  7. <result name="success" type="chain">  
  8.   
  9. <param name="actionName">test2</param>  
  10.   
  11. </result>  
  12.   
  13. </action>  
  14.   
  15. <action name="test2" class="com.asm.Test2Action">  
  16.   
  17. <result name="success">/test2Suc.jsp</result>  
  18.   
  19. </action>  
  20.   
  21. </package>  
  22.   
  23. </struts>  

[html]  view plain  copy
  1. <struts>  
  2.   
  3. <package name="resultTest" extends="struts-default">  
  4.   
  5. <action name="test" class="com.asm.TestAction">  
  6.   
  7. <result name="success" type="chain">  
  8.   
  9. <param name="actionName">test2</param>  
  10.   
  11. </result>  
  12.   
  13. </action>  
  14.   
  15. <action name="test2" class="com.asm.Test2Action">  
  16.   
  17. <result name="success">/test2Suc.jsp</result>  
  18.   
  19. </action>  
  20.   
  21. </package>  
  22.   
  23. </struts>  

说明:在名为“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中写成:
[html]  view plain  copy
  1. <result name="success" type="redirect">  
  2. /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中,所以采用了#的方式来取出值。图示说明:

步骤三,编写链接页面index.jsp。发布测试:

全局result

如果我们所有的action均有可能跳到相同的页面,则不防使用全局result。为了方便引用我们专门建立一个package来存放公共的result。在会用到个全局的跳转时,只需要把继承自这个公共的package即可。

建立公共包,代码如下:

[html]  view plain  copy
  1. <package name="pubResult" extends="struts-default" abstract="true">  
  2.   
  3. <global-results>  
  4.   
  5. <result name="error">/error.jsp</result>  
  6.   
  7. </global-results>  
  8.   
  9. </package>   


由于它下面没的action配置,所以我们可以像默认的struts-default包一样,声明abstract=true,这样声明表示此packgage下不会有action,它一般是用来让别的package继承。随后再在要用到全局result中引用这个公共的package。代码如下:

[html]  view plain  copy
  1. <package name="testGlobal" extends="pubResult" >  
  2.   
  3. <action name="error" class="com.asm.ErrorAction"></action>  
  4.   
  5. <action name="error2" class="com.asm.Error2Action"></action>  


</package>这样操作相当于把全局的result加到了此package下的所有action中去。

动态Result:了解

步骤一:建立DyanAction,主要代码如下:

[html]  view plain  copy
  1. package com.asm;  
  2.   
  3. public class DynaAction extends ActionSupport {  
  4.   
  5. private String username;  
  6.   
  7. private String nextAction;  
  8.   
  9. public String execute() throws Exception {  
  10.   
  11. if (username.equals("admin")) {  
  12.   
  13. nextAction = "admin";  
  14.   
  15. } else if (username.equals("user")) {  
  16.   
  17. nextAction = "user";  
  18.   
  19. } else {  
  20.   
  21. nextAction = ERROR;  
  22.   
  23. }  
  24.   
  25. return SUCCESS;  
  26.   
  27. }  
  28.   
  29. ...省略get/set方法  
  30.   
  31. }  

步骤二、建立jsp页面dyna.jsp,主要是为了向DynaAction中传递username参数。

步骤三、相关配置如下:

[html]  view plain  copy
  1. <package name="dynaTest" extends="pubResult">  
  2.   
  3. <action name="dyna" class="com.asm.DynaAction">  
  4.   
  5. <result name="success" type="chain">${nextAction}</result>  
  6.   
  7. </action>  
  8.   
  9. <action name="admin" >  
  10.   
  11. <result>/admin.jsp</result>  
  12.   
  13. </action>  
  14.   
  15. <action name="user">  
  16.   
  17. <result>/user.jsp</result>  
  18.   
  19. </action>  
  20.   
  21. </package>  


分析:当dyna.jsp把参数传递到DynaAction中去时,如果传递的值为admin,我们便设定了nextAction的值admin,在配置文件中我们通过${nextAction}(用在struts配置文件中的ognl,其实nextAction的值是存在值栈中,我们通过${}这样的形式取出。在此只作了解)来获取值便为admin,随后再继续把请求传递到下一个Action中去(此时也即admin.action),为了方便我们设定了两个ForwardActionadmin.action和user.action。这样便可以跳到指定的jsp页面。 原理:dyna.action执行后会继续把请求传递给下一个Action,而下一个Action的到底是哪一个Action,是通过DynaAction中动态指定的,比如这里是根据传递的username的值指定。

12.异常处理

步骤一、建立struts2exception项目下,在该项目下建立登录页面login.jsp。主要代码如下:

[html]  view plain  copy
  1. <form action="<%=request.getContextPath() %>/login.action">  
  2.   
  3. username:<input type="username" name="username"><br>  
  4.   
  5. <input type="submit" value="login">  
  6.   
  7. </form>   

步骤二、建立LoginAction,代码如下:

[html]  view plain  copy
  1. <pre name="code" class="java">package com.asm;  
  2.   
  3. public class LoginAction extends ActionSupport {  
  4.   
  5. private String username;  
  6.   
  7. public String execute() throws Exception {  
  8.   
  9. if (username.equals("exception")) {  
  10.   
  11. throw new ClassNotFoundException("类未被找到");  
  12.   
  13. } else if (username.equals("global")) {  
  14.   
  15. throw new Exception("全局异常");  
  16.   
  17. } else {  
  18.   
  19. return SUCCESS;  
  20.   
  21. }  
  22.   
  23. }  
  24. ...省力get/set方法  
  25.   
  26. }</pre><br>  
  27. <br>  
  28. <pre></pre>  
  29. <br>  
  30. <p></p>  
  31. <p>步骤三、struts.xml配置文件如下:</p>  
  32. <pre name="code" class="html"><struts>  
  33.   
  34. <package name="ex" extends="def">  
  35.   
  36. <action name="login" class="com.asm.LoginAction">  
  37.   
  38. <exception-mapping result="myException"  
  39.   
  40. exception="java.lang.ClassNotFoundException">  
  41.   
  42. </exception-mapping>  
  43.   
  44. <result name="myException">/exception.jsp</result>  
  45.   
  46. <result name="success">/main.jsp</result>  
  47.   
  48. </action>  
  49.   
  50. </package>  
  51.   
  52. <package name="def" extends="struts-default" abstract="true">  
  53.   
  54. <global-results>  
  55.   
  56. <result name="myGlobal">/globalException.jsp</result>  
  57.   
  58. </global-results>  
  59.   
  60. <global-exception-mappings>  
  61.   
  62. <exception-mapping result="myGlobal"  
  63.   
  64. exception="java.lang.Exception">  
  65.   
  66. </exception-mapping>  
  67.   
  68. </global-exception-mappings>  
  69.   
  70. </package>  
  71.   
  72. </struts></pre><br>  
  73. <br>  
  74. <p>分析:异常处理机制较为简单,所以在此只略作说明。当登录时输入“exception”时,在LoginAction中会抛出会一个ClassNotFoundException异常,此异常我们采取的局部异常处理的方式,如果登录时输入“globla”,则会抛出Exception异常,此异常我们采取的是全局异常的处理方式,在ex包中我们继承了全局异常所在的包。提示:<exception-mapping>中的result属性的值来源于<result>元素中的name属性的值。从实例可以看出,我们一般把这种全局性的异常放在一个抽象包中供其实包继承。</p>  
  75. <br>  

struts2之Action配置的各项默认值、result配置的各种试图转发类型及为应用指定多个struts配置文件

1、Action配置的各项默认值
(1)、如果没有为action指定class,默认是ActionSupport。
(2)、如果没有为action指定method,默认执行action中的execute()方法。
(3)、如果没有为action指定result,默认值为success。

   

2、result配置的各种试图转发类型
<result type="">...</result>
其中type的常用类型有:
dispatcher(默认值) ->转发
redirect ->重定向
redirectAction ->重定向的action在别的命名空间下
如:<result type="redirectAction">
          <param name="actionName">helloworld</param>
          <param name="nameSpace">/test</param>
      </result>
plainText ->显示原始文件内容
如:<result type="">
          <param name="location">/xxx.jsp</param>
          <!--指定读取文件的编码-->
          <param name="charSet">UTF-8</param>
      </result>
注意:在result中还可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中的属性名
如:<result name="success" type="redirect">/index.jsp?username=${username}</result>

   

3、为应用指定多个struts配置文件

在大部分应用里,随着应用规模的增加,系统中Action数量也大量增加,导致struts.xml配置文件变得非常臃肿。为了避免struts.xml文件过于庞大、臃肿,提高struts.xml文件的可读性,我们可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml文件中包含其他配置文件。下面的struts.xml通过<include>元素指定多个配置文件:

<?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="struts-user.xml"/>

  <include file="struts-order.xml"/>

</struts>

通过这种方式,我们就可以将Struts 2的Action按模块配置在多个配置文件中。

以下为模拟案例

目录结构

    

        

HelloWordAction action类

复制代码
package  com.ljq.action;

import  java.net.URLEncoder;


public   class  HelloWordAction {
private  String msg;
private  String username;

public  String msg(){
msg 
=   " 我的第一个Struts2应用 " ;
return   " msg " ;
}

public  String list()  throws  Exception{
// 对中文进行编码
msg  =   " 我的第一个Struts2应用 " ;
this .username = URLEncoder.encode( " 林计钦 " , " UTF-8 " );
return   " list " ;
}

public  String getMsg() {
return  msg;
}

public   void  setMsg(String msg) {
this .msg  =  msg;
}

public  String getUsername() {
return  username;
}

public   void  setUsername(String username) {
this .username  =  username;
}
}
复制代码

       

message.jsp页面

复制代码
<% @ page language = " java "   import = " java.util.* "  pageEncoding = " UTF-8 " %>
<%
String path 
=  request.getContextPath();
String basePath 
= request.getScheme() + " :// " + request.getServerName() + " : " + request.getServerPort() + path + " / " ;
%>

<! DOCTYPE HTML PUBLIC  " -//W3C//DTD HTML 4.01 Transitional//EN " >
< html >
< head >
< base href = " <%=basePath%> " >

< title > message </ title >

< meta http - equiv = " pragma "  content = " no-cache " >
< meta http - equiv = " cache-control "  content = " no-cache " >
< meta http - equiv = " expires "  content = " 0 " >  
< meta http - equiv = " keywords "  content = " keyword1,keyword2,keyword3 " >
< meta http - equiv = " description "  content = " This is my page " >
<!--
< link rel = " stylesheet "  type = " text/css "  href = " styles.css " >
-->

</ head >

< body >
< b > ${msg } </ b >
</ body >
</ html >
复制代码

      

index.jsp页面

复制代码
<% @ page language = " java "   import = " java.util.*,java.net.* "  pageEncoding = " UTF-8 " %>
<%
String path 
=  request.getContextPath();
String basePath 
= request.getScheme() + " :// " + request.getServerName() + " : " + request.getServerPort() + path + " / " ;
%>

<! DOCTYPE HTML PUBLIC  " -//W3C//DTD HTML 4.01 Transitional//EN " >
< html >
< head >
< base href = " <%=basePath%> " >

< title > HelloWord </ title >
< meta http - equiv = " pragma "  content = " no-cache " >
< meta http - equiv = " cache-control "  content = " no-cache " >
< meta http - equiv = " expires "  content = " 0 " >  
< meta http - equiv = " keywords "  content = " keyword1,keyword2,keyword3 " >
< meta http - equiv = " description "  content = " This is my page " >
<!--
< link rel = " stylesheet "  type = " text/css "  href = " styles.css " >
-->
</ head >

< body >
<%--  
< result name = " list "  type = " redirect " > 不会显示${msg }的值
< result name = " list "  type = " dispatcher " > 会显示${msg }的值
--%>
${msg }
< br />
<%-- 获取url的请求参数  --%>
<%-- ${param.username }会出现乱码  --%>
${param.username }
< br />
<%= URLDecoder.decode( new  String(request.getParameter( " username " ).getBytes( " ISO8859-1 " ), " UTF-8 " ), " UTF-8 " ) %>
</ body >
</ html >
复制代码

     

helloworld_struts.xml子配置文件

复制代码
<? xml version = " 1.0 "  encoding = " UTF-8 "   ?>
<! DOCTYPE struts PUBLIC
" -//Apache Software Foundation//DTD Struts Configuration 2.0//EN "
" struts-2.0.dtd " >
< struts >
<!--  全局result:有很多时候一个result可供很多action使用,这时可以使用global - results标签来定义全局的result -->
< package  name = " base "   extends = " struts-default " >
< global - results >
< result name = " msg " >/ message.jsp </ result >
</ global - results >
</ package >
< package  name = " helloWord "  namespace = " /helloWord "   extends = " base "   >
<!--  访问路径: http: // localhost:8083/struts2_1/helloWord/manage.do -->
< action name = " manage "   class = " com.ljq.action.HelloWordAction "  method = " msg " ></ action >
<!--  访问路径: http: // localhost:8083/struts2_1/helloWord/listHelloWord.do
http: // localhost:8083/struts2_1/helloWord/msgHelloWord.do
-->
< action name = " *HelloWord "   class = " com.ljq.action.HelloWordAction "  method = " {1} " >
<!--  注意:在result中还可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中的属性名  -->
< result name = " list "  type = " redirect " >/ index.jsp ? username = ${username} </ result >
</ action >
</ package >
</ struts >
复制代码

     

struts.xml配置文件

复制代码
<? xml version = " 1.0 "  encoding = " UTF-8 "   ?>
<! DOCTYPE struts PUBLIC
" -//Apache Software Foundation//DTD Struts Configuration 2.0//EN "
" struts-2.0.dtd " >

< struts >
<!--  该属性指定需要Struts2处理的请求后缀,该属性的默认值是action,即所有匹配 * .action的请求都由Struts2处理。
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 
-->
< constant name = " struts.action.extension "  value = " do,php "   />
<!-- 解决乱码  -->
< 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 "   />
<!--  默认的视图主题  -->
< constant name = " struts.ui.theme "  value = " simple "   />
<!--< constant name = " struts.objectFactory "  value = " spring "   />-->
<!--  动态方法调用和使用通配符定义  -->
<!-- 该属性设置Struts2是否支持动态方法调用,该属性的默认值为true。如果需要关闭动态方法调用,则可设置该为false -->
<!--< constant name = " struts.enable.DynamicMethodInvocation "  value = " false "   />-->
<!-- 上传文件的大小设置(这里的大小指的是总大小) -->
<!--< constant name = " struts.multipart.maxSize "  value = " 10701096 "   />-->

<!--  引入  -->
< include file = " helloworld_struts.xml "   />
</ struts >

<!-- 注意:Struts2读取到Struts2.xml的内容后,以JavaBean形式存放在内存中。 -->
<!-- 以后Struts2对用户的每次请求处理将使用内存中的数据,而不是每次都读取Struts2.xml文件 -->
复制代码

              

运行结果

1、访问路径: http://localhost:8083/struts2_1/helloWord/manage.do

2、http://localhost:8083/struts2_1/helloWord/listHelloWord.do

分类:  struts2

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值