struts2动态方法调用

来源:互联网 发布:ssr centos 一键 编辑:程序博客网 时间:2024/05/16 12:57

如果Action中存在多个方法时,我们可以使用!+方法名调用指定方法。如下:

public class HelloWorldAction{private String message;....public String execute() throws Exception{this.message = "我的第一个struts2应用";return "success";}public String other() throws Exception{this.message = "第二个方法";return "success";}}

假设访问上面action的URL路径为: /struts/test/helloworld.action

要访问action的other() 方法,我们可以这样调用:

/struts/test/helloworld!other.action

如果不想使用动态方法调用,我们可以通过常量struts.enable.DynamicMethodInvocation关闭动态方法调用。

<constantname="struts.enable.DynamicMethodInvocation"value="false"/>

 

动态方法调用是在action的名字中使用感叹号(!)来标识要调用的方法名,其语法格

式为 actionName!methodName.action

<action name="user" class="org.lesson05.UserAction">

            <result name="success">/Methods/list.jsp</result>

   </action>

当请求/user!delete.action时,就会自动调用UserAction中的delete()方法

提示,这种调用方式会带来安全隐患!

使用最新struts2(2.3.15.2),不能使用DMI动态调用方法

 

使用action的method属性可以任意指定处理请求的方法(只要该方法和execute方法具有相同的格式),这样就可以在同一个类中完成相关的任务,而不需要去编写不同的Action类。

Struts2在根据action元素的method属性查找方法时有两种途径:

1)查找与method属性值完全一致的方法

2)查找doMethod()形式的方法。

以上面的例子为例,当请求/reg时,struts2首先查找addUser()方法,如果找不到,则继续查找名为doAddUser() 的方法。这种特性是从WebWork继承而来的,而WebWork提供这种特性,一方面是为了兼容旧版本WebWork遗留的功能,另一方面是因为一些方法别名的需要,例如,default是Java的关键字,不能作为方法名,你可以使用doDefault作为方法名,在配置时,可以使用method=“default”.

这种特性同样也适用于动态方法调用,例如,请求/users! addUser.action,struts2会依次查找addUser()和doAddUser()方法

 

另一种无须配置就可以直接调用Action中的非execute()方法的方式,就是使用struts2的动态方法调用。

动态方法调用(Dynamic Method Invocation,DMI)是在action的名字中使用感叹号( !)来标识要调用的方法名,其语法格式为:

actionName!methodName.action

例如, 我们配置了如下的Action

<action name=“users”class=“com.ambow.UserAction” >…..</action>

当请求/users! addUser.action时,将调用UserAction的addUser()方法;

当请求/users! updateUser.action时,将调用UserAction的updateUser()方法;

DMI的实现本质是,其实现代码扫描action名字中的“!”字符,如果找到,则“欺骗”框架来调用“!”字符后的方法,而非execute方法。虽然调用的是其它方法,但是它使用的仍然是execute方法的配置,包括验证。框架“相信”它正在调用的是Action类的execute()方法。

 

在struts2中使用DMI有两个要注意的问题。首先,DMI可能会带来安全隐患,由于通过URL可以执行action中的任意方法,恶意的用户会利用这一特性来执行一些敏感的方法,即使你不想这些方法被执行。所以在确定使用DMI时,你应该确保Action中的方法都是普通、开放的方法;否则,你应该加上安全控制。其次,DMI与通配符方法有所重叠。

由于上述两个原因,struts2提供了一个属性配置,用于禁止DMI。你可以在struts.xml文件中,使用constant元素将struts.enable.DynamicMethodInvocation属性设置为false,来关闭DMI

那么什么时候使用动态方法调用,什么时候使用action元素的mrthod属性呢?或者二者有什么区别吗?

如果同一个Action的不同方法使用的是相同的配置(同样的拦截器引用,同样的result映射),那么可以使用动态方法调用;

如果不同的方法调用需要配置不同的拦截器引用、不同的result映射,那么可以使用action元素的method属性,为同一个Action配置多个别名。

 

由于业务方法是动态调用,参数是用户传递的,我们不要期待用户按照我们的意愿传递参数,毕竟还是有很多不安份的“用户”,比如有的用户使用了actionName_fn2.action如果该action中存在该方法而且该方法没有参数而且返回String类型的数据的时候,fn2所定义的功能就会被执行,也许fn2是我们程序员使用的,本来不打算暴露给用户的,同时我们又习惯性的定义成了public方法,那么该方法会正确的执行。即使不是这样,我们的方法没有返回String类型的数据,而是返回了其他的类型,该方法同样会被执行,只要这个方法被定义成了public而其没有参数。虽然会抛出异常但是不可否认的是这个方法被完全执行了,异常实在Action的业务方法return以后抛出的,也就是说这个方法完全的暴露给了用户。比如说,一个处理用户注册的业务方法f1在经过必要的判断以后调用f2把用户添加到数据库,如果f2函数符合条件,用户就可以跳过f1直接访问f2。对于安全来说这确实是个问题。


0 0