1、在全局拦截器JFinalFilter的初始化函数init中会调用JFinal的init方法,在该方法中会调用initHandler();、
//JFinal类 boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) { this.servletContext = servletContext; this.contextPath = servletContext.getContextPath(); initPathUtil(); Config.configJFinal(jfinalConfig); // start plugin and init log factory in this method constants = Config.getConstants(); initActionMapping(); initHandler(); //初始化handler,Handler 可以接管所有web请求,并对应用拥有完的控制权,可以很方便地实现更高层的功能性扩展 initRender(); initOreillyCos(); initTokenManager(); return true; }
2、initHandler()方法中会对ActionHandler初始化
private void initHandler() { Handler actionHandler = new ActionHandler(actionMapping, constants); //初始化action的handler handler = HandlerFactory.getHandler(Config.getHandlers().getHandlerList(), actionHandler); }
3、当请求被JFinalFilter拦截时(doFilter),会调用ActionHandler的handle()方法.
//JFinalFilter类 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) target = target.substring(contextPathLength); boolean[] isHandled = {false}; try { handler.handle(target, request, response, isHandled); //调用handler(handler已经在第一步中初始化过) } 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); }
//ActionHandler类 public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) { if (target.indexOf('.') != -1) { return ; } isHandled[0] = true; String[] urlPara = {null}; Action action = actionMapping.getAction(target, urlPara); //获取请求中的action 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 controller = action.getControllerClass().newInstance(); controller.init(request, response, urlPara[0]);//初始化action所属的controller if (devMode) { //开发模式 if (ActionReporter.isReportAfterInvocation(request)) { new Invocation(action, controller).invoke(); ActionReporter.report(controller, action); } else { ActionReporter.report(controller, action); new Invocation(action, controller).invoke(); } } else { new Invocation(action, controller).invoke(); //初始化Invocation } 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, action.getViewPath()).render(); } catch (Throwable t) { if (log.isErrorEnabled()) { String qs = request.getQueryString(); log.error(qs == null ? target : target + "?" + qs, t); } renderFactory.getErrorRender(500).setContext(request, response, action.getViewPath()).render(); } }
5、Invocation类的结构(成员变量)
private Object target; //拦截的目标对象 private Method method; //拦截到的目标对象中的方法 private Object[] args; //方法的参数 private MethodProxy methodProxy; //方法代理, private Interceptor[] inters; //每个方法的所有拦截器
6、Invocation类中invoke方法如下:
public void invoke() { if (index < inters.length) { inters[index++].intercept(this); //执行拦截器的intercept方法,传入了Invocation对象this作为参数,在每个拦截器intercept方法中,会再次调用Invocation的invoke方法,达到遍历执行所有拦截器 } else if (index++ == inters.length) { // index++ ensure invoke action only one time try { // Invoke the action if (action != null) { returnValue = action.getMethod().invoke(target, args); } // Invoke the method else { // if (!Modifier.isAbstract(method.getModifiers())) // returnValue = methodProxy.invokeSuper(target, args); if (useInjectTarget) returnValue = methodProxy.invoke(target, args); else returnValue = methodProxy.invokeSuper(target, args); } } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); throw t instanceof RuntimeException ? (RuntimeException)t : new RuntimeException(e); } catch (RuntimeException e) { throw e; } catch (Throwable t) { throw new RuntimeException(t); } } }