天天看点

学习使用DispatchAction (收集网上资料)

Lesson 2: Action classes should only perform data type validations. Any business rule validation is to be solely done by the Business tier components.

More than one methods in Action class

Often you will find that you are doing some closely coupled operations on a particular business entity. For example, Creating, Reading, Updating and Deleting (CRUD) of Student data are closely related operations all being performed on a single business type Student. It is sometimes good idea to combine all these related functionalities within the same action class. You can do so by extending your own Action class from Struts DispatchAction class and instruct the Struts framework to invoke any desired method from a set of methods defined within that Action class. The Struts framework works on an extra parameter passed to the framework identifying the method to be invoked. For example, the following Action class is an example of a DispatchAction.

public class StudentAction extends DispatchAction

{

   public ActionForward create(ActionMapping mapping, ActionForm form,

                                                HttpServletRequest req,

HttpServletResponse res) throws Exception

{

   return something;

}

   public ActionForward read(ActionMapping mapping, ActionForm form,

                                                HttpServletRequest req,

HttpServletResponse res) throws Exception

{

   return something;

}

   public ActionForward update(ActionMapping mapping, ActionForm form,

                                                HttpServletRequest req,

HttpServletResponse res) throws Exception

{

   return something;

}

   public ActionForward delete(ActionMapping mapping, ActionForm form,

                                                HttpServletRequest req,

HttpServletResponse res) throws Exception

{

   return something;

}

Now to use this class successfully, you need to have the following configuration in the Struts configuration file.

<action path="/studentAction"

        type="StudentAction"

        name="studentForm"

        parameter="methodToCall"

        scope="request"

        validate="true"

        input="/student.jsp">

  <forware name="success" path="/success.jsp">

</action>

In this configuration file the value of the parameter methodToCall determines the method in the StudentAction class to be invoked. For example, the JSP from which you are calling this action, can set the methodToCall parameter to any of the methods it wants to.

//

public abstract class DispatchAction

extends Action

An abstract Action that dispatches to a public method that is named by the request parameter whose name is specified by the parameter property of the corresponding ActionMapping. This Action is useful for developers who prefer to combine many similar actions into a single Action class, in order to simplify their application design.

To configure the use of this action in your struts-config.xml file, create an entry like this:

<action path="/saveSubscription" type="org.apache.struts.actions.DispatchAction" name="subscriptionForm" scope="request" input="/subscription.jsp" parameter="method"/>

which will use the value of the request parameter named "method" to pick the appropriate "execute" method, which must have the same signature (other than method name) of the standard Action.execute method. For example, you might have the following three methods in the same action:

public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception

public ActionForward insert(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception

public ActionForward update(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception

and call one of the methods with a URL like this:

http://localhost:8080/myapp/saveSubscription.do?method=update

NOTE - All of the other mapping characteristics of this action must be shared by the various handlers. This places some constraints over what types of handlers may reasonably be packaged into the same DispatchAction subclass.

NOTE - If the value of the request parameter is empty, a method named unspecified is called. The default action is to throw an exception. If the request was cancelled (a html:cancel button was pressed), the custom handler cancelled will be used instead. You can also override the getMethodName method to override the action's default handler selection.

//

学习使用DispatchAction

DispatchAction继承自Action类,它是一个抽象类,封装了一些基础方法,来解决使用一个Action处理多个操作的能力,这就是DispatchAction最大的用途,它可以帮助我们用一个Action类,封装一套类似的操作方法,节省了类的数目,同时也减轻了后期维护的困难。

DispatchAction中主要包括一下几个方法:

protected ActionForward dispatchMethod

protected java.lang.reflect.Method getMethod getMethod

protected java.lang.String getMethodName

DispatchAction在配置上于标准的Action稍有不同,就是要在Action配置中多一个parametr属性,这个属性将指导DispatchAction找到对应的方法,例如这样配置:

<action path="/saveSubscription"

        type="org.apache.struts.actions.DispatchAction"

        name="subscriptionForm" scope="request" input="/subscription.jsp"   

        parameter="method"/>

parameter 的属性值是可以任意起的,只要你记得在传参数的时候统一就可以了。比如我写了一个类似这样的Action,它继承自DispatchAction类,包含了三个操作方法,有Add(),Update(),Delete()。当我想要调用这个Action的Update操作时,提交的URL应该类似这样的:

http://localhost:8080/myapp/saveSubscription.do?method=update

就是这么简单,不过非常方面我们程序员了,开发中我感觉的确省了好多代码,至少以前的三个类文件变成了现在一个类了,而且在后期维护的时候感觉也是方便很多。

需要注意的是:在调用DispatchAction的时候method参数是不能为空的,如果空,DispatchAction会调用unspecified方法并抛出异常。

//

中间格式有点问题:重发前边几段

不知道有没有人在实际中使用过struts的DispatchAction系列? 谁又能给我明白的讲讲DispatchAction, LookupDispatchAction, MappingDispatchAction各自的用法和区别呢?

1) DispatchAction就是在struts-config中用parameter参数配置一个表单字段名,这个字段的值就是最终替代execute被调用的方法. 例如parameter="method"而request.getParameter("method")="save",其中"save"就是MethodName。struts的请求将根据parameter被分发到"save"或者"edit"或者什么。但是有一点,save()或者edit()等方法的声明和execute必须一模一样。

2) LookupDispatchAction继承DispatchAction, 用于对同一个页面上的多个submit按钮进行不同的响应。其原理是,首先用MessageResource将按钮的文本和ResKey相关联,例如button.save=保存;然后再复写getKeyMethodMap(), 将ResKey和MethodName对应起来, 例如map.put("button.save", "save"); 其配置方法和DispatchAction是一样的, 使用时要这么写:

<html:submit property="method">

  <bean:message key="button.save"/>

</html:submit>

3) MappingDispatchAction是1.2新加的, 也继承自DispatchAction. 它实现的功能和上面两个区别较大, 是通过struts-config.xml将多个action-mapping映射到同一个Action类的不同方法上, 典型的配置就是:

<action-mappings>

  <action path="/saveUser" type="logic.UserAction" parameter="save"></action>

  <action path="/editUser" type="logic.UserAction" parameter="edit"></action>

</action-mappings>

然后UserAction继承MappingDispatchAction,其中有:

public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception

public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception

等方法

可以看到, 不管怎么变化, 其实这些类都是把execute给分解开, 不管是save, edit还是其他什么方法, 其实都是和原来的execute是等价的, save和edit之间没有任何直接的关系, 而事实呢,它们是同一个业务模型的两种不同操作。 我觉得这就是一个问题,对于save和edit这两种请求, 我后台逻辑有可能只是调用service的方法那一句不一样,其他代码是完全一致的(例如错误处理, 日志记录等)。因此我想出了这个小东西,在execute方法内部进行局部分解。

 Re: 一个关于Struts Action的小框架, 请高手指点一下  发表时间: Apr 20, 2005 12:26 PM   回复 

发表人: warbaby    发表文章: 9 / 注册时间: 2005-01 

可能还是有些地方没说明白。

TestAction的配置和普通Action的配置完全一样。

TestActionForm里面有一个method属性。

运行结果:

http://localhost/webapp/test.do?method=save

在后台显示Saving the world.

http://localhost/webapp/test.do?method=edit

在后台显示Editing the world.

banq说关键是edit,save等methods是如何激活的。就是这句:

dispatchSubAction(form.getMethod(), params, methods);

根据请求的method值,从methods中选择一个java.lang.Method类,以params为参数调用。

这句是老版本,该贴发出后,经过优化,这里不需要使用methods来调用了。dispatchSubAction(form.getMethod(), params);就行了。在BaseAction里有一句

protected Map methods = getMethodMap();

在struts初始化Action时,反射一次得到本Action的所有save,edit等等方法,Map里保存的是java.lang.Method,这样以后调用应该能快些。子类中根本不需要看不到这一过程了,只要知道dispatchSubAction的第一个参数是方法名,第二个参数是调用方法的参数对象数组即可。