`

Rose初始化

 
阅读更多
Rose初始化

rose封装了spring框架,集合spring IOC和AOP所构建的一个MVC框架

rose载体为RoseFilter
在web.xml配置文件,如filter进行配置即可,如下:
< filter>
             < filter-name> roseFilter </filter-name >
             < filter-class> net.paoding.rose.RoseFilter </filter-class >
       </ filter>

       < filter-mapping>
             < filter-name> roseFilter </filter-name >
             < url-pattern> /*</ url-pattern >
             < dispatcher> REQUEST </dispatcher >
             < dispatcher> FORWARD </dispatcher >
             < dispatcher> INCLUDE </dispatcher >
       </ filter-mapping>

RoseFilter 
初始化函数:initFilterBean

初始化 rose的 context 容器
WebApplicationContext rootContext = prepareRootApplicationContext();
rose通过继承XmlWebApplicationContext,构建自己的context RoseWebAppContext 作为最根级别的 ApplicationContext 对象
RoseWebAppContext rootContext = new RoseWebAppContext(getServletContext(), load , false);
        rootContext.setConfigLocation(contextConfigLocation);
        rootContext.setId( "rose.root");
        rootContext.refresh();

上述的 refresh 方法和spring的 context 的初始化过程一样,即IOC对象的初始化
调用refresh 方法后,就会把配置文件中的 bean 载入到内存,成为 BeanDefinition

rose下 会有如下配置文件的约定 /WEB-INF/applicationContext*.xml
所有形如该形式的.xml文件将会被rose所识别,并载入到IOC容器中


// 识别 Rose 程序模块
            this.modules = prepareModules(rootContext);

rose 以 controllers 作为一个模块,controllers 下的package也会作为一个模块
模块对象 ModuleResource 封装了 controllers 相关的资源
包括模块路径,匹配的xml资源等 
初始化过程通过 provider.findModuleResources( load) 进行资源的加载,构建 List<ModuleResource>

初始化过程会把模块里的 beandefinition 类加载到内存,并保存在ModuleResource 
module.addModuleClass(Class. forName(className));

完成模块资源扫描后,就开始为每个具体的模块进行具体的资源搭配构建了
List<Module> modules = modulesBuilder. build(moduleResources, rootContext)
构建一个模块list,包括了rose的各个模块,即对rose的各个模块的初始化

单独的模块 Module 会构建自己的 context 对象
ServletContext servletContext = parent.getServletContext();
        Assert. notNull(servletContext);
        ModuleAppContext wac = new ModuleAppContext();
        wac.setParent(parent);
        wac.setServletContext(servletContext);
        wac.setContextResources( toResources(contextResources));
        wac.setId(uniqueId);
        wac.setNamespace(namespace);
        wac.setMessageBaseNames(messageBasenames);
        wac.refresh();

又看到 refresh 方法了,即初始化 Module 的context IOC容器
然后会把模块相关的bean 注册到模块的 IOC容器里
registerBeanDefinitions (moduleContext, moduleResource.getModuleClasses());


然后 rose 会把模块相关的 resolver interceptor等资源进行加载
// 从Spring应用环境中找出本web模块要使用的ParamValidator,ParamResolver, ControllerInterceptor, ControllerErrorHandler
            List<ParamResolver> customerResolvers = findContextResolvers(moduleContext);
            List<InterceptorDelegate> interceptors = findContextInterceptors(moduleContext);
            List<ParamValidator> validators = findContextValidators(moduleContext);
            ControllerErrorHandler errorHandler = getContextErrorHandler(moduleContext);
找出关联的资源,然后会加载到module 中
module.addCustomerResolver(resolver);
module.addControllerInterceptor(interceptor);
module.addValidator(validator);
module.setErrorHandler(errorHandler);

对于interceptor 的加载如下
 for ( int i = 0; i < interceptors .size(); i++) {
            // 先判断是否有"名字"一样的拦截器
            InterceptorDelegate temp = interceptors.get(i);
            if (temp.getName().equals(interceptor.getName())) {
                // rose内部要求interceptor要有一个唯一的标识
                // 请这两个类的提供者商量改类名,不能同时取一样的类名
                // 如果是通过@Component等设置名字的,则不要设置一样
                ControllerInterceptor duplicated1 = InterceptorDelegate
                        . getMostInnerInterceptor(temp);
                ControllerInterceptor duplicated2 = InterceptorDelegate
                        . getMostInnerInterceptor(interceptor);

                throw new IllegalArgumentException(
                        "duplicated interceptor name for these two interceptors: '"
                                + duplicated1.getClass() + "' and '" + duplicated2.getClass() + "'" );
            }
            // 加入到这个位置?
            if (!added && interceptor.getPriority() > temp.getPriority()) {
                this.interceptors .add(i, interceptor);
                added = true;
            }
        }

拦截器的优先级即通过 if (!added && interceptor.getPriority() > temp.getPriority()) 这个语句进行判断
然后把拦截器加载到适当的位置


加载完相关的资源后,rose才对controller进行初始化,对模块里的各个 controller 进行初始化
for (String beanName : beanFactory.getBeanDefinitionNames()) {
                checkController(moduleContext, beanName, module);
            }

在初始化过程中,可以看到以下的语句:
Path reqMappingAnnotation = clazz.getAnnotation(Path.class);
        if (reqMappingAnnotation != null) {
            controllerPaths = reqMappingAnnotation.value();
        }
我们在 controller 上标注的@Path 注解,在这里得到了解析,作为controller 的新路径

另外可以看到如下语句,rose 约定,controller 的命名规范
// TODO: 这个代码是为了使从0.9到1.0比较顺畅而做的判断,201007之后可以考虑删除掉
            if (controllerName.equals("index" ) || controllerName.equals("home" )
                    || controllerName.equals( "welcome")) {
                // 这个异常的意思是让大家在IndexController/HomeController/WelcomeController上明确标注@Path("")
                throw new IllegalArgumentException("please add @Path(\"\") to " + clazz.getName());
            } else {
                controllerPaths = new String[] { "/" + controllerName };
            }


然后 rose 从context 里得到 controller 实例,没有对 controller 进行属性的标注,就是单例了
Object controller = context.getBean(beanName);
        module. addController(//
                controllerPaths, clazz, controllerName, controller);
添加 controller 实例到module 里
这样一个 module 就填充完成了


完成了资源的加载后就到了 另一个关键的步骤了,即rose的匹配树的构建过程
// 创建匹配树以及各个结点的上的执行逻辑(Engine)
            this.mappingTree = prepareMappingTree(modules);

rose构建一个根节点,然后从根节点进行枝叶的添加
Mapping rootMapping = new ConstantMapping( "");
        MappingNode mappingTree = new MappingNode(rootMapping);
        LinkedEngine rootEngine = new LinkedEngine(null, new RootEngine(instructionExecutor ),
                mappingTree);
        mappingTree.getMiddleEngines().addEngine(ReqMethod. ALL, rootEngine);

        TreeBuilder treeBuilder = new TreeBuilder();
        treeBuilder.create(mappingTree, modules);

构建过程由 create 方法开始
整个构建过程为先从 module 开始,一个一个路径添加到匹配树上
for (Module module : modules) {
            addModule(rootNode, module);
        }
然后把controllers 的路径添加到匹配树上
for (ControllerRef controller : controllers) {
            addController(module, parent, moduleEngine, controller);
        }
最后把 action 方法的路径添加到匹配树上
for (MethodRef action : actions) {
                addAction(module, controller, action, target, controllerEngine);
            }

在把 controllers 的action 方法添加到匹配树上前,rose会对 controllers 进行初始化操作

如下,标注了 @Get @Post的方法会得到处理,解析并获取标注的路径值
for (Annotation annotation : annotations) {
            if (annotation instanceof Delete) {
                restMethods.put(ReqMethod. DELETE, ((Delete ) annotation).value());
            } else if (annotation instanceof Get) {
                restMethods.put(ReqMethod. GET, ((Get ) annotation).value());
            } else if (annotation instanceof Head) {
                restMethods.put(ReqMethod. HEAD, ((Head ) annotation).value());
            } else if (annotation instanceof Options) {
                restMethods.put(ReqMethod. OPTIONS, ((Options ) annotation).value());
            } else if (annotation instanceof Post) {
                restMethods.put(ReqMethod. POST, ((Post ) annotation).value());
            } else if (annotation instanceof Put) {
                restMethods.put(ReqMethod. PUT, ((Put ) annotation).value());
            } else if (annotation instanceof Trace) {
                restMethods.put(ReqMethod. TRACE, ((Trace ) annotation).value());
            } else {}
        }
        for (String[] paths : restMethods.values()) {
            for (int i = 0; i < paths.length; i++) {
                String path = paths[i];
                if (path.length() > 0 && path.charAt(0) != '/') {
                    paths[i] = "/" + path;
                }
            }
        }

如下,rose 做了约定,凡是使用index/get等的方法名的必须添加注解
否则rose会抛出异常
// TODO: 这个代码是为了使从0.9到1.0比较顺畅而做的判断,201007之后可以考虑删除掉
                        if ("get" .equals(method.getName()) || "index".equals(method.getName())) {
                            // 这个异常的意思是让大家在get/index上明确标注@Get,请注意@Get的意思
                            throw new IllegalArgumentException("please add @Get to "
                                    + controllerClass.getName() + "#" + method.getName());
                        }
                        if ("post" .equals(method.getName()) || "delete".equals(method.getName())
                                || "put".equals(method.getName())) {
                            // 这个异常的意思是让大家在post/delete/put上明确标注@Get/@Delete/@Put,请注意@Get的意思
                            throw new IllegalArgumentException("please add @"
                                    + StringUtils.capitalize(method.getName()) + " to "
                                    + controllerClass.getName() + "#" + method.getName());
                        }

如果方法没有标注任何注解,则 rose会使用默认操作
方法会默认可以处理get、post请求,请求路径名为方法名
shotcutMappings.put(ReqMethod. GET, new String[] { "/" + method.getName() });
                        shotcutMappings
                                .put(ReqMethod. POST, new String[] { "/" + method.getName() });

另外,对于标注了 @AsSuperController 注解的 controller 类,其子类可以使用父类的action方法
其处理过程如下,rose 会解析注解,标注该注解则会 解析父类的action方法,并添加到匹配树中
clz = clz.getSuperclass();
            if (clz == null || clz.getAnnotation(AsSuperController .class) == null) {
                break;
            }

// 初始化完成后,就可以通过addAction 添加 controller的方法了
//  而addAction方法里有下面的逻辑
Engine actionEngine = new ActionEngine(module, controller.getControllerClass(),//
                controller.getControllerObject(), action.getMethod());

// 初始化actionEngine对象
public ActionEngine(Module module, Class<?> controllerClass, Object controller, Method method) {
        this .module = module;
        this .controllerClass = controllerClass;
        this .controller = controller;
        this .method = method;
        this .interceptors = compileInterceptors ();
        this .methodParameterResolver = compileParamResolvers();
        this .validators = compileValidators();
        this .acceptedCheckers = compileAcceptedCheckers();
    }

// 这里可以看到这该方法下的连接器的初始化
private InterceptorDelegate[] compileInterceptors () {
        List<InterceptorDelegate> interceptors = module .getInterceptors();
        List<InterceptorDelegate> registeredInterceptors = new ArrayList<InterceptorDelegate>(
                interceptors.size());
        for (InterceptorDelegate interceptor : interceptors) {
            // 获取@Intercepted注解 (@Intercepted注解配置于控制器或其方法中,决定一个拦截器是否应该拦截之。没有配置按“需要”处理)
            Intercepted intercepted = method .getAnnotation(Intercepted . class);
            if (intercepted == null) {
                // 对于标注@Inherited的annotation,class.getAnnotation可以保证:如果本类没有,自动会从父类判断是否具有
                intercepted = this .controllerClass .getAnnotation( Intercepted. class );
            }
            // 通过@Intercepted注解的allow和deny排除拦截器
            if (intercepted != null) {
                // 3.1 先排除deny禁止的
                if (ArrayUtils.contains(intercepted.deny(), "*" )
                        || ArrayUtils. contains(intercepted.deny(), interceptor.getName())) {
                    continue ;
                }
                // 3.2 确认最大的allow允许
                else if (!ArrayUtils.contains (intercepted.allow(), "*" )
                        && !ArrayUtils. contains(intercepted.allow(), interceptor.getName())) {
                    continue ;
                }
            }
            // 取得拦截器同意后,注册到这个控制器方法中
            if (interceptor.isForAction(controllerClass , method )) {
                registeredInterceptors.add(interceptor);
            }
        }
        //
        return registeredInterceptors
                .toArray( new InterceptorDelegate[registeredInterceptors.size()]);
    }

// 我们知道拦截器可以通过使用注解来标注是否拦截一个请求的处理的
// 具体是否需要拦截,这个判断就是通过 interceptor.isForAction 这个方法来实现的
public final boolean isForAction(Class<?> controllerClazz, Method actionMethod) {
        // 返回false,表示控制器或其方法没有标注本拦截器所要求的注解
        if (!checkRequiredAnnotations(controllerClazz, actionMethod)) {
            return false;
        }
        // 返回true,表示控制器或其方法标注了“拒绝”注解
        if (checkDenyAnnotations(controllerClazz, actionMethod)) {
            return false;
        }
        return isForAction(actionMethod, controllerClazz);
    }
分享到:
评论

相关推荐

    初始化和清理.ppt初始化和清理.ppt初始化和清理.ppt初始化和清理.ppt

    初始化和清理是编程中至关重要的概念,特别是在Java这样的高级编程语言中。本节主要讨论了Java中的构造器、成员初始化、对象创建过程、垃圾回收以及垃圾回收器的工作原理。 4.1 构造器 构造器是Java中用于初始化新...

    ipv6初始化和处理流程分析.pdf

    ### IPv6初始化和处理流程分析 #### IPv6与Linux网络子系统概述 Linux内核中的网络相关代码构成了一个独立的子系统,这个子系统是层次化的结构,包括以下层次: 1. **Socket层**:位于BSD socket APIs和具体的...

    rose框架使用Demo

    - **数据库准备**:`user.sql`文件可能是用于初始化数据库的脚本,包含了创建表和填充测试数据的语句。 - **运行Demo**:`rose1`可能是一个包含Rose框架应用的示例项目,你可以通过导入到IDE中,运行并观察其如何...

    Rose框架例子(rose-example)

    4. **db.sql**: 这是数据库脚本文件,通常用于初始化或更新数据库结构。在Rose框架例子中,它可能包含了创建表、插入初始数据等操作。 5. **.settings**: 存放项目的Eclipse设置,如编码格式、编译器选项等,对每个...

    flash cs5运行时出现“java运行时环境初始化时出现错误”.pdf

    ### flash CS5运行时出现“Java运行时环境初始化时出现错误”的解决方法 #### 问题背景 在使用Adobe Flash CS5的过程中,部分用户遇到了“Java运行时环境初始化时出现错误”的提示,导致软件无法正常启动。这一问题...

    RoseHA关于linux下mysql配置

    部署MySQL时,需要对安装路径、初始化参数等进行配置,以确保MySQL可以正常运行并加入到RoseHA的高可用配置中。 安装RoseHA涉及的步骤包括RoseHA软件的安装、服务的启动和配置、以及卸载操作。在安装后,通常需要...

    paoding-rose备份

    9. **命令行工具**:Paoding Rose提供了一系列的命令行工具,用于项目初始化、生成代码、部署应用等,提高了开发效率。 10. **社区支持**:虽然Paoding Rose可能不如现代的一些框架活跃,但它仍有一部分忠实用户和...

    Rosemirrorha

    这种方式适用于初始化阶段,能够确保数据的一致性和完整性。 - **差分镜像**:仅传输两台主机间数据的不同部分,避免传输相同数据,从而减少了网络资源的消耗,提高了数据镜像的效率。 **3. 按需复制,优化资源使用...

    rose 安装步骤详解

    9. **初次启动和设置**:首次启动ROSE,可能需要进行一些初始化设置,如语言选择、工作区配置等。根据屏幕提示进行操作即可。 10. **学习使用**:ROSE拥有丰富的功能,包括建模、代码生成、静态分析等。建议查阅...

    uml rationnal rose

    Rational Rose是IBM公司推出的一款基于UML的可视化建模工具,它不仅支持UML的所有图类型,还提供了一套完整的软件开发环境,使得开发者能够从需求分析到设计、编码、测试和维护的整个过程中都能利用到该工具。...

    RoseMirrorHA4.0 for RHEL4.0 MySQL5.1 配置文档

    3. 初始化RoseMirrorHA4.0集群,创建并启动守护进程。 **四、MySQL5.1配置** 1. 在主服务器上安装并配置MySQL5.1,包括初始化数据库、设置用户权限、创建必要的数据库和表。 2. 配置MySQL的主从复制,使数据在主...

    ROSEHA双机软件图解安装配置linux借鉴.pdf

    ROSE HA双机软件图解安装配置Linux借鉴 ...ROSE HA双机软件图解安装配置Linux借鉴,讲述了如何在Linux环境下安装和配置ROSE HA双机软件,包括安装ROSE HA、初始化ROSE HA、设置ROSE HA的初始化、配置双机HA等步骤。

    rational rose 7.0 验证码

    1. **Rational Rose**:是一款功能强大的可视化建模工具,主要用于系统设计、分析和文档编写等。 2. **面向对象的建模**:Rational Rose 支持 UML 语言进行面向对象的建模,可以帮助开发者更好地理解和组织复杂的...

    rose的简单deno

    1. `app.ts`:这是应用的主入口文件,包含了Rose框架的初始化代码,以及路由和中间件的设置。 2. `index.html`:可能是一个简单的HTML模板,用于展示Rose-Deno应用的首页。 3. `routes/` 目录:存放应用的路由文件,...

    Rose_HA_配置操作指导

    - **HA管理进程 (HAManager)**:初始化系统配置,协调主备服务器之间的关系。 - **服务程序 (Service)**:为用户提供服务,如数据库服务等。 - **HA代理 (Agent)**:监控服务状态并向HAManager汇报。 - **GUI管理...

    Rose ha10.0 for windows安装

    安装结束后,需要按照指南进行集群的配置和初始化设置。 2.2 Rose HA服务 安装完成后,需要设置Rose HA服务,包括服务的启动、停止、故障转移的配置等。 2.3 卸载Rose HA 在某些情况下,可能需要从系统中卸载Rose ...

    paoding rose 一个完整的MVC的demo

    从"helloRose.readMe.txt"和"helloRose"这两个文件名来看,"helloRose"可能是项目的根目录,包含初始化的项目结构和配置文件,而"helloRose.readMe.txt"可能是介绍如何运行和理解这个示例的说明文件。在这个demo中,...

    paoding rose Demo

    4. **数据库文件**:在Demo中包含的数据库文件,可能是SQL脚本或者数据备份,用于初始化和填充测试数据。开发者可以通过这些文件快速搭建测试环境,了解Paoding Rose如何与数据库进行交互。 5. **项目结构**:通常...

    Rational Rose出现MEM_BadPoiter错误解决办法

    2. **指针操作错误**:在编程过程中,如果指针未初始化或者在操作过程中被误修改,可能会指向无效的内存位置。 3. **并发问题**:在多线程环境中,如果多个线程同时访问并修改同一块内存,可能导致数据不一致,从而...

Global site tag (gtag.js) - Google Analytics