zoukankan      html  css  js  c++  java
  • 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;
        }
  • 相关阅读:
    Java8中的LocalDateTime工具类
    纳德拉再造微软:市值如何重回第一阵营(思维确实变了,不再是以windows为中心,拥抱其它各种平台,敢在主战场之外找到适合自己的新战场)
    马化腾,直接把360做特了!(人从一生下来牙牙学语开始,就在模仿,关键在于在已有的基础上进行改进,提高用户体验!)
    RISC-V首度被我国列入扶持对象,上海已成RISC-V重要“据点”
    Oracle高水位线
    oracle优化:避免全表扫描
    oracle中in和exists的区别
    分库、分表
    missing required source folder
    varnish页面缓存服务
  • 原文地址:https://www.cnblogs.com/SZLLQ2000/p/5767643.html
Copyright © 2011-2022 走看看