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 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

AngularJS Providers 详解

供应者(Providers) ? Each web application you build is composed of objects that coll...

1855
来自专栏Google Dart

Dart 服务端开发 shelf_bind 包

shelf_bind倾向于约定优于配置,因此您可以编写必要的最小代码,但仍然可以根据需要覆盖默认值。

712
来自专栏颇忒脱的技术博客

Servlet 3.1 Async IO分析

Servlet Async Processing提供了一种异步请求处理的手段(见我的另一篇文章Servlet 3.0 异步处理详解),能够让你将Http thr...

803
来自专栏aoho求索

Spring中的事件驱动模型(一)

事件驱动模型 事件驱动模型通常也被理解成观察者或者发布/订阅模型。 是一种对象间的一对多的关系; 当目标发送改变(发布),观察者(订阅者)就可以接收到改变; ...

3055
来自专栏美团技术团队

这个Spring高危漏洞,你修补了吗?

前言 2009年9月Spring 3.0 RC1发布后,Spring就引入了SpEL(Spring Expression Language)。对于开发者而言,引...

57711
来自专栏代码拾遗

​SpringMVC 教程 - Handler Method

由注解@RequestMapping注解修饰的处理请求的函数的签名非常的灵活,可以使用controller函数支持的一系列参数和返回值。

871
来自专栏菩提树下的杨过

struts2: 玩转 rest-plugin

近期使用struts2的rest-plugin,参考官方示例struts2-rest-showcase,做了一个restful service小项目,但官网提供...

2425
来自专栏菩提树下的杨过

JAVA CDI 学习(2) - Scope 生命周期

在上一节中,我们已经知道了如何用@Inject实现基本注入,这一节研究Bean实例注入后的“生命周期”,web application中有几种基本的生命周期(不...

19110
来自专栏blackheart的专栏

[C#6] 8-异常增强

0. 目录 C#6 新增特性目录 1. 在catch和finally块中使用await 在C#5中引入一对关键字await/async,用来支持新的异步编程模型...

1785
来自专栏一个会写诗的程序员的博客

《Springboot极简教程》问题解决:Spring MVC 关于controller的字符编码问题描述原因分析@RequestMapping

在使用springMVC框架构建web应用,返回http请求json格式的数据,中文乱码。

692

扫码关注云+社区