前言:上一节,我们新建了一个jfinal 的项目。接下来,我们初步理解下jfinal
我们理解一个东西,肯定是从我们看到的开始。我们看到了页面,看到了我们访问的地址返回了Hello Jfinal World这个串。我们看看程序的运行。
一、当我们启动程序时
1、进入web.xml加载过滤器com.jfinal.core.JFinalFilter,并执行 init 方法,我们来看看这个方法
public void init(FilterConfig filterConfig) throws ServletException { private Handler handler; private String encoding; private JFinalConfig jfinalConfig; private Constants constants; private static final JFinal jfinal = JFinal.me(); private static Logger log; private int contextPathLength; /** //分步将第一行代码 1、 filterConfig.getInitParameter("configClass"), 这方法是获取启动参数,我们在web.xml中配置了 <init-param> <param-name>configClass</param-name> <param-value>demo.DemoConfig</param-value> </init-param> 所以这个方法取到的就是 demo.DemoConfig这个字符串 2、createJFinalConfig("demo.DemoConfig"),主要做了几件事: 1)反射得到 DemoConfig这个类,并实例化了一个DemoConfig 对象; 2)jfinalConfig = DemoConfig实例化的对象 */ createJFinalConfig(filterConfig.getInitParameter("configClass")); /** jfinal.init,这里是根据DemoConfig初始化,主要为: initPathUtil();//初始化页面路径 //初始化插件,暂时没用插件 Config.configJFinal(jfinalConfig); // start plugin and init logger factory in this method //初始化常量,没用到 constants = Config.getConstants(); //初始化 ActionMapping,即 页面请求路径 与 处理请求的action的对应关系。举个栗子: 在 DemoConfig类中的configRoute(Routes me),我们 me.add("/hello", HelloController.class); 那么此时初始化后,我们就得到了这个一个map { "hello":{renderText("Hello JFinal World."))} } 如果 HelloController 中 还有其他 方法,例如 delete,add 啊。那么这个map就会变成这样 { "hello":{renderText("Hello JFinal World."))} "hello/add":{处理add的action} "hello/delete":{处理 delete的action} } 所以最总,我们访问一个地址时,时由它所对应的action来处理的 initActionMapping(); //初始化handler,让 jfinal 中的ActionHandler 成为默认的handler initHandler(); //下面几个就不细说了 initRender(); initOreillyCos(); initI18n(); initTokenManager(); */ if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false) throw new RuntimeException("JFinal init error!"); handler = jfinal.getHandler(); constants = Config.getConstants(); encoding = constants.getEncoding(); jfinalConfig.afterJFinalStart(); String contextPath = filterConfig.getServletContext().getContextPath(); contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length()); }
看完这个init 方法,我们可以知道的是:它初始化了 路劲对应action的关系,初始化的 默认handler,还有些编码(至于初始化数据库访问插件,因为我们还没用到就不看了)。
二、当请求来临时 :
执行 dofilter 方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; request.setCharacterEncoding(encoding); String target = request.getRequestURI(); if (contextPathLength != 0) //获取目标路径,这样才能从actionMapping 中找到处理 这个请求的action,我们这是得到target="hello" target = target.substring(contextPathLength); boolean[] isHandled = {false}; try { //这个是关键,此时的handler是actionhandler的实例化对象,我们进去handle方法看一下,源码在下面 handler.handle(target, request, response, isHandled); } catch (Exception e) { if (log.isErrorEnabled()) { String qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, e); } } if (isHandled[0] == false) chain.doFilter(request, response); }
public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) { if (target.indexOf(".") != -1) { return ; } isHandled[0] = true; String[] urlPara = {null}; //根据hello 从map中获取到处理它的action Action action = actionMapping.getAction(target, urlPara); if (action == null) { if (log.isWarnEnabled()) { String qs = request.getQueryString(); log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs)); } renderFactory.getErrorRender(404).setContext(request, response).render(); return ; } try { //获取处理它的controller这里是HelloController Controller controller = action.getControllerClass().newInstance(); //控制器初始化,拿到 request,response对象,后面就由这个控制器来操作 request和response了, controller.init(request, response, urlPara[0]); if (devMode) { boolean isMultipartRequest = ActionReporter.reportCommonRequest(controller, action); new ActionInvocation(action, controller).invoke(); if (isMultipartRequest) ActionReporter.reportMultipartRequest(controller, action); } else { new ActionInvocation(action, controller).invoke(); } //我们的例子最后的结果就是response返回了 Hello JFinal World. 字符串,所以我们页面上看到了字符串 Render render = controller.getRender(); if (render instanceof ActionRender) { String actionUrl = ((ActionRender)render).getActionUrl(); if (target.equals(actionUrl)) throw new RuntimeException("The forward action url is the same as before."); else handle(actionUrl, request, response, isHandled); return ; } if (render == null) render = renderFactory.getDefaultRender(action.getViewPath() + action.getMethodName()); render.setContext(request, response, action.getViewPath()).render(); } catch (RenderException e) { if (log.isErrorEnabled()) { String qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, e); } } catch (ActionException e) { int errorCode = e.getErrorCode(); if (errorCode == 404 && log.isWarnEnabled()) { String qs = request.getQueryString(); log.warn("404 Not Found: " + (qs == null ? target : target + "?" + qs)); } else if (errorCode == 401 && log.isWarnEnabled()) { String qs = request.getQueryString(); log.warn("401 Unauthorized: " + (qs == null ? target : target + "?" + qs)); } else if (errorCode == 403 && log.isWarnEnabled()) { String qs = request.getQueryString(); log.warn("403 Forbidden: " + (qs == null ? target : target + "?" + qs)); } else if (log.isErrorEnabled()) { String qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, e); } e.getErrorRender().setContext(request, response).render(); } catch (Exception e) { if (log.isErrorEnabled()) { String qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, e); } renderFactory.getErrorRender(500).setContext(request, response).render(); } }