1 当访问某个链接之后JFinal便会调用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();//获取URI如访问 /app/login if (contextPathLength != 0) target = target.substring(contextPathLength);//去除weapp name boolean[] isHandled = {false};//是否处理标识符 try { 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);//继续处理chain上其他操作 }
handler.handle(target, request, response, isHandled);
handler中的方法handle方法为抽象方法,由于为加载其他插件,先分析ActionHandler中的handle方法
final class ActionHandler extends Handler { private final boolean devMode; private final ActionMapping actionMapping; private static final RenderFactory renderFactory = RenderFactory.me(); private static final Logger log = Logger.getLogger(ActionHandler.class); public ActionHandler(ActionMapping actionMapping, Constants constants) { this.actionMapping = actionMapping; this.devMode = constants.getDevMode(); } /** * handle * 1: Action action = actionMapping.getAction(target) * 2: new Invocation(...).invoke() * 3: render(...) */ public final void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) { if (target.indexOf('.') != -1) {//urk中存在.则跳过 return ; } isHandled[0] = true;//标识为true String[] urlPara = {null};//url参数数组 Action action = actionMapping.getAction(target, urlPara);//从actionMAp中获取处理的action对象 if (action == null) {//为空则返回404 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();//获取action的具体Controller的名字并实例化,高并发和访问估计会带来问题 controller.init(request, response, urlPara[0]);//初始化request,response,以及url参数 if (devMode) { boolean isMultipartRequest = ActionReporter.reportCommonRequest(controller, action);//判断是否需要打印相关信息到控制台 new Invocation(action, controller).invoke();//调用invoke方法进行处理,此为核心代码。 if (isMultipartRequest) ActionReporter.reportMultipartRequest(controller, action); } else { new Invocation(action, controller).invoke(); } Render render = controller.getRender();//get the render if (render instanceof ActionRender) { String actionUrl = ((ActionRender)render).getActionUrl();//获取actionURl if (target.equals(actionUrl)) throw new RuntimeException("The forward action url is the same as before."); else handle(actionUrl, request, response, isHandled); return ; } //不涉及渲染的操作render为null 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(); } } }
以下为核心处理代码
new Invocation(action, controller).invoke();
public void invoke() { // inters为此action的拦截器栈,依次执行此action的拦截器,由初始化过程可知,拦截器顺序依次为 全局,controller,method //此方法是个递归方法 拦截器01_before->拦截器02_before->xx_before->action.getMethod.invoke(controller,NULL_ARGS)->xx_after->拦截器02_after->拦截器01_after //作者原话:inters是一个拦截器数组,index变量是指向这个数组当前正在执行的拦截器的下标。ActionInvocation.invoke()方法是一个递归调用,此递归属于间接递归,即:ActionInvocation.invoke()中调用了Interceptor.intercepte(ActionInvocation ai),而Interceptor.intercepte(ai)方法中开发者又调用了ai.invoke(),形成间接递归关系。每次递归index变量值会加一,直到index==inters.length递归终止,此时会调用Controller中的方法。这个设计构成了拦截器对action的环绕型拦截,是一种精巧、简洁、高效的设计。 //作者原话: if (index < inters.length) { inters[index++].intercept(this);//逐个处理拦截 } //拦截器执行完则开始执行controller中的方法 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);//调用该controller中的方法 } // Invoke the method else { // if (!Modifier.isAbstract(method.getModifiers())) // returnValue = methodProxy.invokeSuper(target, args); if (useInjectTarget)//判断method是否为抽象方法 returnValue = methodProxy.invoke(target, args); else returnValue = methodProxy.invokeSuper(target, args);//利用cglib的代理调用父类方法 } } 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); } } }