欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-02 17:02:07
...

以前学习iBATIS时候只是粗略的看了一下代码,今天翻出来从新看了看,才发现iBATIS给的JpetStore中关于iBATIS的实现简直太精妙了,它直接把action和actionform合并在一起~JpetStore中MVC机制实现的研究,BeanAction以及BaseBean工作机制(看完有种恍然大悟的感觉啊!)
            
    
    博客分类: Java 工作MVCBeaniBATISStruts  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.csdn.net/bookfiles/700/

这个网站有免费试读。