利用了一个晚上的业余时间看了一下struts2官方文档中的Action Configuration章节,可对该章节的翻译(呵呵,还谈不上翻译,只是个大概意思)却消耗了我近一个星期的业余时间,由于英文水平太差,翻译起来感觉其累,呵呵,希望通过这样坚持下去也将自己的英文阅读提高一些。当然,看英文文档从中的收获也是不少的!
在这篇笔记中,有几个地方实在是不知道如何将其准确的翻译和表达出来,因此,就直接将原文贴出来了(红色字体部分),如果有哪位高人看到可以帮忙翻译一下,先谢下!
好了,又是一堆废话,希望下边的内容能对大家有用。。。
Action 的配置是 Struts2 框架的一个基础工作单元,每一个 Action 的配置都有对应的处理类,当一个请求和 Action 的 name 相匹配时,框架将根据所配置的 Action 映射来决定对请求的处理。
1、 Action 映射配置
在 Action 映射中可以指定 result types 、异常处理器( exception handlers )及拦截器,但是,只有 Action 的 name 属性是必需指定的,其他属性也可以在 package 范围内进行定义,供该 package 下配置的所有 Action 引用。如:
A Logon Action <action name="Logon" class="tutorial.Logon"> <result type="redirect-action">Menu</result> <result name="input">/tutorial/Logon.jsp</result> </action>
2、 Action 名称及命名
在 web 应用中, action 的 name 属性用于匹配通过浏览器发送的请求地址或链接的一部分。框架将取主机地址、应用名称和扩展名之间的部分和 name 属性进行匹配,如:一个请求 http://www.planetstruts.org/struts2-mailreader/Welcome.do将映射到 name属性为 Welcome的 Action 处理类。
在一个应用里边,通常通过在标签中指定 action 的 name 来链接到相应的 action ,,然后由框架自动追加 action 的扩展名和其它需要的内容。如:
A Hello Form <s:form action="Hello"> <s:textfield label="Please enter your name" name="name"/> <s:submit/> </s:form>
注意:如果在你的 action 的 name 中包含有斜线(如: <action name="admin/home" class="tutorial.Admin"/> ),你需要在 struts.xml 中进行如下配置: <constant name="struts.enable.SlashesInActionNames" value="true"/> ,但是,启用该配置也会产生一些副作用,具体详情可参考 https://issues.apache.org/struts/browse/WW-1383 上的讨论。
警告:谨慎使用在 action 名称中包含点 (eg:create.user) 、斜线 (create/user) 和横线 (create-user) 的情况,虽然 action 的名称定义非常灵活,但是,当在 action 的 name 中使用点、斜线或横线时,应该谨慎。有时候,当点符号没有明显的副作用时,横线符号将会导致为某一个标签或主题( themes )生成 javascript 时的问题。因此,尽量使用软件工程中规范的或者带下划线的命名,如: createUser 或者 my_action 。
严重提示:Struts2以命名空间的方式来管理Action,同一个命名空间不能有同名的Action。
3、 Action 方法
缺省的处理类入口方法是在 Action 接口中进行定义的, Action 接口代码如下:
Action interface
public interface Action {
public abstract String execute() throws Exception;
public static final String SUCCESS = "success";
public static final String NONE = "none";
public static final String ERROR = "error";
public static final String INPUT = "input";
public static final String LOGIN = "login";
}
该接口的实现是可选的,如果编写的 action 没有实现该接口,框架将自动从 action 中通过反射去查找 execute 方法。
通常,开发人员习惯在一个 action 中创建多个入口方法,例如,在一个具有数据访问功能的 action 中,开发人员想分别实现添加、查询、更新和删除四个入口方法,入口方法可以通过 action 配置中的 method 属性来进行指定,如:
<action name= "delete" class= "example.CrudAction" method= "delete" >
如果在一个 action 中没有 execute 方法,也没有其它方法在配置文件中进行配置,框架将抛出异常。
4、 通配符方法
大多数情况下,一组 action 映射拥有通用的模式,如:所有的 edit actions 可能都是以 edit 开头,并且在 action 类中的入口方法也被命名为 edit 。 delete actions 也将可能具有相同的模式,且在 action 类中的入口方法名被命名为 delete 。
这里,并非需要为每一个存在这种模式(或共性)的 action 类进行单独的映射配置,而是可直接通过通配符映射只需配置一次即可。代码如下:
<action name= "*Crud" class= "example.Crud" method= "{1}" >
在这里,当在应用中将 action 指定为“ editCrud ”时,将调用 editCrud Action 处理类实例中的 edit 方法。同样,“ deleteCrud ”将调用 deleteCrud Action 处理类实例中的 delete 方法。
另外一种方法是通过 action 的后缀来匹配方法名,并且通过感叹号、下划线或者其它特殊字符将其进行分开。
- "action=Crud_input"
- "action=Crud_delete"
下面的代码片断演示了在 action 名称的最后使用星号通配符的示例:
<action name= "Crud_*" class= "example.Crud" method= "{1}" >
从框架的角度看,通配符方式使用与常规的、静态映射同样的属性,创建了一个新的虚拟的映射配置。结果,你能够通过替换通配符来作为校验、类型转换及 message resource 文件,正象他作为 action 的 name 。
- Crud_input-validation.xml
- Crud_delete-conversion.xml
| If Wildcard Method mapping uses a "Unable to render embedded object: File (" in the action name, the Wildcard Method will overlap with another flexible approach to mapping, Dynamic Method Invocation . To use action names that include the ") not found. " character, set struts.enable.DynamicMethodInvocation to FALSE in the application configuration. |
5、 动态方法调用
在 WebWork2 中,可以使用感叹号(!)来指定要执行(或调用)非 execute 方法,但是还没有一个真正的术语该种方式的定义。在 s2 的讨论中,我们定义了“动态方法调用”这个术语来描述 webwork/s2 对感叹号的使用。
动态方法调用( DMI )通过在 action 名称和要调用的 Action 方法之间添加一个感叹号进行分割,以表示调用 action 中指定的方法(非 exeucte 方法)。如:“ Category ! create.action ”,表示调用 Category Action 中定义的 create 方法。
在 Struts2 中,让动态方法调用可配置,有两个原因: 1 )如果使用的是 POJO action ,动态方法调用可能会引起安全问题; 2 )动态方法调用和从 Struts 1 中引用过来的通配符方法有重叠;如果你的应用涉及到安全,或者习惯在 action 配置中使用感叹号作为通配符的话,需要在 struts 应用的 struts.properties 配置文件中将 struts.enable.DynamicMethodInvocation 设置为 false 。
The framework does support DMI, just like WebWork 2, but there are problems with way DMI is implemented. Essentially, the code scans the action name for a "!" character, and finding one, tricks the framework into invoking the other method instead of execute. The other method is invoked, but it uses the same configuration as the execute method, including validations. The framework "believes" it is invoking the Category action with the execute method.
The Wildcard Method feature is implemented differently. When a Wildcard Method action is invoked, the framework acts as if the matching action had been hardcoded in the configuration. The framework "believes" it's executing the action Category!create and "knows" it is executing the create method of the corresponding Action class. Accordingly, we can add for a Wildcard Method action mapping its own validations, message resources, and type converters, just like a conventional action mapping. For this reason, the Wildcard Method is preferred.
6、 ActionSupport 的缺省使用和配置
当在 Action 的配置中没有指定 class 属性时, Struts2 将默认使用 com.opensymphony.xwork.ActionSupport 类。
<action name="Hello"> // ... </action>
Ø ActionSupport 类中有 execute 和 input 方法,其中 execute 方法直接返回“ success ”
Ø 可通过在 package 内配置 default-action-ref ,将其 name 属性指定到缺省的 action 处理类,这时,当找不到对应的 action 处理类时,将默认去调用 default-action-ref 标签的 name 属性对应的 action 类。如下面的配置片断:
<package name="Hello" extends="action-default"> <default-action-ref name="UnderConstruction"> <action name="UnderConstruction"> <result>/UnderConstruction.jsp</result> </action> </package>
每个 package 内可以配置自己的缺省 action ,但是在每个命名空间下只能配置一个缺省的 action ,如果在多个具有相同命名空间的 package 内配置有多个缺省 action 时,框架就没法保证哪个 action 将被作为缺省的 action 。
7、 Wildcard Default
Using wildcards is another approach to default actions. A wildcard action at the end of the configuration can be used to catch unmatched references.
<action name="*" > <result>/{1}.jsp</result> </action>
When a new action is needed, just add a stub page.