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://www.cnblogs.com/SZLLQ2000/p/5767643.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JFinal 中,路由配置规则主要由以下几种方式实现: 1. 使用 @RoutePath 注解 在 Controller 类中的方法上使用 @RoutePath 注解,可以指定该方法对应的路由规则,例如: ```java @RoutePath("/user/:id") public void getUser(int id) { // 处理用户信息 } ``` 上述代码中,使用 @RoutePath 注解指定了路由规则为 /user/:id,其中 :id 表示动态参数,可以在方法中以参数形式获取。 2. 使用配置文件 在 JFinal 的配置文件中,可以使用 routes 属性来指定路由规则,例如: ```java public void configRoute(Routes routes) { routes.add("/user", UserController.class, "/user"); } ``` 上述代码中,使用 routes.add() 方法来添加路由规则,其中第一个参数为请求路径前缀,第二个参数为处理请求的 Controller 类名,第三个参数为视图路径前缀。在这种方式下,请求路径为 /user/:method,其中 :method 表示请求方法名。 3. 使用 JFinal 提供的默认路由规则 JFinal 提供了一些默认的路由规则,例如: ```java // 自动扫描 Controller 类并添加路由规则 routes.scan(); // 添加默认路由规则 routes.add(new DefaultRoute("/user", UserController.class)); ``` 上述代码中,使用 routes.scan() 方法可以自动扫描 Controller 类并添加路由规则,使用 DefaultRoute 类可以添加默认路由规则。 总的来说,JFinal路由配置规则非常灵活,可以根据实际需求选择不同的方式来进行配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值