struts2中配置篇值请求处理元素
对请求进行处理的元素主要有interceptors、Action以及Result。下面分别对其进行讲述。
1.拦截器配置(interceptors)
通过使用拦截器,我们可以在action中的方法执行之前先执行一些我们事先定义好了的方法,也可以在action中的方法执行之后立即执行一些我们事先定义好了的方法。在开发的过程中,拦截器将是一个强有力的工具。拦截器有很多很多的功能,如校验、属性封装、安全、日志等等,如下所示:
校验(validation): 检查输入是否正确
属性封装(property population): 将输入传输和转化为对象的属性
日志(logging): 记录关于每个action的详细信息
切面(profiling): 记录action的吞吐量,寻找性能瓶颈(不是很懂)
我们可以将多个拦截器链接在一起形成一个拦截器栈。比方说一个action不仅要对客户端的资格进行审查,还要记录它自己的行为,那么我们可以将实现这两个功能的拦截器放在一起,形成一个拦截器栈(interceptor stack)。拦截器是以java类的形式实现的,因此每一个拦截器都有一个唯一的类名。为了让对拦截器的参考更加容易,我们可以在框架中为每个拦截器注册一个更简单的名字。下面给出了一个注册拦截器的例子:
?
在定义一个拦截器栈的时候,单个的拦截器和拦截器栈可以以任意的顺序混合在一起,struts框架将会按照拦截器在栈里面的顺序调用它们。大多数应用程序都会定义一个默认的拦截器栈,如:<default-interceptor-ref name="defaultStack"/>,默认的拦截器栈会作用于package中的每个action上。当然action还可以定义它自己的本地(局部)栈,如下面例子所示:
<action?name="VelocityCounter"?class="org.apache.struts2.example.counter.SimpleCounter">?
2.Action配置
action mappings是框架中的基本工作单元,框架通过对请求的request路径进行映射来决定由哪个action来处理请求。action mappings能指定一系列的result、异常处理器以及拦截器。action元素的所有属性中只有name属性是必须的,其它属性都是可选的。关于如何从请求路径映射到action在namespace那节中已经说过了,这里就不说了。尽管对于action的命名很灵活,但是action的名字中最好不要出现斜线(/)、点号(.)、破折号(/),以免出现一些不可预知的错误。
在Action接口中定义了action默认的方法入口,它就是execute方法。但是并不是每个action类都必须实现这个接口,如果action类没有实现这个接口的话,框架将使用反射来寻找一个execute方法。有时候我们的action中可能会包括多个方法入口,并且不同的情况下方法入口不同,例如执行修改操作时我们想进入action的mofify方法,执行增加操作时进入action的add方法,这个时候怎么办呢?我们可以通过指定action元素的method属性来实现,如下所示:
<action name="modify" method="modify">
如果在action类中没有execute方法,也没有在配置文件中指定其它的方法,框架会抛出异常。
很多时候,多个action mapping会共享一个相同的模式,这个时候我们可以使用通配符方法。还是举例来说,如下所示。
<action name=”editCrud” class=”example.CrudAction” method=”edit”/>
<action name=”deleteCrud” class=” example.CrudAction” method=” delete”/>
上述两个action mapping调用的是同一个action类,只是执行的方法不同而已,并且所执行的方法名都是action mapping名字的开头部分,而且action mapping的名字除去方法名之后剩下的部分是一样的。这种情况下我们可以使用一个action mapping来代替上面两个action mapping:
<action name=”*Crud” class=”example.CrudAction” method=”{1}”>
匹配过程是这样的 (以请求的action mapping的名字是editCrud为例) :
● *可以表示任何内容,因此任何以Crud结尾的action mapping都会匹配上
● 当editCrud匹配上后,*的内容此时就是edit
● 调用名字为第一个*号的内容的方法,此时仅有一个*号,并且此时它的内容为edit,因此action类的edit方法被调用了
● 同理,如果请求的action是deleteCrud,匹配成功后*的内容就是delete,调用的方法就是delete了。
使用通配符匹配方法可以让我们减少配置文件的内容,是配置更加简洁。
如果我们没有给action元素指定class属性的话,框架会默认它的class属性为com.opensymphony.xwork.ActionSupport,如果想指定别的类作为默认的Action类,可以通过package的default-action-ref属性来设置。在设置了default-action-ref之后,如果我们在package中没有匹配到所请求的action,那么这个默认的action就会被调用。一般一个命名空间下最好只定义一个默认的action。
3.Result元素配置
action类处理完一个请求后会返回一个字符串,这个字符串将被用来选择一个result元素。通常一个action mapping会有多个result,代表各个可能不同的结果。ActionSupport中定义了几个标准的result token,如下所示:
String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";
通常我们都会自定义一些result token类匹配特定的情况。
result元素负责完成两个工作:1.提供一个逻辑名用于与action类的返回字符串进行匹配;2.提供一个返回类型(Result Type)。尽管大多数的result只是简单的转向一个页面或模板,但是我们还可以利用其它的返回类型(Result Type)做其它的一些事情。我们可以为每个包设置默认的返回类型(Result Type),如果一个包继承了另外一个包,它可以选择设置自己的默认返回类型或者直接使用父包的。设置默认返回类型的方式如下:
<result-types>
<result-type name="dispatcher" default="true"
type="redirect-action">Logon!input</result>
</global-results>
有时候我们的result在运行前可能是未知的。比方说,一个result它所跳转的页面取决于它所在action类的运行结果或者客户端的输入等等,这时候我们可以使用动态的result,也就是说result的值可以使用表达式语言(EL)来表示,这个表达式的值是动态的,取决于action的运行时状况,下面是一个例子:
private String nextAction;
public String getNextAction() {
return nextAction;
}
……………………………………………………………………………………
<action name="fragment" type="redirect-action">${nextAction}</result>
</action>
在上例中result的值将是它所在action的nextAction的属性值,nextAction属性的值不同,当action的方法返回”next”时所跳向的url也不同。
?
?
?
?