实习期间,公司使用jfinal做开发,所以就学习了这个框架

Jfinal作为一个极速ORM,使用上非常方便,核心源代码1万多行,压缩后只有200多KB。

从入口开始

作为一个web项目,首先解读web.xml文件,其中配置了一个filter,

<filter-class>com.jfinal.core.JFinalFilter</filter-class>

finalfilter继承了filter。

关于filkter:filter是jsp中的一个接口,需要实现的方法有Init(),doFilter(),和destroy()三个必要的方法。

打开源代码中的JfinalFilter往下解读进入public void init(FilterConfig filterConfig) ,createJFinalConfig函数作用是初始化jfinalConfig,它使用了java反射方式查找,使用class.newInstance()方法实例化一个对象,再将temp对象强制转化成JFinalConfig对象

初始化完成jfinalConfig之后,使用了jfinal.init(jfinalConfig, filterConfig.getServletContext())这一方法。

再次进入JFinal类

public final class JFinal{
  .............
  boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
   this.servletContext = servletContext;
   this.contextPath = servletContext.getContextPath();
   initPathUtil();//获得webroot路径
   Config.configJFinal(jfinalConfig); // start plugin and init logger factory in this method
   constants = Config.getConstants();
   initActionMapping();
   initHandler();
   initRender();
   initActiveRecord();
   initOreillyCos();
   initI18n();
   initTokenManager();
   return true;
   }
}

Config.configJFinal(jfinalConfig);方法为Config类中的几个静态变量赋值,并启动插件

initActionMapping();initHandler();initRender();initActiveRecord();initOreillyCos();initI18n();initTokenManager();依次做了初始化工作。

private void initActionMapping() {
actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors()); //传入了jfinalconfig中的routs和Interceptors,jfinalConfig中的Interceptors为全局拦截器
actionMapping.buildActionMapping();
}

initActionMapping是jfinal中核心设计,代码比较长

private final Map<String, Action> mapping = new HashMap<String, Action>();

void buildActionMapping() {
mapping.clear();
Set<String> excludedMethodName = buildExcludedMethodName(); //获得Controller自带的一些方法名称
InterceptorBuilder interceptorBuilder = new InterceptorBuilder();
Interceptor[] defaultInters = interceptors.getInterceptorArray();
interceptorBuilder.addToInterceptorsMap(defaultInters);
for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) {//循环遍历routs
Class<? extends Controller> controllerClass = entry.getValue();
Interceptor[] controllerInters = interceptorBuilder.buildControllerInterceptors(controllerClass); //在buildControllerInterceptors方法中,如果有Before声明
Method[] methods = controllerClass.getMethods(); //获取controllerClass所有方法
for (Method method : methods) {
String methodName = method.getName();
if (!excludedMethodName.contains(methodName) && method.getParameterTypes().length == 0) { //无参数函数为action,且不是基类Controller.class包含的方法
Interceptor[] methodInters = interceptorBuilder.buildMethodInterceptors(method);//在此方法中 查找Before
Interceptor[] actionInters = interceptorBuilder.buildActionInterceptors(defaultInters, controllerInters, controllerClass, methodInters, method);//返回整个action的拦截器[Interceptor]
String controllerKey = entry.getKey(); //controllerKey即为path路径 ActionKey ak = method.getAnnotation(ActionKey.class);//获得注解actionkey
if (ak != null) {
String 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; if (mapping.containsKey(actionKey)) {
warnning(actionKey, controllerClass, method);
continue;
} Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
mapping.put(actionKey, action);
}
else if (methodName.equals("index")) {//index为默认的
String actionKey = controllerKey; Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
action = mapping.put(actionKey, action); if (action != null) {
warnning(action.getActionKey(), action.getControllerClass(), action.getMethod());
}
}
else {
String actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName; if (mapping.containsKey(actionKey)) {
warnning(actionKey, controllerClass, method);
continue;
} Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, routes.getViewPath(controllerKey));
mapping.put(actionKey, action);
}
}
}
} // support url = controllerKey + urlParas with "/" of controllerKey
Action actoin = mapping.get("/");
if (actoin != null)
mapping.put("", actoin);
}
buildExcludedMethodName()首先将Controllerlei中的无参函数取出,放入set集合中
private Set<String> buildExcludedMethodName() {
Set<String> excludedMethodName = new HashSet<String>();
Method[] methods = Controller.class.getMethods();
for (Method m : methods) {
if (m.getParameterTypes().length == 0)
excludedMethodName.add(m.getName());
}
return excludedMethodName;
}

Interceptor[] defaultInters = interceptors.getInterceptorArray();获得全局拦截器,转换成数组后的GlobalInterceptor

然后for循环遍历routs

循环中

Interceptor[] controllerInters = interceptorBuilder.buildControllerInterceptors(controllerClass); 返回controller中的Before声明

    Interceptor[] buildControllerInterceptors(Class<? extends Controller> controllerClass) {
Before before = controllerClass.getAnnotation(Before.class);
return before != null ? createInterceptors(before) : NULL_INTERCEPTOR_ARRAY;
}

在循环routs中嵌套循环遍历每一个函数方法

这里就知道了为什么Controller中的无参函数才是一个action

if (!excludedMethodName.contains(methodName) && method.getParameterTypes().length == 0) {
//controller中的无参,并且不是基类Controller的方法
..............................
}

返回的每一个controller中无参的方法即为一个action

Interceptor[] methodInters = interceptorBuilder.buildMethodInterceptors(method);
Interceptor[] actionInters = interceptorBuilder.buildActionInterceptors(defaultInters, controllerInters, controllerClass, methodInters, method);

构建action的所有拦截器,interceptorBuilder.buildActionInterceptors(defaultInters, controllerInters, controllerClass, methodInters, method);中勿个参数就分别对应了全局拦截器,controller拦截器,controller类,action声明的before拦截器和方法体。

action的生成遵循几个规则:

    1、如果声明了actionkey注解,就根据actionkey中的声明。

    2、若方法名是index(),则action就于controllerkey。

    3、否则actionkey等于 controllerkey+“/”+methodName

Jfinal学习笔记的更多相关文章

  1. JFinal 学习笔记之Handler包分析

    HandlerFactory.java HandlerFactory是不可实例化的,因为 它的构造 函数 特意定位 私有 的:它有一个 静态的方法叫做 getHandler,它有两个参数 ,一个是Ha ...

  2. jfinal框架教程-学习笔记

    jfinal框架教程-学习笔记 JFinal  是基于 Java  语言的极速  WEB  + ORM  开发框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restfu ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  7. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  8. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  9. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

随机推荐

  1. ffmpeg内置aac编码器正式发布

    https://www.ffmpeg.org/#aac_encoder_stable February 15th, 2016, FFmpeg 3.0 "Einstein" FFmp ...

  2. Educational Codeforces Round 1(D. Igor In the Museum) (BFS+离线访问)

    题目链接:http://codeforces.com/problemset/problem/598/D 题意是 给你一张行为n宽为m的图 k个询问点 ,求每个寻问点所在的封闭的一个上下左右连接的块所能 ...

  3. CodeForces 706D Vasiliy's Multiset (字典树查询+贪心)

    题意:最开始的时候有一个集合,集合里面只有一个元素0,现在有q次操作,操作分为3种: + x: 表示向集合中添加一个元素x - x:表示删除集合中值为x的一个元素 ? x:表示查询集合中与x异或的最大 ...

  4. CSS实现子级窗口高度随低级窗口高度变化

    纯粹使用使用height:100%;或者height:auto;来定义内部容器自适应高度,都无法实现让内部容器高度随着外部父容器高度变化而变化,所以我们必需要使用position绝对定位属性来配合协助 ...

  5. TypeScript 素描 - 模块

    /* 其实前面一些都是废话,因为都和C#类似.从模块开始就需要深入的去理解了 文档反复声明了 内部模块现在称做 命令空间 外部模块称为 模块 模块在其自身的作用域里执行,而不是在全局作用域里,也就是说 ...

  6. 10款无需编程的App DIY开发工具

    10款无需编程的App DIY开发工具 你有一个很棒的创意但不会编程怎么办?外包.合伙开发还是从零学编程?这里提供另外一种方式--使用无需编程的App  DIY开发工具.DIY开发工具不仅节省了开发时 ...

  7. HTML5结构化标签

    一 结构化标签 在之前的HTML页面中,大家基本上都是用了Div+CSS的布局方式.而搜索引擎去抓取页面的内容的时候,它只能猜测你的某个Div内的内容是文章内容容器,或者是导航模块的容器,或者是作者介 ...

  8. vs2012下安装VisualHG

    好久没写东西了.懒了.最近开发用到HG,记录一下.希望对用这个的有用 http://visualhg.codeplex.com/ 这里下载 VisualHG 安装完默认情况下 源代码管理出不来Visu ...

  9. 教你50招提升ASP.NET性能(二十二):利用.NET 4.5异步结构

    (40)Take advantage of .NET 4.5 async constructs 招数40: 利用.NET 4.5异步结构 With the arrival of .NET 4.5, w ...

  10. hdu 2037 今年暑假不AC (java)

    问题: 此题为贪心算法入门,思路是先将各个时间段依照结束时间进行排序(按结束越早遍历.节目愈多), 再从第一个节目開始,假设下一节目開始时间大于上一节目的開始时间则进行该节目.依次递推. 输入时,要求 ...