功能:通过请求的参数来决定该执行哪一个方法,而不像一般的Action,从Execute方法执行。
BaseAction在AppFuse中作为所有Action的父类。使用LookupDispatchAction,在一个窗体中包括两个以上同名的按钮时,由Struts来决定具体执行那个按钮操作,减少了Action类,增加了请求处理的灵活性。继承了LookupDispatchAction后,需要复写 getKeyMethodMap()方法。
Struts的LookupDispatchAction类说明
LookupDispatchAction是DispatchAction的子类。它们都允许同一个Action根据请求URL
中的不同参数执行不同操作(即调用不同的函数)。DispatchAction的子类是根据用户请
求URL中的参数,严格匹配DispatchAction子类中的方法名称来实现的。而
LookupDispatchAction的实现则是资源配置文件的Map结构中的键-值,和用户请求URL
中的参数匹配,反向查询资源文件绑定,并将查询得到的键值和Action类中的具体方法匹
配,选择具体的方法执行。
继承LookupDispatchAction的子类,复写getKeyMethodMap()方法,该方法返回一个包含一组
键/值对的java.util.Map。而这个Map的键应该和资源属性文件中的键匹配,与Map中的每个键相关的
值,应该和LookupDispatchAction子类中的方法名称严格匹配。
例子:如
(1)editUser.html?username=tomcat&from=list&method=edit
(2) editUser.html?username=tomcat&from=list&method=search
Struts可以根据请求URL中的method参数,使得同
一个org.dudu.webapp.action.UserAction执行不同的操作。
Ø BaseAction类
public class BaseAction extends LookupDispatchAction { //根据请求参数和属性文件中的属性比较,填充Map映射结构 public Map getKeyMethodMap() { Map map = new HashMap(); String pkg = this.getClass().getPackage().getName(); //通过ResourceBundle.getBundle在运行时动态加载属性文件 // org.dudu.webapp.action包中的LookupMethods.properties //属性文件中对应的具体方法,如add方法在BaseAction的子类中定义 ResourceBundle methods = ResourceBundle.getBundle(pkg + ".LookupMethods"); Enumeration keys = methods.getKeys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); map.put(key, methods.getString(key)); } return map; } |
public class BaseAction extends LookupDispatchAction { //根据请求参数和属性文件中的属性比较,填充Map映射结构 public Map getKeyMethodMap() { Map map = new HashMap(); String pkg = this.getClass().getPackage().getName(); //通过ResourceBundle.getBundle在运行时动态加载属性文件 // org.dudu.webapp.action包中的LookupMethods.properties //属性文件中对应的具体方法,如add方法在BaseAction的子类中定义 ResourceBundle methods = ResourceBundle.getBundle(pkg + ".LookupMethods"); Enumeration keys = methods.getKeys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); map.put(key, methods.getString(key)); } return map; } |
public class BaseAction extends LookupDispatchAction { //根据请求参数和属性文件中的属性比较,填充Map映射结构 public Map getKeyMethodMap() { Map map = new HashMap(); String pkg = this.getClass().getPackage().getName(); //通过ResourceBundle.getBundle在运行时动态加载属性文件 // org.dudu.webapp.action包中的LookupMethods.properties //属性文件中对应的具体方法,如add方法在BaseAction的子类中定义 ResourceBundle methods = ResourceBundle.getBundle(pkg + ".LookupMethods"); Enumeration keys = methods.getKeys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); map.put(key, methods.getString(key)); } return map; } |
Ø具体实现的子类
public final class UserAction extends BaseAction { //具体的操作方法search public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { //具体的操作方法cancel public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {… …} //具体的操作方法delete public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {… …}
|
Ø Struts-config.xml中的配置1
<forward name="viewUsers" path="/editUser.html?method=Search"/>
Ø Struts-config.xml中的配置2
<action
path="/editUser"
type="org.dudu.webapp.action.UserAction"
name="userForm"
scope="request"
input="list"
roles="admin"
parameter="method"
unknown="false"
validate="false"
>
Ø 说明: 用户提出viewUsers请求时,请求参数中的method=Search参数被UserAction的父类
BaseAction处理,BaseAction的父类LookupDispatchAction会根据该参数method=Search,在属性文件
中文件找到对应的key,然后根据key与从getKeyMethodMap()得知要执行的方法search。
public ActionForward search(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
if (log.isDebugEnabled()) {
log.debug("Entering 'search' method");
}
UserForm userForm = (UserForm) form;
// Exceptions are caught by ActionExceptionHandler
UserManager mgr = (UserManager) getBean("userManager");
User user = (User) convert(userForm);
List users = mgr.getUsers(user);
request.setAttribute(Constants.USER_LIST, users);
// return a forward to the user list definition
return mapping.findForward("list");
}
注:LookupMethods.properties属性文件中的内容
button.add=add
button.cancel=cancel
button.copy=copy
button.edit=edit
button.delete=delete
button.save=save
button.search=search
注解[引用]:
ResourceBundle:该类是一个抽象类,需要通过静态方法ResourceBundle.getBundle()指定具体实现类或属性文件的基本名称。基本名称会协同指定的或默认的Locale类,决定具体调用的类或属性文件的唯一名称。例如:指定基本类或属性文件名称为TestBundle,而指定的Locale是CHINESE,那么最适合匹配的类名称为TestBundle_zh_CN.class,而最佳匹配属性文件名称为TestBundle_zh_CN.properties。按照Java Doc和相关文档的要求,如果该类或属性文件没有找到,系统会查找近似匹配(主文件名依次为TestBundle_zh和TestBundle的类或属性文件)。该类提供的getKeys()方法用于获得所有成员的键名,并提供handleGetObject方法获得指定键的对应元素。
★ 问题:看这一部分时,我遇到了一个问题,如果那位兄弟知道结果,烦请相告,不胜感激。
AppFuse查看用户列表页面,单击用户信息表格中的用户名,在浏览器下的状态栏中显示
URL是editUser.html?username=tomcat&from=list ,
如果在AppFuse中的BaseAction处理,按照read AppFuse BaseAction类分析中谈到,
URL应该是editUser.html?username=tomcat&from=list &method=edit,程序才会按照LookupMethods.properties的配置,跳到查看具体用户信息的页面,但现在URL中并没有method=edit这一个匹配条件,那程序是根据什么条件跳动
用户信息的页面呢?
★ 感谢网友zbird的帮助,问题解决,调试结果如下:
(1)BaseAction类
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
log.debug("BaseAction: entering BaseAction... ... ");
if (isCancelled(request)) {
ActionForward af = cancelled(mapping, form, request, response);
if (af != null) {
return af;
}
}
MessageResources resources = getResources(request);
// Identify the localized message for the cancel button
String edit = resources.getMessage(Locale.ENGLISH, "button.edit").toLowerCase();
String save = resources.getMessage(Locale.ENGLISH, "button.save").toLowerCase();
String search = resources.getMessage(Locale.ENGLISH, "button.search").toLowerCase();
String view = resources.getMessage(Locale.ENGLISH, "button.view").toLowerCase();
String[] rules = {edit, save, search, view};
// Identify the request parameter containing the method name
//判断请求参数中是否包含method参数名称
String parameter = mapping.getParameter();
// don't set keyName unless it's defined on the action-mapping
// no keyName -> unspecified will be called
String keyName = null;
if (parameter != null) {
keyName = request.getParameter(parameter);
}
log.debug("BaseAction: keyName:" + keyName);
String path="";
if ((keyName == null) || (keyName.length() == 0)) {
for (int i = 0; i < rules.length; i++) {
// apply the rules for automatically appending the method name
//当keyName == null,即请求参数中不包含method参数名称时
//此时的path is:/editUser.html,而rules[0]="edit",
//通过indexOf操作,匹配并执行以下代码
//即当请求UserAction时,如果请求参数中没有method属性名,
//就默认执行edit方法,
//以这种方式实现默认操作,无言,有些晦涩,浪费了很多时间去阅读
if (request.getServletPath().indexOf(rules[i]) > -1) {
path = request.getServletPath();
log.debug("BaseAction: path is:" + path);
log.debug("BaseAction: rules[i] " + rules[i]);
log.debug("BaseAction: rules[i] index i= " + i);
return dispatchMethod(mapping, form, request, response, rules[i]);
}
}
if (log.isDebugEnabled()) {
log.debug("BaseAction: exit for" + keyName);
}
return this.unspecified(mapping, form, request, response);
}
// Identify the string to lookup
//如果请求参数中包含method参数名称时,取得Map值,执行对应的操作,如add
//操作。
String methodName =
getMethodName(mapping, form, request, response, parameter);
if (log.isDebugEnabled()) {
log.debug("BaseAction: parameter " + parameter);
}
return dispatchMethod(mapping, form, request, response, methodName);
}