rose分析

简介:
最简单的rose配置:
< project  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
    xmlns
="http://maven.apache.org/POM/4.0.0"
    xsi:schemaLocation
="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
     < modelVersion >4.0.0 </ modelVersion >
     < groupId >com.jiexi.demos </ groupId >
     < artifactId >rose-demos </ artifactId >
     < version >0.0.1-SNAPSHOT </ version >
     < packaging >war </ packaging >

     < dependencies >
         < dependency >
             < groupId >net.paoding </ groupId >
             < artifactId >paoding-rose </ artifactId >
             < version >1.0-SNAPSHOT </ version >
         </ dependency >
        
         < dependency >
             < groupId >log4j </ groupId >
             < artifactId >log4j </ artifactId >
             < version >1.2.15 </ version >
             < exclusions >
                 < exclusion >
                     < artifactId >mail </ artifactId >
                     < groupId >javax.mail </ groupId >
                 </ exclusion >
                 < exclusion >
                     < artifactId >jms </ artifactId >
                     < groupId >javax.jms </ groupId >
                 </ exclusion >
                 < exclusion >
                     < artifactId >jmxtools </ artifactId >
                     < groupId >com.sun.jdmk </ groupId >
                 </ exclusion >
                 < exclusion >
                     < artifactId >jmxri </ artifactId >
                     < groupId >com.sun.jmx </ groupId >
                 </ exclusion >
             </ exclusions >
         </ dependency >
     </ dependencies >
    

     < build >
         < finalName >jeasyweb-framework </ finalName >

         < plugins >
             < plugin >
                 < groupId >org.apache.maven.plugins </ groupId >
                 < artifactId >maven-compiler-plugin </ artifactId >
                 < configuration >
                     < source >1.6 </ source >
                     < target >1.6 </ target >
                     < encoding >UTF-8 </ encoding >
                 </ configuration >
             </ plugin >

             < plugin >
                 < groupId >org.mortbay.jetty </ groupId >
                 < artifactId >maven-jetty-plugin </ artifactId >
                 < version >6.1.26 </ version >
                 < configuration >
                     < contextPath >/ </ contextPath >
                     < scanIntervalSeconds >10 </ scanIntervalSeconds >
                     < stopKey >foo </ stopKey >
                     < stopPort >9998 </ stopPort >
                 </ configuration >
                 < executions >
                     < execution >
                         < id >start-jetty </ id >
                         < phase >pre-integration-test </ phase >
                         < goals >
                             < goal >run </ goal >
                         </ goals >
                         < configuration >
                             < scanIntervalSeconds >0 </ scanIntervalSeconds >
                             < daemon >true </ daemon >
                         </ configuration >
                     </ execution >  
                     < execution >
                         < id >stop-jetty </ id >
                         < phase >post-integration-test </ phase >
                         < goals >
                             < goal >stop </ goal >
                         </ goals >
                     </ execution >
                 </ executions >
             </ plugin >
         </ plugins >
     </ build >
</ project >


<? xml version="1.0" encoding="utf-8" ?>

< web-app  xmlns ="http://java.sun.com/xml/ns/j2ee"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"
    version
="2.4" >
     

     < context-param >
         < param-name >log4jConfigLocation </ param-name >
         < param-value >/WEB-INF/log4j.properties </ param-value >
     </ context-param >
 
     < listener >
         < listener-class >org.springframework.web.util.Log4jConfigListener </ listener-class >
     </ listener >
     

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


</ web-app >


package com.jiexi.demos.rose.controllers;

import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;

@Path("")
public  class IndexController {

    @Get("index")
     public String index() {
         return "index";
    }

}

rose启动到底做了那些工作:

   @Override
     protected  final  void initFilterBean()  throws ServletException {
         try {
            
             long startTime = System.currentTimeMillis();
            
             if (logger.isInfoEnabled()) {
                logger.info("[init] call 'init/rootContext'");
            }

             if (logger.isDebugEnabled()) {
                StringBuilder sb =  new StringBuilder();
                @SuppressWarnings("unchecked")
                Enumeration<String> iter = getFilterConfig().getInitParameterNames();
                 while (iter.hasMoreElements()) {
                    String name = (String) iter.nextElement();
                    sb.append(name).append("='").append(getFilterConfig().getInitParameter(name))
                            .append("'\n");
                }
                logger.debug("[init] parameters: " + sb);
            }

            WebApplicationContext rootContext = prepareRootApplicationContext();

             if (logger.isInfoEnabled()) {
                logger.info("[init] exits from 'init/rootContext'");
                logger.info("[init] call 'init/module'");
            }

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

             if (logger.isInfoEnabled()) {
                logger.info("[init] exits from 'init/module'");
                logger.info("[init] call 'init/mappingTree'");
            }

             //  创建匹配树以及各个结点的上的执行逻辑(Engine)
             this.mappingTree = prepareMappingTree(modules);

             if (logger.isInfoEnabled()) {
                logger.info("[init] exits from 'init/mappingTree'");
                logger.info("[init] exits from 'init'");
            }

             long endTime = System.currentTimeMillis();
            
             //  打印启动信息
            printRoseInfos(endTime -  startTime);

             //
        }  catch ( final Throwable e) {
            StringBuilder sb =  new StringBuilder(1024);
            sb.append("[Rose-").append(RoseVersion.getVersion());
            sb.append("@Spring-").append(SpringVersion.getVersion()).append("]:");
            sb.append(e.getMessage());
            logger.error(sb.toString(), e);
             throw  new NestedServletException(sb.toString(), e);
        }
    }

2大核心功能:

功能1:
    /**
     * 创建最根级别的 ApplicationContext 对象,比如WEB-INF、WEB-INF/classes、
     * jar中的spring配置文件所组成代表的、整合为一个 ApplicationContext 对象
     * 
     * 
@return
     * 
@throws  IOException
     
*/
     private WebApplicationContext prepareRootApplicationContext()  throws IOException {

         if (logger.isInfoEnabled()) {
            logger.info("[init/rootContext] starting  ");
        }

        ApplicationContext oldRootContext = (ApplicationContext) getServletContext().getAttribute(
                ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

         //  如果web.xml配置使用了spring装载root应用context  不可以
        
//  roseFilter可能因为启动失败,在请求的时候容器还会尝试重新启动,此时rootContext可能已经存在,不要简单地抛出异常
        
//  同时这样留出了使用Listener作为init rose context的扩展机会
         if (oldRootContext !=  null) {
             if (oldRootContext.getClass() != RoseWebAppContext. class) {
                 throw  new IllegalStateException(
                        "Cannot initialize context because there is already a root application context present - "
                                + "check whether you have multiple ContextLoader* definitions in your web.xml!");
            }
             if (logger.isInfoEnabled()) {
                logger.info("[init/rootContext] the root context exists:" + oldRootContext);
            }
             return (RoseWebAppContext) oldRootContext;
        }

        RoseWebAppContext rootContext =  new RoseWebAppContext(getServletContext(), load,  false);

        String contextConfigLocation =  this.contextConfigLocation;
         //  确认所使用的applicationContext配置
         if (StringUtils.isBlank(contextConfigLocation)) {
            String webxmlContextConfigLocation = getServletContext().getInitParameter(
                    "contextConfigLocation");
             if (StringUtils.isBlank(webxmlContextConfigLocation)) {
                contextConfigLocation = RoseWebAppContext.DEFAULT_CONFIG_LOCATION;
            }  else {
                contextConfigLocation = webxmlContextConfigLocation;
            }
        }
        rootContext.setConfigLocation(contextConfigLocation);
        rootContext.setId("rose.root");
        rootContext.refresh();

         if (logger.isInfoEnabled()) {
            logger.info("[init/rootContext] exits");
        }

         /*  enable: WebApplicationContextUtils.getWebApplicationContext()  */
        getServletContext().setAttribute(ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootContext);

         if (logger.isInfoEnabled()) {
            logger.info("[init/rootContext] Published rose.root WebApplicationContext ["
                    + rootContext + "] as ServletContext attribute with name ["
                    + ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
        }

         return rootContext;
    }


首先通过new直接创建WebApplicationContext,然后将其作为参数继续构建modules。可以看到参数contextConfigLocation的处理:
String webxmlContextConfigLocation = getServletContext().getInitParameter(
                    "contextConfigLocation");
             if (StringUtils.isBlank(webxmlContextConfigLocation)) {
                contextConfigLocation = RoseWebAppContext.DEFAULT_CONFIG_LOCATION;
            }  else {
                contextConfigLocation = webxmlContextConfigLocation;
            }
这里可以再web.xml里面定义参数,或者使用系统默认的参数:"/WEB-INF/applicationContext*.xml"
而对于main/resources/applicationContext *.xml 或者jar包里面的applicationContext*.xml文件的读取,是通过复写XmlWebApplicationContext的方法实现的:
    @Override
     protected  void loadBeanDefinitions(XmlBeanDefinitionReader reader)  throws BeansException,
            IOException {
        Resource[] configResources = getConfigResourcesThrows();
         if (configResources !=  null) {
            reader.loadBeanDefinitions(configResources);
        }
        String[] configLocations = getConfigLocations();
         if (configLocations !=  null) {
             for ( int i = 0; i < configLocations.length; i++) {
                reader.loadBeanDefinitions(configLocations[i]);
            }
        }
    }
功能2:
     private List<Module> prepareModules(WebApplicationContext rootContext)  throws Exception {
         //  自动扫描识别web层资源,纳入Rose管理
         if (logger.isInfoEnabled()) {
            logger.info("[init/mudule] starting  ");
        }

        ModuleResourceProvider provider = moduleResourceProviderClass.newInstance();

         if (logger.isInfoEnabled()) {
            logger.info("[init/module] using provider: " + provider);
            logger.info("[init/module] call 'moduleResource': to find all module resources.");
            logger.info("[init/module] load " + load);
        }
        List<ModuleResource> moduleResources = provider.findModuleResources(load);

         if (logger.isInfoEnabled()) {
            logger.info("[init/mudule] exits 'moduleResource'");
        }

        ModulesBuilder modulesBuilder = modulesBuilderClass.newInstance();

         if (logger.isInfoEnabled()) {
            logger.info("[init/module] using modulesBuilder: " + modulesBuilder);
            logger.info("[init/module] call 'moduleBuild': to build modules.");
        }

        List<Module> modules = modulesBuilder.build(moduleResources, rootContext);

         if (logger.isInfoEnabled()) {
            logger.info("[init/module] exits from 'moduleBuild'");
            logger.info("[init/mudule] found " + modules.size() + " modules.");
        }

         return modules;
    }

rose在init时会读取controllers里面的以Controller结尾的类,通过prepareModules功能实现的。
这块功能较复杂,涉及到*Controller,*Interceptor,*ErrorHandler,rose.properties,messages等的读取配置。

这块功能具体实现了rose的约定大约配置的思想,默认读取package的配置对应到不同的module中。

本文转自博客园沉睡森林@漂在北京的博客,原文链接:rose分析,如需转载请自行联系原博主。

目录
相关文章
|
12月前
|
定位技术
MIKE 21 教程 1.7 网格生成过程中的常见报错与问题
MIKE 21 教程 1.7 网格生成过程中的常见报错与问题
|
12月前
|
设计模式 数据可视化 测试技术
UML总结 面向对象技术 、Rational Rose 界面
UML总结 面向对象技术 、Rational Rose 界面
|
12月前
|
uml
UML 总结 类图的构成: Rational Rose:描述软件
UML 总结 类图的构成: Rational Rose:描述软件
|
测试技术
Rational Rose UseCaseView LogicalView ComponentView DeploymentView 四种视图含义
Rational Rose UseCaseView LogicalView ComponentView DeploymentView 四种视图含义
76 0
【安装教程】【Rational Rose2003】(未成功)
【安装教程】【Rational Rose2003】(未成功)
256 0
【安装教程】【Rational Rose2003】(未成功)