JFinal源码分析------初始化那些事儿3之ActionMapping

今儿话题,ActionMapping,这个过程主要是创建起你URL访问使用具体是使用哪儿个Action去处理你的请求,这个过程主要也是也是发生在JFinalFilter初始化过程当中的,下面咱们就具体好好分析分析,ActionMapping他是如何作的,他的内部是如何实现的,上篇博文中咱们就说过,ActionMapping是我认为最巧妙的地方,如何巧妙,我尽可能用我本身对JFinal的理解去解释这么过过程!!先看代码:java

<!-- lang: java -->

private void initActionMapping() { actionMapping = new ActionMapping(Config.getRoutes(), Config.getInterceptors()); actionMapping.buildActionMapping(); }数组

咱们看到在initActionMapping中是这样定义的,他主要是作了一下的两件事情: 一、建立一个ActionMapping的实例,初始化他的routes,和interceptors,具体的做用是什么,一会详细说说 二、建立ActionMapping(也就是Action的映射)app

咱们打开ActionMapping发现有以下的类属性:框架

private static final String SLASH = "/";
private Routes routes;
private Interceptors interceptors;

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

当咱们的程序执行到这个ActionMapping文件时候,刚刚咱们看到的routes,interceptors属性在咱们的ActionMapping的构造函数中已经被初始化了,还有一个就是咱们的mapping类属性,你们能看到,这个是一个Map集合类型,你能猜到他是作什么的么??函数

也许你能猜到,其实这个就是咱们装载咱们Action映射的容器,由于Map这个东西经过Key来获得Value,(也就是咱们所说的键值对),有这个之后,咱们就直接能够经过咱们的Key去取得咱们先要的Action了,固然,理论是这么个理论,可是如何实现的话, 咱们就须要经过分析BuildActionMapping的方法去找寻咱们的答案了!!因为BuildActionMapping中的代码比较多,那么我只能选取一些我认为比较重要的代码进行解析,有遗漏的欢迎各位不全,不胜感激!!!ui

进入buildActionMapping方法,咱们能够看到有这样么一段代码: Set<String> excludedMethodName = buildExcludedMethodName(); 这个主要是作啥的?不知道的话 咱们就找到这个方法,而后看看 他作了啥?this

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

喏,看吧 他是想获取Controller中全部的类的方法,而后经过循环的方式,找出那些个么有不带参数的方法,而且减那些不带参数的方法添加至一个HashSet的集合类型当中。他为何要作这个操做,以及他的意图何在?先别急,接着往下看。继承

当咱们获取了上述的方法的执行结果以后,咱们看看后面的几句代码:路由

//建立一个interceptorBuilder实例,这个不用解释了吧,搞过JAVA的都会啊 InterceptorBuilder interceptorBuilder = new InterceptorBuilder();

//这个就是获取全部的Interceptor,而后所有转换成为数组而后保存 Interceptor[] defaultInters = interceptors.getInterceptorArray();

//使用interceptorBuilder创建defaultInters 映射 interceptorBuilder.addToInterceptorsMap(defaultInters);

这三个的操做主要是完成对JFinal框架中默认提供的Interceptor进行加载而且映射,步骤基本就是上面说的那些

顺便插一句题外话:

public Interceptors add(Interceptor globalInterceptor) { if (globalInterceptor != null) this.interceptorList.add(globalInterceptor); return this; }

还记不记得在咱们的自定义继承JFinalCofig那个中有一个 public void configInterceptor(Interceptors me) { .... }

这个方法,根据JFinal文档说要注册全局的Interceptor要在这里加,如今看到这个,你应该知道为何做者要特殊的声明说 "Global级拦截器要在JFinalConfig.configInterceptor(Interceptors me)中进行配置“(这是做者的原话,有错误不要找我)

好了,继续回到咱们的话题,继续看代码: 下面就会有一个循环迭代,代码以下: for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) { .... } 有没有看到熟悉的变量了?”routes“,这个咱们刚刚初始化过的,他如今有值了,如今我告诉你这个routes他从哪儿来??他就从下面的方法中来:

public void configRoute(Routes me) { ....(这里是你配置的路由,对吧??) }

他迭代的就是你这里面所配置的全部路由信息,而后一个一个的将其迭代出他的值,看到如下代码 Class<? extends Controller> controllerClass = entry.getValue();

你是否是感受反射又来了,恭喜你 都会抢答了,这个框架中就是大量的使用了Java的反射技术,之前都不知道这个是干啥用的,如今我终于彷佛好像有点明白了。看到这里,你可能会问,他为何或得的值是一个Controller类型的,答案就在这里: public void configRoute(Routes me) { me.add("/", CommonController.class);(在路由中你是这样写的,对吧??) } 因此,在迭代routes的时候,他不获取Controller,他拿什么??嘿嘿....

继续向下(额.....分析这个方法,好累,太多了)

//构建一个ControllerInter数组,用来装全部的Controller级别的ControllerInter

Interceptor[] controllerInters = interceptorBuilder.buildControllerInterceptors(controllerClass); 喏,Jfinal框架中的另一个级别的拦截器出来了(Controller级别),之后被人问起来讲,Controller级别的Interceptor何时被加载建立的,这就是答案啊!!

//获取某个Controller中的全部的Method,记住这个Controller是咱们本身定义,继承Controller类的那个Controller(额,好拗口) Method[] methods = controllerClass.getMethods();

刚刚咱们获得了某一个Controller中的全部方法,而后又开始一个循环,完成对这个获取这个Controller中的全部方法,而后进行迭代,具体代码能够看源码,这个里面的代码太长了,我仍是挑重要的说。

当咱们进入一下的循环之后,主要作了一下操做: 一、获取method[]中的每个方法名 二、检查这个方法名是否包含在咱们刚刚获取的excludedMethodName中,而且还要检查该方法是否有参数,加入不在excludedMethodName中,而且也没有任何参数,则进入第3步 三、分别构造一个Action级别的MethodInterceptor和构造一个ActionInterceptors,而且获取controllerkey 四、看看有没有使用ActionKey这个注解符,而且对Actionkey注解符中设定的值继续合理性的验证,验证无误之后,新建一个action实例,而后将该实例放入放入mapping这个类型集合中 五、当咱们的Action中没有放入Actionkey注解符,就先看看methodname是否是”index“,(咱们知道index这个是Controller中默认的一个方法),若是是,则建立一个Action实例,将这个action实例放入mapping这个集合变量中去。

六、假如咱们在Controller了中没有使用ActionKey,咱们的方法名称是index之外的方法,那么咱们就按照这样的方式来构造actionkey(固然建立action实例,是和上面相似的,由于他们使用的是一个action建立的方法)

actionkey的格式 String actionKey = controllerKey.equals(SLASH) ? SLASH + methodName : controllerKey + SLASH + methodName;

这个够清楚了吧,格式就是这样了。若是之后再出现action没法访问,那么,你就须要从这里来找缘由了

七、在最后,咱们从mapping中获取”/“对应的方法,等待着触发

完整至此,ActionMapping中的映射创建了。哎哟,妈呀 可把我累坏了!!关于ActionMapping的好处,或者是其余的一些特色,下次再开扒吧!!由于扒源码真的是个力气活!!

相关文章
相关标签/搜索