ofbiz view渲染处理机制

1.1.1.1  初始化

       ControlServlet.java 这是一个servlet,其配置文件在web.xml里

      <servlet>
              <servlet-name>ControlServlet</servlet-name>
              <display-name>ControlServlet</display-name>
              <description>MainControl Servlet</description>
              <servlet-class>org.apache.ofbiz.webapp.control.ControlServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
       </servlet>
       <servlet-mapping>
              <servlet-name>ControlServlet</servlet-name>
              <url-pattern>/control/*</url-pattern>
       </servlet-mapping>

      这也是为什么大多数请求都是组件名/control/*

      首先在第一次请求时经过Servlet的init方法,该Servlet方法如下:

   public void init(ServletConfig config) throws ServletException {
       super.init(config);
       if (Debug.infoOn()) {
           ServletContext servletContext = config.getServletContext();
           String webappName = servletContext.getContextPath().length() != 0 ?servletContext.getContextPath().substring(1) : "";
           Debug.logInfo("Loading webapp [" + webappName + "],located at " + servletContext.getRealPath("/"), module);
   }


 
       //配置默认脚本引擎,默认有beanshell和平台自定义的minilang脚本,可扩展其它脚本
       configureBsf();
       // 初始化request处理句柄,实质就是加载controller.xml中handler节点中class属性值对应类的实例化和初始化
       getRequestHandler();
   }

该方法中的getRequestHandler就是获取所有的handler节点,加载方式如下

/**
    * @Title: getRequestHandler
    * @Description: 获取request的处理句柄,request处理分两类,一类是view,
    * 另一类是event,对应controller.xml中handler节点的配置信息的获取
    * @return: RequestHandler
    */
   protected RequestHandler getRequestHandler() {
       return RequestHandler.getRequestHandler(getServletContext());
}
/**
    * @Title: getRequestHandler
    * @Description: 在上下文中新建一个requesthandler,命名为_REQUEST_HANDLER_,
    * 构造方法为private,此方法共外界获取实例,为单例模式使用,requesthandler配置来至
    * 处理controller.xml中handler节点的配置数据
    * @param servletContext
    * @return: RequestHandler
    */
   public static RequestHandler getRequestHandler(ServletContextservletContext) {
       RequestHandler rh = (RequestHandler)servletContext.getAttribute("_REQUEST_HANDLER_");
       if (rh == null) {
           rh = newRequestHandler(servletContext);
           servletContext.setAttribute("_REQUEST_HANDLER_", rh);
       }
       return rh;
}

其中的RequestHandler方法如下

/**
    * @author jack
    * 第一步:将controller.xml的解析信息加入到缓存中
    * */
   private RequestHandler(ServletContext context) {
       // init the ControllerConfig, but don't save it anywhere, just load itinto the cache
       this.controllerConfigURL = ConfigXMLReader.getControllerConfigURL(context);
       try {
            //将controller.xml的解析信息加入到缓存中
           ConfigXMLReader.getControllerConfig(this.controllerConfigURL);
       } catch (WebAppConfigurationException e) {
           // FIXME: controller.xml errors should throw an exception.
           Debug.logError(e, "Exception thrown while parsing controller.xmlfile: ", module);
       }
       //加载ViewHandler实现类的实例,其为controller.xml中handler的类型为view
       this.viewFactory = new ViewFactory(context,this.controllerConfigURL);
       //加载EventHandler实现类的实例,其为controller.xml中handler的类型为非view的情况
       this.eventFactory = new EventFactory(context, this.controllerConfigURL);
 
       this.forceHttpSession ="true".equalsIgnoreCase(context.getInitParameter("forceHttpSession"));
       this.trackServerHit =!"false".equalsIgnoreCase(context.getInitParameter("track-serverhit"));
       this.trackVisit =!"false".equalsIgnoreCase(context.getInitParameter("track-visit"));
       this.cookies = !"false".equalsIgnoreCase(context.getInitParameter("cookies"));
       this.charset = context.getInitParameter("charset");
}

其具体存储方式如下

/**
    * @author jack
    * 构建ViewHandler实现类的map,对handler节点的class属性值对应的类进行实例化和初始化,
    * 并设置key=default时,其value=com.hanlin.fadp.webapp.view.JspViewHandler的实例
    * @param context
    * @param controllerConfigURL
    */
   public ViewFactory(ServletContext context, URL controllerConfigURL) {
       // load all the view handlers
        try {
           Set<Map.Entry<String,String>> handlerEntries =ConfigXMLReader.getControllerConfig(controllerConfigURL).getViewHandlerMap().entrySet();
           if (handlerEntries != null) {
                for(Map.Entry<String,String> handlerEntry: handlerEntries) {
                                          //将对应的handler给实例化
                    ViewHandlerhandler = (ViewHandler) ObjectType.getInstance(handlerEntry.getValue());
                   handler.setName(handlerEntry.getKey());
                    handler.init(context);
                    this.handlers.put(handlerEntry.getKey(),handler);
                }
           }
           // load the "default" type
           if (!this.handlers.containsKey("default")) {
                ViewHandler defaultHandler =(ViewHandler) ObjectType.getInstance("com.hanlin.fadp.webapp.view.JspViewHandler");
                defaultHandler.init(context);
                this.handlers.put("default", defaultHandler);
           }
       } catch (Exception e) {
           Debug.logError(e, module);
           throw new GeneralRuntimeException(e);
       }
    }

1.1.1.2  渲染处理

      在经过多contoller文件的request 和response标签处理后,其中的response中对应type=“view”会到对应的view-map标签处理,最终处理如下:

     try {
            if (Debug.verboseOn())Debug.logVerbose("Rendering view [" + nextPage + "] of type[" + viewMap.type + "]", module);
            ViewHandlervh = viewFactory.getViewHandler(viewMap.type);
            vh.render(view,nextPage, viewMap.info, contentType, charset, req, resp);
        } catch (ViewHandlerException e) {
            Throwable throwable = e.getNested()!= null ? e.getNested() : e;
 
            throw newRequestHandlerException(e.getNonNestedMessage(), throwable);
        }

       标记的第一步是根据key获取上文初始化中的对应ViewHandler实例,这个key来自于view-map中的screen.具体操作如下

   public ViewHandlergetViewHandler(String type) throws ViewHandlerException {
        if (UtilValidate.isEmpty(type)) {
            type = "default";
        }
        // get the view handler by type fromthe contextHandlers
        ViewHandler handler =handlers.get(type);
        if (handler == null) {
            throw newViewHandlerException("No handler found for type: " + type);
        }
        return handler;
    }

       标记的第二步是进行具体的渲染,针对于不同类型有不同实现类进行处理,在这里只是展示一下它的接口

   /**
     * Render the page.
     *
     * @param name The name of the view.
     * @param page The source of the view;could be a page, url, etc depending on the type of handler.
     * @param info An info string attached tothis view
     * @param request The HttpServletRequestobject used when requesting this page.
     * @param response The HttpServletResponseobject to be used to present the page.
     * @throws ViewHandlerException
     */
    public void render(String name, Stringpage, String info, String contentType, String encoding, HttpServletRequestrequest, HttpServletResponse response) throws ViewHandlerException;

         至此view的大致处理过程就清楚了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java学习

Java每日一练(2017/6/8)

Java基础 | 数据库 | Android | 学习视频 | 学习资料下载 课前导读 ●回复"每日一练"获取以前的题目! ●答案公布时间:为每期发布题目的第二...

2707
来自专栏黑泽君的专栏

day17_Listener与Filter学习笔记

    事件:就是一个事情。     事件源:产生这个事情的源头。     监听器:用于监听指定的事件的对象。(关联事件和事件源)     注册监听:要想让监听...

591
来自专栏数据结构与算法

BZOJ1269: [AHOI2006]文本编辑器editor

Descriptio 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗? 为了明确任务目标,可可对“文本编辑器...

2757
来自专栏SeanCheney的专栏

《利用Python进行数据分析·第2版》第6章 数据加载、存储与文件格式6.1 读写文本格式的数据6.2 二进制数据格式6.3 Web APIs交互6.4 数据库交互6.5 总结

访问数据是使用本书所介绍的这些工具的第一步。我会着重介绍pandas的数据输入与输出,虽然别的库中也有不少以此为目的的工具。 输入输出通常可以划分为几个大类:读...

5436
来自专栏我的小碗汤

golang 设置 http response 响应头与坑

之前遇到个问题,在一段代码中这样设置WriteHeader,最后在header中取Name时怎么也取不到。

852
来自专栏jeremy的技术点滴

JVM的Finalization Delay引起的OOM

3808
来自专栏Android相关

Android中的Proguard使用

之前介绍了如何使用命令行将Jar包根据配置文件进行ProGuard,以及ProGuard的过程,会遇到的问题等。接下来会介绍常用的ProGuard如何配置参数。...

1073
来自专栏图像识别与深度学习

蓝牙项目开发心得

3219
来自专栏Hongten

自己写的一个代码自动生成工具_java版_源码下载

这里要实现的功能是,当我们给出了bean,如:Admin,User,People等实体类后,

1K1
来自专栏Ryan Miao

Spring resource bundle多语言,单引号format异常

Spring resource bundle多语言,单引号format异常 source code 前言 十一假期被通知出现大bug,然后发现是多语言翻译问题。...

3728

扫码关注云+社区