在AppFuse框架中,struts action 采用了继承DispatchAction的方法来实现一个Action里实现多种操作。
首先看看DispatchAction原理
DispatchAction在配置上于标准的Action稍有不同,就是要在Action配置中多一个parametr属性,这个属性将指导DispatchAction找到对应的方法,例如这样配置
<action
path="/persons"
type="com.lms.webapp.action.PersonAction"
name="personForm"
scope="request"
input="mainMenu"
parameter="method"
unknown="false"
validate="false" >
parameter的属性值是可以任意起的,只要你记得在传参数的时候统一就可以了。比如我写了一个类似这样的Action,它继承自DispatchAction类,包含了三个操作方法,有Add(),Update(),Delete()。当我想要调用这个Action的Update操作时,提交的URL应该类似这样的:
http://localhost:8080/myapp/persons.do?method=update
在AppFuse中的应用在AppFuse中,有个继承DispatchAction的BaseAction类,每个Action都继承BaseAction,因此在执行Action的时候,都先执行BaseAction里的execute()方法达到指导要执行哪个操作。代码如下
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (isCancelled(request)) {
try {
getMethod("cancel");
return dispatchMethod(mapping, form, request, response, "cancel");
} catch (NoSuchMethodException n) {
log.warn("No 'cancel' method found, returning null");
return cancelled(mapping, form, request, response);
}
}
// Check to see if methodName indicated by request parameter
String actionMethod = getActionMethodWithMapping(request, mapping);
if (actionMethod != null) {
return dispatchMethod(mapping, form, request, response, actionMethod);
} else {
String[] rules = {"edit", "save", "search", "view"};
for (int i = 0; i < rules.length; i++) {
// apply the rules for automatically appending the method name
if (request.getServletPath().indexOf(rules[i]) > -1) {
return dispatchMethod(mapping, form, request, response, rules[i]);
}
}
}
return super.execute(mapping, form, request, response);
}
代码分析:
isCancelled(request)方法:if the current form's cancel button was pressed!进而执行cancel方法。
getActionMethodWithMapping方法来确定所要执行的操作。在getActionMethod方法里,首先是判断request里是否有method=methodName,如果有则返回methodName;如果没有则判断request里是否有包含method.methodName的parameter,有的话则返回截取"method."后面的methodName。
如果通过getActionMethodWithMapping方法取不到methodName,则判断servletPath里是否有包含edit....等字符,以决定执行什么操作。
如果以上都不能取到methodName,那么将执行 return super.execute(mapping, form, request, response);通过查看DispatchAction源码发现最终会执行
unspecified(),而在AppFuse里的每个Action都会重写这个方法。
private String getActionMethodWithMapping(HttpServletRequest request, ActionMapping mapping) {
return getActionMethod(request, mapping.getParameter());
}
/** *//**
* Gets the method name based on the prepender passed to it.
*/
protected String getActionMethod(HttpServletRequest request, String prepend) {
String name = null;
// for backwards compatibility, try with no prepend first
name = request.getParameter(prepend);
if (name != null) {
// trim any whitespace around - this might happen on buttons
name = name.trim();
// lowercase first letter
return name.replace(name.charAt(0), Character.toLowerCase(name.charAt(0)));
}
Enumeration e = request.getParameterNames();
while (e.hasMoreElements()) {
String currentName = (String) e.nextElement();
if (currentName.startsWith(prepend + ".")) {
if (log.isDebugEnabled()) {
log.debug("calling method: " + currentName);
}
String[] parameterMethodNameAndArgs = StringUtils.split(currentName, ".");
name = parameterMethodNameAndArgs[1];
break;
}
}
return name;
}
综上,在AppFuse里可以通过以下几种方法来达到指定实现哪种操作:
1:在路径里包含edit、add、delete字段
如
:http://loaclhost:8080/myapp/editPerson.html2:在request里包含method.methodName参数
如:
<html:submit styleClass="button" property="method.save" onclick="bCancel=false">
<fmt:message key="button.save"/>
</html:submit>
3:执行cancel操作
<html:cancel styleClass="button" onclick="bCancel=true">
<fmt:message key="button.cancel"/>
</html:cancel>
4:都不执行以上操作时,执行unspecified()方法
public ActionForward unspecified(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
return search(mapping, form, request, response);
}
posted on 2007-06-20 16:39
扭曲的铅笔 阅读(643)
评论(0) 编辑 收藏 所属分类:
AppFuse