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

jfinal路由简单解析的更多相关文章

  1. ASP.NET路由模型解析

    大家好,我又来吹牛逼了 ~-_-~ 转载请注明出处:来自吹牛逼之<ASP.NET路由模型解析> 背景:很多人知道Asp.Net中路由怎么用的,却不知道路由模型内部的运行原理,今天我就给大家 ...

  2. kubernetes源码解析---- apiserver路由构建解析(1)

    kubernetes源码解析---- apiserver路由构建解析(1) apiserver作为k8s集群的唯一入口,内部主要实现了两个功能,一个是请求的路由和处理,简单说就是监听一个端口,把接收到 ...

  3. Python Flask框架路由简单实现

    Python Flask框架路由的简单实现 也许你听说过Flask框架.也许你也使用过,也使用的非常好.但是当你在浏览器上输入一串路由地址,跳转至你所写的页面,在Flask中是怎样实现的,你是否感到好 ...

  4. kubernetes源码解析---- apiserver路由构建解析(2)

    kubernetes源码解析---- apiserver路由构建解析(2) 上文主要对go-restful这个包进行了简单的介绍,下面我们通过阅读代码来理解apiserver路由的详细构建过程. (k ...

  5. 对 cloudwu 简单的 cstring 进行简单解析

    题外话 以前也用C写过字符串,主要应用的领域是,大字符串,文件读取方面.写的很粗暴,用的凑合着.那时候看见云风前辈的一个开源的 cstring 串. 当时简单观摩了一下,觉得挺好的.也没细看.过了较长 ...

  6. 基于DOM的XSS注入漏洞简单解析

    基于DOM的XSS注入漏洞简单解析http://automationqa.com/forum.php?mod=viewthread&tid=2956&fromuid=21

  7. 15.5 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表

    点击返回:自学Zabbix之路 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表  1. Actions表 actions表记录了当触发器触发时,需要采用的动作. 2.Aler ...

  8. 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)

    深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...

  9. List<T>集合的Sort自定义排序用法简单解析

    List<T>集合的Sort自定义排序用法简单解析: 如下:一系列无序数字,如果想要他们倒序排列,则使用如下代码: 那么如何理解这段代码呢? (x,y)表示相邻的两个对象,如果满足条件:x ...

随机推荐

  1. 每天一个linux命令---curl

    linux curl是一个利用URL规则在命令行下工作的文件传输工具.详细请参考:http://www.codesky.net/article/201010/170043.html 例如:curl ' ...

  2. angularjs指令(二)

    最近学习了下angularjs指令的相关知识,也参考了前人的一些文章,在此总结下. 欢迎批评指出错误的地方.   Angularjs指令定义的API AngularJs的指令定义大致如下 angula ...

  3. js 四舍五入保留二位小数

    1. 最笨的办法....... [我就怎么干的.........] function get() { var s = 22.127456 + ""; var str = s.sub ...

  4. Grunt vs Gulp

    grunt vs gulp 虽然gulp已经出来很久了,但是一直没有去使用过.得益于最近项目需要,就尝试了一下,以下从几个要点讲一下grunt和gulp使用的区别,侧重讲一下在使用gulp过程中发现的 ...

  5. node.js 调用天气webservice接口

    首先安装soap模块 npm install soap 1 2 3 4 5 6 7 8 9 10   var soap = require('soap');   var url = 'http://w ...

  6. ACM: Happy 2004-数论专题-因子求和-快速幂

    Happy 2004 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descript ...

  7. NOIP 2005 青蛙过河

    做题记录:2016-08-10 21:58:09 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都 ...

  8. js中继承的几种用法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 <SPAN style="BACKGROUND-COLOR: #ffffff">& ...

  9. 【CodeVS】p1038 一元三次方程求解

    题目描述 Description 有形如:ax3+bx2+cx+d=0  这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d  均为实数),并约定该方程存在三个不同实根(根的范围在-100 ...

  10. iOS 两种易混淆的存储路径

    一,NSBundle 1>我们可以通过解压等操作获取 NSBundle 中的内容. 2>NSBundle主要是包路径,也就是代码编译后的 imge 和 sb 资源文件... 3>例如 ...