转载

jfinal路由简单解析

在jfinal中,通过JFinalFilter对所有的类进行过滤。

以下是路由的调用关系(我在调用关系旁边做了标记,会贴出具体的代码和解释):

-1- Config:     Routes -2-     Interceptors     Handlers -3- public void init(){     createJFinalConfig     -4-     init:         initActionMapping:             new ActionMapping              buildActionMapping -5-         initHandler             new ActionHandler              getHandler          initRender } -6-     public void dofilter(){     -7-     handle:         Action action = new actionMapping.getAction(target) -8-         new ActionInvocation.invoke()         render }    

-1-Config是基本的配置。

在Config这个类中,Routes、Interceptors、Handlers均以成员变量的形式存在。

class Config {     private static final Routes routes = new Routes(){public void config() {}};     private static final Interceptors interceptors = new Interceptors();     private static final Handlers handlers = new Handlers(); }

-2-

Routes

在Route中有两个Map:map和viewPathMap。

map中放置的是controllerKey和controllerClass的键值对。

viewPathMap中放置的是controllerKey和viewPath的键值对。

public abstract class Routes {         private final Map<String, Class<? extends Controller>> map = new HashMap<String, Class<? extends Controller>>();     private final Map<String, String> viewPathMap = new HashMap<String, String>();     public Routes add(String controllerKey, Class<? extends Controller> controllerClass, String viewPath) {         if (controllerKey == null)             throw new IllegalArgumentException("The controllerKey can not be null");         // if (controllerKey.indexOf(".") != -1)             // throw new IllegalArgumentException("The controllerKey can not contain dot character: /"./"");         controllerKey = controllerKey.trim();         if ("".equals(controllerKey))             throw new IllegalArgumentException("The controllerKey can not be blank");         if (controllerClass == null)             throw new IllegalArgumentException("The controllerClass can not be null");         if (!controllerKey.startsWith("/"))             controllerKey = "/" + controllerKey;         if (map.containsKey(controllerKey))             throw new IllegalArgumentException("The controllerKey already exists: " + controllerKey);                  map.put(controllerKey, controllerClass);                  if (viewPath == null || "".equals(viewPath.trim()))    // view path is controllerKey by default             viewPath = controllerKey;                  viewPath = viewPath.trim();         if (!viewPath.startsWith("/"))                    // "/" added to prefix             viewPath = "/" + viewPath;                  if (!viewPath.endsWith("/"))                    // "/" added to postfix             viewPath = viewPath + "/";                  if (baseViewPath != null)                        // support baseViewPath             viewPath = baseViewPath + viewPath;                  viewPathMap.put(controllerKey, viewPath);         return this;     } }

-3-JFinalFilter中的init方法

public void init(FilterConfig filterConfig) throws ServletException {         createJFinalConfig(filterConfig.getInitParameter("configClass"));                  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());     }

-4-在JFinalFilter中调用了方法jfinal.init,进行初始化

boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {         this.servletContext = servletContext;         this.contextPath = servletContext.getContextPath();                  initPathUtil();                  Config.configJFinal(jfinalConfig);    // start plugin and init logger factory in this method         constants = Config.getConstants();                  initActionMapping();         initHandler();         initRender();         initOreillyCos();         initTokenManager();                  return true;     }

-5-在initActionMapping中将Routes和Interceptors组织起来。其中,在initActionMapping中有一个重要的方法:buildActionMapping

    void buildActionMapping() {         mapping.clear();         Set<String> excludedMethodName = buildExcludedMethodName();         ActionInterceptorBuilder interceptorBuilder = new ActionInterceptorBuilder();         Interceptor[] globalInters = interceptors.getGlobalActionInterceptor();         interceptorBuilder.addToInterceptorsMap(globalInters);         for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) {             Class<? extends Controller> controllerClass = entry.getValue();             Interceptor[] controllerInters = interceptorBuilder.buildControllerInterceptors(controllerClass);                          boolean sonOfController = (controllerClass.getSuperclass() == Controller.class);             Method[] methods = (sonOfController ? controllerClass.getDeclaredMethods() : controllerClass.getMethods());             for (Method method : methods) {                 String methodName = method.getName();                 if (excludedMethodName.contains(methodName) || method.getParameterTypes().length != 0)                     continue ;                 if (sonOfController && !Modifier.isPublic(method.getModifiers()))                     continue ;                                  Interceptor[] methodInters = interceptorBuilder.buildMethodInterceptors(method);                 Interceptor[] actionInters = interceptorBuilder.buildActionInterceptors(globalInters, controllerInters, methodInters, method);                 String controllerKey = entry.getKey();                                  ActionKey ak = method.getAnnotation(ActionKey.class);                 String actionKey;                 if (ak != null) {                     actionKey = ak.value().trim();                     if ("".equals(actionKey))                         throw new IllegalArgumentException(controllerClass.getName() + "." + methodName + "(): The argument of ActionKey can not be blank.");                                          if (!actionKey.startsWith(SLASH))                         actionKey = SLASH + actionKey;                 }                 else if (methodName.equals("index")) {                     actionKey = controllerKey;                 }                 else {                     actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName;                 }                                  Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));                 if (mapping.put(actionKey, action) != null)                     throw new RuntimeException(buildMsg(actionKey, controllerClass, method));             }         }                  // support url = controllerKey + urlParas with "/" of controllerKey         Action actoin = mapping.get("/");         if (actoin != null)             mapping.put("", actoin);     }

-6-JFinalFilter中的doFilter。在doFilter中主要是调用了handle方法。

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);         }         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);     }

-7-handle方法

/**      * 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) {             return ;         }                  isHandled[0] = true;         String[] urlPara = {null};         //通过url得到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 {             //根据action得到controller!!!             Controller controller = action.getControllerClass().newInstance();             controller.init(request, response, urlPara[0]);                          if (devMode) {                 boolean isMultipartRequest = ActionReporter.reportCommonRequest(controller, action);                 //用获得的action进行调用处理请求!!!                 new Invocation(action, controller).invoke();                 if (isMultipartRequest) ActionReporter.reportMultipartRequest(controller, action);             }             else {                 new Invocation(action, controller).invoke();             }                          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();         }     }

-8-getAction方法:通过url得到action

    Action getAction(String url, String[] urlPara) {         Action action = mapping.get(url);         if (action != null) {             return action;         }                  // --------         int i = url.lastIndexOf(SLASH);         if (i != -1) {             action = mapping.get(url.substring(0, i));             urlPara[0] = url.substring(i + 1);         }                  return action;     }
原文  https://segmentfault.com/a/1190000004933612
正文到此结束
Loading...