源码有毒:Jfinal源码解析(三)

源码有毒:Jfinal源码解析(一)

[源码有毒:Jfinal源码解析(二)

jfinalConfig.configInterceptor(interceptors);

    @Override
    public void configInterceptor(Interceptors me) {
        me.add(new GlobalActionInterceptor());
    }

添加全局拦截器,最终会把这里添加的拦截器存储到InterceptorManager类的singletonMap中

private void addGlobalInterceptor(boolean forAction, Interceptor... inters) {
    ...for (Interceptor inter : inters) {
        singletonMap.put(inter.getClass(), inter);
    }
    ...略    
}

jfinalConfig.configHandler(handlers);
这里比较简单,直接把handler存储到了Handlers类的集合中

final public class Handlers {

    private final List<Handler> handlerList = new ArrayList<Handler>();

    public Handlers add(Handler handler) {
        if (handler != null)
            handlerList.add(handler);
        return this;
    }

    public List<Handler> getHandlerList() {
        return handlerList;
    }
}

到这里,就把我们自己写MianConfig中有所有配置信息,初始化到Config中。
回到JFinal类的init()方法

boolean init(JFinalConfig jfinalConfig, ServletContext servletContext) {
        this.servletContext = servletContext;
        this.contextPath = servletContext.getContextPath();

        initPathUtil();

        Config.configJFinal(jfinalConfig);  // start plugin and init log factory in this method
        constants = Config.getConstants();

        initActionMapping();
        initHandler();
        initRender();
        initOreillyCos();
        initTokenManager();

        return true;
    }

继续看initActionMapping();

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

创建了ActionMapping类的对象,并把刚才初始化到Config中的路径信息和拦截器传递到了ActionMapping对象中,并调用了actionMapping.buildActionMapping();方法。

void buildActionMapping() {
 mapping.clear();
 Set<String> excludedMethodName =buildExcludedMethodName();
 InterceptorManager interMan = InterceptorManager.me(); 
 for (Entry<String, Class<? extends Controller>> entry : routes.getEntrySet()) {
    Class<? extends Controller> controllerClass = entry.getValue();
    Interceptor[] controllerInters = interMan.createControllerInterceptor(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[] actionInters = interMan.buildControllerActionInterceptor(controllerInters, controllerClass, 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));
    }
} 
    Action action = mapping.get("/");
    if (action != null)
        mapping.put("", action);
    }

方法一开始先是调用了buildExcludedMethodName()方法返回一个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;
    }

其实就是将Controller类中不带参数的方法名获取处理存储到Set集合中,便于区分用户自己在Controller中编写的Action方法。紧接着获取了InterceptorManager拦截器Manager的实例。然后对从Config中传递进来的Routes中的map集合进行了遍历,依次取出Controller的Class,然后通过调用InterceptorManager.createControllerInterceptor()方法,取出注解在Controller类的拦截器信息,并存储到InterceptorManager中

Interceptor[] controllerInters = interMan.createControllerInterceptor(controllerClass);


public Interceptor[] createControllerInterceptor(Class<? extends Controller> controllerClass) {
        return createInterceptor(controllerClass.getAnnotation(Before.class));
}

接着看

boolean sonOfController = (controllerClass.getSuperclass() == Controller.class);
            Method[] methods = (sonOfController ? controllerClass.getDeclaredMethods() : controllerClass.getMethods());

这里获取到了Controller中的所有Action方法,通过判断是否是Controller的子类,来解决我们自己编写的Controller的继承问题

// 遍历methods
for (Method method : methods) {
    String methodName = method.getName();
    // 去除Controller父类中的方法和权限不为public的方法
    if (excludedMethodName.contains(methodName) || method.getParameterTypes().length != 0)
    continue ;
    if (sonOfController && !Modifier.isPublic(method.getModifiers()))
    continue ;
    // 获取method的注解拦截器,并添加全局拦截器和类拦截器并返回
    Interceptor[] actionInters = interMan.buildControllerActionInterceptor(controllerInters, controllerClass, method);
    // 获取Controller的路径信息,判断是否配置有ActionKey,对Action的路径 “/” 进行处理,单独处理 index 方法
    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实例
// controllerKey: 请求Controller根路径  
// actionKey:请求method的路径 
// controllerClass:Controller的Class
// actionInters:拦截器                 
 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));
            }

看个具体的实例

public final class AppRoute extends Routes {

    @Override
    public void config() {
        //这里的"/user" 就是controllerKey
        this.add("/user", UserAction.class);
    }
}

public class UserAction extends Controller {

    // 这里的login 就是actionKey
    public void login(){

    }
}   

这里如果要访问UserAction的login方法,路径则为localhost:port/user/login

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));

在创建好Action之后,把Action存储到了一个map集合之中,如果集合中已经存在这个Action,则抛出异常

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值