RequestHandler,可以称之为请求处理器,在ControlServlet.init()中初始化:
public class ControlServlet extends HttpServlet { public void init(ServletConfig config) throws ServletException { super.init(config); // configure custom BSF engines configureBsf(); // initialize the request handler getRequestHandler(); } protected RequestHandler getRequestHandler() { return RequestHandler.getRequestHandler(getServletContext()); } }
ControlServlet没有为RequestHandler定义变量,而是放在ServletContext中。一个ServletContext只允许有一个RequestHandler。
public class RequestHandler { public static RequestHandler getRequestHandler(ServletContext servletContext) { RequestHandler rh = (RequestHandler) servletContext.getAttribute("_REQUEST_HANDLER_"); if (rh == null) { rh = new RequestHandler(); servletContext.setAttribute("_REQUEST_HANDLER_", rh); rh.init(servletContext); } return rh; } }
RequestHandler的构造器是空的,它的初始化放在init()中。
public class RequestHandler { public void init(ServletContext context) { this.context = context; // init the ControllerConfig, but don't save it anywhere // 初始化ControllerConfig, 但是不要保存它 this.controllerConfigURL = ConfigXMLReader.getControllerConfigURL(context); ConfigXMLReader.getControllerConfig(this.controllerConfigURL); this.viewFactory = new ViewFactory(this); this.eventFactory = new EventFactory(this); } }
RequestHandler对应的配置文件是WEB-INF/controller.xml,透过ConfigXMLReader处理。OFBiz处理controller.xml使用了缓存,超时时会被自动清理。所以,当OFBiz类中需要ControllerConfig时,不会定义一个变量保存ControllerConfig,而只是定义一个controller.xml对应的URL变量,因为ConfigXMLReader以URL为Key缓存ControllerConfig。RequestHandler的doRequest()获取ControllerConfig就是这样处理的:
public class RequestHandler { public void doRequest(HttpServletRequest request, HttpServletResponse response, String chain, GenericValue userLogin, Delegator delegator) throws RequestHandlerException { ... ... // get the controllerConfig once for this method so we don't have to get it over and over inside the method ConfigXMLReader.ControllerConfig controllerConfig = this.getControllerConfig(); Map<String, ConfigXMLReader.RequestMap> requestMapMap = controllerConfig.getRequestMapMap(); ... ... } public ConfigXMLReader.ControllerConfig getControllerConfig() { return ConfigXMLReader.getControllerConfig(this.controllerConfigURL); } }
RequestHandler包含了一个ViewFactory对象和一个EventFactory对象。ViewFactory对象的初始化由自身的构造器完成。
public class ViewFactory { public ViewFactory(RequestHandler requestHandler) { this.handlers = FastMap.newInstance(); this.requestHandler = requestHandler; this.context = requestHandler.getServletContext(); // pre-load all the view handlers try { this.preLoadAll(); } catch (ViewHandlerException e) { Debug.logError(e, module); throw new GeneralRuntimeException(e); } } }
ViewFactory初始时,调用preLoadAll()装入所有在controller.xml中定义的ViewHandler。
public class ViewFactory { private void preLoadAll() throws ViewHandlerException { Set<String> handlers = this.requestHandler.getControllerConfig().getViewHandlerMap().keySet(); if (handlers != null) { for (String type: handlers) { this.handlers.put(type, this.loadViewHandler(type)); } } // load the "default" type if (!this.handlers.containsKey("default")) { try { ViewHandler h = (ViewHandler) ObjectType.getInstance("org.ofbiz.webapp.view.JspViewHandler"); h.init(context); this. handlers.put("default", h); } catch (Exception e) { throw new ViewHandlerException(e); } } } }
loadViewHandler()执行具体的ViewHandler初始化。
public class ViewFactory { private ViewHandler loadViewHandler(String type) throws ViewHandlerException { ViewHandler handler = null; String handlerClass = this.requestHandler.getControllerConfig().getViewHandlerMap().get(type); if (handlerClass == null) { throw new ViewHandlerException("Unknown handler type: " + type); } try { handler = (ViewHandler) ObjectType.getInstance(handlerClass); handler.setName(type); handler.init(context); } catch (ClassNotFoundException cnf) { //throw new ViewHandlerException("Cannot load handler class", cnf); Debug.logWarning("Warning: could not load view handler class because it was not found; note that some views may not work: " + cnf.toString(), module); } catch (InstantiationException ie) { throw new ViewHandlerException("Cannot get instance of the handler", ie); } catch (IllegalAccessException iae) { throw new ViewHandlerException(iae.getMessage(), iae); } return handler; } }
ViewHandler对象创建后,紧接着执行其init()方法。以具体的VelocityViewHandler为例,其inti()方法就完成了VelocityEngine的初始化。
public class VelocityViewHandler extends AbstractViewHandler { public void init(ServletContext context) throws ViewHandlerException { try { Debug.logInfo("[VelocityViewHandler.init] : Loading...", module); ve = new VelocityEngine(); // set the properties // use log4j for logging // use classpath template loading (file loading will not work in WAR) ve.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogSystem"); ve.setProperty("runtime.log.logsystem.log4j.category", module); Properties props = null; try { props = UtilProperties.getProperties(context.getResource("/WEB-INF/velocity.properties")); Debug.logInfo("[VelocityViewHandler.init] : Loaded /WEB-INF/velocity.properties", module); } catch (MalformedURLException e) { Debug.logError(e, module); } if (props == null) { props = new Properties(); Debug.logWarning("[VelocityViewHandler.init] : Cannot load /WEB-INF/velocity.properties. " + "Using default properties.", module); } // set the file loader path -- used to mount the webapp if (context.getRealPath("/") != null) { props.setProperty("file.resource.loader.path", context.getRealPath("/")); Debug.logInfo("[VelocityViewHandler.init] : Got true webapp path, mounting as template path.", module); } ve.init(props); } catch (Exception e) { throw new ViewHandlerException(e.getMessage(), e); } } }