属性
- name:action请求的名称。
- class:指定Action类。缺省值为ActionSupport类。
- method:指定处理逻辑的方法名。缺省值为excute方法。
name-以action之名
由上图可以直观的看出action的name如何和package的namespace组成一个action请求。
注意:
- 支持正斜杠[/],需要设置常量struts.enable.SlashesInActionNames的值为true
- 支持[.][-]两个符号,但是注意使用[.]符号的话,action请求需要在最后显示设置请求后缀,例如.action。否者会被识别为请求后缀而出现错误。
- 无法支持中文
ps:action请求还有更复杂的一些情况可以参看文章《strust2-学习(二)<package>配置详解》中namespace配置的实验部分
class-逻辑控制中心
MVC是一个经典的设计模式,而在struts2中的控制层就是action的class指定的Action类了。
class属性在没有容器管理的情况下,应包含Action的全路径。as follows:
<!-- class的配置 -->
<package name="class" namespace="/class" extends="struts-default">
<!-- 为action指定逻辑处理的Action类 -->
<action name="controller-default" class="struts2.action.action.ControllerAction">
<result>/class/my-class.jsp</result>
</action>
</package>
package struts2.action.action;
import com.opensymphony.xwork2.ActionSupport;
public class ControllerAction extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("进入ControllerAction控制器");
return super.execute();
}
}
如果action没有指定具体执行逻辑的方法,则默认的执行方法是execute。Action类可以继承ActionSupport类然后可以重写execute方法。否则会执行ActionSupport的execute方法,该方法返回字符串"success"。这里我们重写了一下execute方法使得控制台输出一些信息。最后返回的父类ActionSupport的execute执行的结果--success。
ps:系列文章基于循序渐进的方式编写,Action类的部分因为超出此部分内容所以此内容在后面的文章介绍。在此有关Action部分的内容--例如返回值“success”的作用大家可以先不求甚解。
method
前面说到Action是逻辑处理中心,而实际逻辑处理单元是method--就是Action类中的方法。上文中我们只使用了struts2默认的执行方execute。其实每个action不仅可以自定义执行的类同样可以指定方法。
例子:
<!-- method的配置 -->
<package name="method" namespace="/method" extends="struts-default">
<!-- method缺省值为 execute -->
<action name="default-method" class="struts2.action.action.MethodAction">
<result>/method/my-method.jsp</result>
</action>
</package>
package struts2.action.action;
public class MethodAction {
public String execute() throws Exception {
System.out.println("执行默认的excute方法");
return "success";
}
}
这个例子和class小节中的配置相差不多,不同的是MethodAction此时没有继承ActionSupport类。但是实现的execute方法依然被当做默认方法被调用。所以可以看出struts2的Action类完全可以是一个简单类而与struts2无任何关系。
动态调用method
当我们想在一个action配置中指定不同的逻辑处理的方法,可以使用动态的调用method的方式。struts中提供了多种实现的方式。动态调用方法使得简化了action的配置,也是的配置更加灵活。
1. 使用符号--!
配置如下
<!-- 可以在action请求的最后使用!指定逻辑执行的方法 -->
<action name="dynamic-method" class="struts2.action.action.MethodAction">
<result >/method/dynamic-method.jsp</result>
</action>
在上面的配置中制定了action的name和class属性。当我们在请求dynamic-method时在请求的最后加上符号[!]和具体执行方法的名称,就可以实现动态调用。例如
http://localhost:8080/struts2.action/method/dynamic-method!dymMethod1
http://localhost:8080/struts2.action/method/dynamic-method!dymMethod2
上面两个请求都是dynamic-method然后会根据!后的方法名称去执行对应的方法。可以在返回的页面和控制台看到执行了不同的方法。
补上MethodAction类新增的方法
public String dymMethod1(){
dynmMethod = "动态方法--1";
System.out.println("执行动态方法--1");
return "success";
}
public String dymMethod2(){
dynmMethod = "动态方法--2";
System.out.println("执行动态方法--2");
return "success";
}
ps:作者看的教材提到说要在配置文件中显示开启动态方法调用--设置常量struts.enable.DynamicMethodInvocation为true。配置如下:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
作者发现无需显示配置也可支持。
2. 使用符号--*
看到*可能部分读者会感到亲切,在很多地方我们都把它作为一个通配符使用。在这里它同样是作为通配符使用。
配置如下:
<!-- 使用通配符*来动态调用方法 -->
<action name="dynamic-method-*" class="struts2.action.action.MethodAction" method="{1}">
<result >/method/dynamic-method.jsp</result>
</action>
在name属性中使用通配符,这样可以匹配所有dynamic-method-xxxx形式的action请求。然后匹配到的字符串(例如:xxxx)就可以在method中通过{1}获取({2}获取的是第二个通配符匹配的字符串)。
访问以下请求动态调用不同的方法,返回不同的结果。
http://localhost:8080/struts2.action/method/dynamic-method-dymMethod1
http://localhost:8080/struts2.action/method/dynamic-method-dymMethod2
通配符匹配的字符串不近可以在method属性中使用,可以在result中使用。
例如:
<package name="pages" namespace="/pages" extends="struts-default">
<action name="*-page">
<result>{1}.jsp</result>
</action>
</package>
在上面的配置下,我们可以通过输入jsp页面的名称来动态访问。
请求:
http://localhost:8080/struts2.action/pages/my-login-page
http://localhost:8080/struts2.action/pages/my-register-page
使用通配符引发的优先级问题。如果我们使用通配符的话会出现action请求匹配优先级的问题。
<!-- 验证通配符匹配优先级问题 -->
<action name="dynamic-*" class="struts2.action.action.MethodAction">
<result >/method/dynamic-method2.jsp</result>
</action>
<!-- 使用通配符*来动态调用方法 -->
<action name="dynamic-method-*" class="struts2.action.action.MethodAction" method="{1}">
<result >/method/dynamic-method.jsp</result>
</action>
上面的配置会出现同时可以匹配以下的请求的情况。
http://localhost:8080/struts2.action/method/dynamic-method-dymMethod1
这个时候会进入的是哪个action呢?
结果:dynamic-method-的优先级比dynamic-**高,这与前一篇文章中判断package的namespace优先级的结果是一样--都是根据长度越长则优先级越高。
配置默认Action
当我们输入的action请求无法匹配到对应的actiond则会抛出异场,返回一个异常页面。struts2通过<default-action-ref>提供默认Action来处理无法匹配的action请求。配置如下
<package name="default-action" namespace="/default" extends="struts-default">
<!-- 设置默认的action -->
<default-action-ref name="default"/>
<action name="default">
<result>/default.jsp</result>
</action>
</package>
但是默认action是针对每个package的。
default-action-ref的name指向的是已存在的action。
我们访问下面的网址,该请求无法匹配任何action所以结果是会返回name为default的action的物理视图。
localhost:8080/struts2.action/default/yyyy
localhost:8080/struts2.action/default/xxxx
配置默认Action类
我们知道如果不指定action中的class则会默认调用ActionSupport类。这其实是在struts-default.xml文件中配置好的。如下
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
所以我们自己也可以给package中的action指定默认执行的Action类。实现方式和上面的代码相同。
代码示例
可以在github下载study项目中的struts2.action工程。查看示例源码
struts2.action项目地址