JpetStore中MVC机制实现的研究,BeanAction以及BaseBean工作机制(看完有种恍然大悟的感觉啊!)...

本文详细解析了iBATIS JPetStore中BeanAction的实现原理,揭示了如何利用反射机制调用BaseBean中的方法,以及ActionInterceptor接口在处理请求过程中的作用。
以前学习iBATIS时候只是粗略的看了一下代码,今天翻出来从新看了看,才发现iBATIS给的JpetStore中关于iBATIS的实现简直太精妙了,它直接把action和actionform合并在一起~ very good!!!

JpetStore的src文件夹,并无一个具体的Action,那么它是如何来完成普通Struts的Action工作了?
查看JpetStore的struts-config.xml可以发现,它的Action只有一个,即 “org.apache.stuts.beanaction.Beanaction”。通过Eclipse查看直接跳转到beanaction.jar的源代码,可以发现Beanaction继承了普通Action,即具备普通的action的功能。那么它具体Action的奥妙在哪,继续研究BeanAction的代码,发现BeanAction其实只有一个方法,源代码如下:

public final ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
String forward = SUCCESS_FORWARD;
try {
if (!(form instanceof BaseBean)) {
if (form != null) {
throw new BeanActionException("The form for mapping '" + mapping.getPath() + "' named '" + mapping.getName() + "' was not an instance of BaseBean. BeanAction requires an BaseBean instance.");
} else {
throw new BeanActionException("The form for mapping '" + mapping.getPath() + "' named '" + mapping.getName() + "' was null. BeanAction requires an BaseBean instance.");
}
}
BaseBean bean = (BaseBean) form;
ActionContext.initCurrentContext(request, response);
if (bean != null) {
// Explicit Method Mapping

Method method = null;
String methodName = mapping.getParameter();
if (methodName != null && !NO_METHOD_CALL.equals(methodName)) {
try {
method = bean.getClass().getMethod(methodName, null);
synchronized (bean) {
forward = bean.getInterceptor().intercept(new ActionInvoker(bean, method));
}
} catch (Exception e) {
throw new BeanActionException("Error dispatching bean action via method parameter ('" + methodName + "'). Cause: " + e, e);
}
}


// Path Based Method Mapping

if (method == null && !NO_METHOD_CALL.equals(methodName)) {
methodName = mapping.getPath();
if (methodName.length() > 1) {
int slash = methodName.lastIndexOf("/") + 1;
methodName = methodName.substring(slash);
if (methodName.length() > 0) {
try {
method = bean.getClass().getMethod(methodName, null);
synchronized (bean) {
forward = bean.getInterceptor().intercept(new ActionInvoker(bean, method));
}
} catch (Exception e) {
throw new BeanActionException("Error dispatching bean action via URL pattern ('" + methodName + "'). Cause: " + e, e);
}
}
}
}
}
} catch (Exception e) {
forward = "error";
request.setAttribute("BeanActionException", e);
}
return mapping.findForward(forward);
}


最关键的地方应该就是这里:

/*通过反射,根据得到的方法名称取得方法的句柄*/
method = bean.getClass().getMethod(methodName, null);
synchronized (bean) {
/*下面是关键一句,调用basebean拥有的接口ActionInterceptor的实现DefaultActionInterceptor,来完成具体方法的调用*/
forward = bean.getInterceptor().intercept(new ActionInvoker(bean, method));
}

而ActionInvoker中

public String invoke() {
try {
return (String) method.invoke(bean, null);
} catch (Exception e) {
throw new BeanActionException("Error invoking Action. Cause: " + e, e);
}
}

至此可知,它调用的是formbean中的函数。且从这段代码可知,formbean的这类特殊函数,此处称为action方法,要符合两个特征:1)无参数;2)返回值为string,此返回string即是struts-config.xml的全局或局部的forward。



高手估计会不屑一顾,但是新手们绝对有用,还有不懂的可以看iBATIS实战中的第14章,非常经典http://book.youkuaiyun.com/bookfiles/700/
这个网站有免费试读。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值