SlideShare una empresa de Scribd logo
1 de 82
Exodus2 大局观
 内容纲要:

 1 , Exodus2 的历史
 2 , WebX 大局观
 3 , Exodus2 的部署
 4 ,数据访问层
                   hongjiang
                   2009.5.16
1, Exodus2 的历史
Exodus2 代号名称的由来:
不知道大家注意过没有, exodus 和 ezra(BOPS 的代号 ) 都是
出自圣经,容易联想到这两个产品的设计者可能是基督教信仰
者或者深谙圣经。

校长:
Exodus 是《圣经》出埃及记那一章。摩西带领犹太人走出埃
及是一段非常艰辛的过程。早些年 ali 曾经比较崇拜国外的技
术,雇佣硅谷的一些工程师开发过一些东西,后来证明并不好
用,后由宝宝带领开发出一套新的框架。这个过程是有些类似
于出埃及的过程的。 exodus2 是 exodus 后来的重构版本。
Exodus2 的历史

即使一些工作 2 , 3 年以上的同事,谈及
Exodus2 的时候,也会说“水很深”。越
深入的了解,发现它的确有很多模糊或者
困惑的地方可能是历史遗留原因,我们需
要弄清楚,避免一些错误。

这个框架不仅 ali 在用,淘宝,支付宝也在
用,有些因素可能是其他公司有特殊的需
求,使得框架有所妥协而违背原先的设计
。
2. WebX 大局观

2.1 , Spring 框架
2.2 , Service 框架
2.3 , WebX 的表现层
2.4 , WebX 的业务层
2.5 ,表现层和业务层的交互 :
     CommandDispatcher— 忧愁河上的桥
2.1 Spring 框架

   核心: DI 和 AOP
Spring 框架布局
                     J2EE应用程序


                                           消除
基于                                         重复代
       Spring应用框架
POJO                                       码
简单开
发

           IoC容器                AOP框架


       事务       远程      DAO      JMS    JNDI

                    支持企业服务
Spring 容器:

Spring 容器有多种实现,分两类 :
 1: BeanFactory
 2: ApplicationContext
  ( 扩展了 BeanFactory, 提供了更多功能,
     绝大部分应用都使用
ApplicationContext)
依赖注入:
依赖注入是 Spring 运用反向控制
原则解决配置管理和对象关系管理
的手段。

 依赖注入的方式:
1: setter 方式
2: 构造器方式
3: 方法注入,抽象方法
对 AOP 的支持,
用代理类包裹切面
                                      代理
                  调用者
                                        目标




       Spring 基于代理实现对 AOP 的支持
    通过 J2SE dynamic proxies ,可以代理任意 Java 接口。
        通过 CGLIB 字节码生成,可以代理 Java 类。
  Spring 的代理机制可以支持由 Spring 容器创建的
  bean ,无法支持应用中自行 new 出来的 bean 。
           Spring 只支持方法连接点。
Bean 如何和 Spring 容器交
        互


3 个 Ware 接口:《骇客帝国》中的红药丸

BeanNameAware : 了解 Bean 的名称
BeanFactoryAware: 了解容器
ApplicationContextAware: 了解容器
2.2 Service FrameWork

    和 Spring 有些相似的一套框架,
 用来管理 Service 对象,负责其生命周期,根
 据配置来装载 Service ,可以确保 Service 之间
           的耦合是松散的
Service 是什么?

没什么特别的,就是一些对象 ( 实
现了 Service 接口而已 ) ,不过这
些对象在 WebX 中都是一些比较通
    用的服务或者工具。
Webx 正常运行所必须的 Service


FormService             读取并验证用户 submit 的 form 表单的 service 。
JSPService              JSP 模板引擎,用来渲染 jsp 写成的页面模板。需要 TemplateService 的支持。
MappingService          将一个名字映射到另一个名字的 service 。
ModuleLoaderService     装载 turbine module 的 service ,例如: screen 、 action 、 control 等。
PipelineService         用来创建 pipeline 的 service 。
PoolService             缓存以减少对象创建的开销。
PullService             Pull model service ,自动创建一定作用域的对象,而不需要应用程序干预
                        ( push )。
ResourceLoaderService   用来装载资源的 Resource loader service 。
RunDataService          Webx 核心 service 之一,用来保存每一个 HTTP 请求的状态。需要 PoolService
                        和 UploadService 的支持。
TemplateService         用来管理 template engine ,渲染页面的 service 。
ThreadContextService    线程空间的 singleton 服务,方便 service 存取 request scope 的对象。
URIBrokerService        自动生成 URI 的 service 。
UploadService           用来上传图片和文件的 service 。
VelocityService         Velocity 模板引擎,用来渲染 velocity 写成的页面模板。需要 TemplateService 的
                        支持。
Service 概念 ( 摘自《 Exodus2 代码分析初步》 )

一个服务 (Service) 可以有多个服务实例

一个实例 (Instance) 可以包含多个服务,并有一个实例上下文
(InstanceContext)

同一个实例的所有服务共享该实例上下文

在 Webx 中:
  每个 WebxComponent 都是一个实例
  每个 WebxComponent 都由一个 webx.xml 配置其中的服务
  每个 WebxComponent 都继承缺省实例的配置,缺省实例由 webx-default.xml 和
  webx-turbine-default.xml 的来合并定义
类图结构
Service 容器结构
假设我们有 2 个 car 。
我们为全局配置了 A,B 两个服
务;为 car1 配置了 C 服务
;为 car2 配置了 D 服务。
ServiceManager 初始化后
   容器中会是怎样?
A           B



Car1        Car2

 C           D




       是这样么 ?
ServiceInstanceContext



    ServiceConfig




  ServiceInstance        Service




注意: ServiceInstance 是对
   Service 的包装
ServiceInstancA   ServiceInstanceB   ServiceInstanceC   ServiceInstanceD




         ServiceInstancA                  ServiceInstancA

        ServiceInstanceB                  ServiceInstanceB

        ServiceInstanceC                  ServiceInstanceC

        ServiceInstanceD                  ServiceInstanceD




它有一个将未申明 Service 补全的过程。是这样
                                ?
ServiceInstance 是对 Service 的包装。那么从
ServiceInstance 中如何获取 Service 对象?不同的
ServiceInstance 会共享 Service 么?看一下代码中的注释:

// 1. 如果是 main-instance ,并且指定了 classname ,则实例化 main-instance 。
 // 2. 如果是 main-instance ,并且未指定 classname ,则返回 null 。

  // 3. 如果是 sub-instance ,并且指定了 classname ,那么:
       // 3.1 如果是 MultiInstance ,如果和 main-instance 的类相同,则同 4.3 。
       // 否则报错。(这样做是为了兼容性好,特别是当一个原来不是
MultiInstance 的类转换成 MIS 时)
       // 3.2 如果 main-instance 不存在,则实例化 service instance 。
       // 3.3 如果 main-instance 存在,但不是 MultiInstance ,则实例化 service
instance 。
       // 3.4 如果 main-instance 存在,而且是 MultiInstance ,则报错。

  // 4. 如果是 sub-instance ,并且未指定 classname ,那么:
       // 4.1 如果 main-instance 不存在,则返回 null
    // 4.2 如果 main-instance 存在,但不是 MultiInstance ,则用 main-instance 的
类实例化 service instance 。
       // 4.3 如果 main-instance 存在,而且是 MultiInstance ,则调用 main-
instance 的 getInstance 方法。
假设我们的 A 服务实现了 MultiInstance 接口, B 服务

                            没有。


 InstanceA              InstanceB       InstanceC          InstanceD
             A                      B               null            null




                  A                           A



                  B                           B



                  C                          null


                 null                         D
说明:可以参考 DefaultServiceManager 的 initMapping 函数,最后
一段逻辑。
Exdodus2 中一共配置了 12 个 car , 22 个 Service 。经过
initMapping 后, services 这个 Map 中一共有 286 个 entry

而实现 MultiInstance 接口的只有:
BootstrapResourceLoaderService,
DefaultIPSeekerService, DefaultRunDataService,
DefaultViewCacheService, 这 4 个 Service ,也就是说大部分
Service 每个 car 都会再创建自己的实例。这样在全局定义那么多
Service 干嘛?比如全局的 PullService , TemplateService 有什么作
用?



 另外 : 在 webx-turbine-default.xml 中对 sub-instance
 定义了 FreeMarkerService ,会用到么?
配置级联的 Spring 容器
我们说过,每个 car 里的 service 都是一份独立的
实例。同样,作为一个普通的 Service ,每个 car
中都会创建一份自己的 Spring 容器。假如我有
10 个 car ,就有 10 个各不相干的 Spring 容器。
但是,有一些 Beans 是不能够这样做的,否则会占用不必要的
系统资源。例如,和 cache 有关的 beans 。怎么解决这个问题
呢?有办法!我们可以把 Spring 容器级联起来,使父容器被所
有的 car 共享。改进方案如图:
要配置这种级联的 Spring 容器非常简单:
                     WAR
                 └─ WEB-INF
          │webx.xml - 在此配置共享的父容器
                        │
                     ├─ car1
         │webx.xml - 在此配置派生的子容器
                     └─ car2
           webx.xml - 在此配置派生的子容器
配置文件的写法完全同前例。这样,当查找一个 bean 时
, Spring 会首先在子容器中查找,如果找不到,再到父
容器里查找。你可以自由地决定,哪些 beans 需要被共享
         ,哪些 beans 需要被某个 car 独享。
看看 Service 接口定义的 getParentService 方法:

对于 sub-instance ,取得其 main-instance ,否则返回 null 。

注意:和 ServiceContext.getService 方法不同,即使 parent instance
初始化失败, getParentService 也不会抛出异常,而是将 parent
instance 初始化失败的信息记录在 log 中。

ServiceContext( 全局 Service 容器 ) 中:
getService(svcName)
getService(svcName, instanceName)
注释中说:如果 service 不存在,或初始化失败抛出
ServiceInstantiationException
但实际代码并未声明 throws ServiceInstantiationException
to fix: 代码中的注释应该也修改一下。
Service 框架和 Spring 框架的异同


 1: Spring 是个更通用的容器,容器装载的 Bean
 可    以是任何类型对象。而 Service 容器中装载
 的是 Service 对象。

 2: Spring 容器中的对象可以不必知道容器,而
 Service 容器中 service 对象是紧密和容器耦合的
 。
Service 框架究竟有没有实现“依
          赖注入”
 《 Service 框架指南》中说 Service 框架不支持“注入”,而 Module 中却
 用到了注入。

 宝宝的答复:

  Service 框架不支持注入。但是应工程师要求,在
 screen/action/control 等部
 件中加入了注入功能,是用 cglib 直接实现的,和 service 框
 架无关。

 另外,我目前在做的工作是,将 webx 移植到纯 spring 框架
 中,抛弃 service 框架,
 因此注入从此不是问题了。
2.3 WebX 表现层

1, RunData :对 Req,Resp,Session 的封
装
2, Module :页面编程模块
3, Pipeline: 逻辑流程
4, 分析一个页面请求的流程
RunData: 简化对 http 请求操作


RunData 实现了 RequestContext 接
           口。

RequestContext 体系是一个用装饰
  模式实现对功能的层层扩展。
RequestContext 的构建 : 封装了哪些功能?
看看配置文件,对 RunDataService 的装配:
构建一个 ChinaRunData, 它通过一个个的工厂类来进行装配
(Decorate) ,负责调用这些工厂的是 RequestContextChainService
这些工厂的设置顺序:

               BufferedRequestContextFactory
                             ↓
             LazyCommitRequestContextFactory
                             ↓
                ParserRequestContextFactory
                             ↓
               SessionRequestContextFactory
                             ↓
              SetLocaleRequestContextFactory
                             ↓
               RewriteRequestContextFactory
ChinaRunData: 注意包装的顺序

RewriteRequestContext

      SetLocaleRequestContext

             SessionRequestContext
                 ParserRequestContext

                        LazyCommitRequestContext

                          BufferedRequestContext

                                RequestContextImpl
HttpSession 中的问题:
通过 BufferedRequestContext
LazyCommitRequestContext
防止了 HttpResponse 的“自动输出”,使
得我们可以一直控制 http 头,有机会改写
cookie 信息,实现 session 的存储。

BufferedRequestContext 是缓冲了整个
http 的 head 和 content 还是只缓冲了
head ?

如果遇到一个很大的页面会如何?
WebX 中的 Module


   Webx 中的页面逻辑编程模块。
 Screen, Action,Control,Layout 都实现
了 Module 接口。所有的 Module 都是通
  过 ModuleLoaderService 装载的。
ModuleLoaderService 的装载
       和依赖注入
装载 Module:
     将创建各种 module 的任务转交给
ModuleFactory 去做。它可以为每一种 module
( screen/control/action )指定一个或多个
ModuleFactory 来创建。

Module 中的依赖注入 :
  1: setter 方式。
  2 : abstract getter 方式。

注入究竟是怎么实现的?
如果不加特别的配置,那么 DefaultModuleFactory 已经可以支持将 Service
  注入到 module 中。例如在 module 中定义下面的 abstract getter :
                                
   protected abstract URIBrokerService getURIBrokerService();

这句话告诉 DefaultModuleFactory :将 URIBrokerService 注入到 module 中
                           去。



  对于抽象类,通过 CGLIB 动态生成子类
                             。 在获取 Module 实例时,调用
  DefaultModuleFactory 的 getModule
            instantiateModule(String moduleClassName)
  判断 Module 是否 abstract class, 如果是则用 CGLIB 来创建 Module 子
           类。 ( 非 abstract 则用反射方式 newInstance)
   随后 instantiateModule 函数中,如果 module 实例不为 null 则调用
   injectDependences 函数,加载所创建的 module 实例依赖的对象。
     injectDependences 调用 propertySetter.invoke 来注入依赖对象
如果 注入的不是 Service, 而是一个 Bean, 则需要利用
              ReferenceResolver 接口
我们实现了 SpringReferenceResolver ,用来从 Spring 容器中取得对
                         象。




  也就是说 Module 中注入 Service 对象, Webx 框架直
  接实现,因为框架本身是一个 Service 容器,很容易获
              取到 Service 对象。
  而 Module 中注入 Bean 对象,则需要借助 Spring 容器
  来获取,非 Service 对象都是通过 Spring 容器托管的。

   比如 CommandDispather 这样的非 Service 对象还有
    Biz 层的 AO,BO 等都是用 Spring 容器来托管的。
模板的渲染:
             TemplateEngineService            TemplateService




JspService

       VelocityService    FreeMarkerService



      TemplateServer 通过注册一个 Engine 来实现渲染 。
          渲染的顺序是: Screen->Layout->Control

    渲染过程需要 TemplateContext , module 是从 rundata
     中获取 templateContext 的, rundata 中需要通过
                PullService 来获取。
Action/Screen 执行顺序
WebX 中的 Pipeline



   Pipeline 是表现层逻辑流程的核心。
它是一种责任链模式, (X 它的代码实现上并不
                 是)
把处理从一个 Valve 流向下一个 Valve ,主要响
      应 action module 的 Valve 是
可以改变现有的 valve ,例如:改变分析 URL 的方法
          PerformActionValve 。
可以插入新的 valve ,例如: Session 处理、权限验证等
                。
根据返回值 ValveForward
             进行跳转




内部重定向的实现方式: RedirectTargetValve



     processModule
 (ChooseValve 根据条件            RedirectTargetValve
   选择 PerformValve)
TryCacheFinallyValue:
     try{
       tryPipeline:

     }catch(Exception e){
       cachePipeline:

     }finally{
        finallyPipeline:

     }
大峰的提问 :
PerformActionValve 的安全性隐患?
金立的补充:

在 pipeline.xml 配置中,第二个 valve:
<valve
class=“com.alibaba.exodus2.web.common.webx.valve.AuthContextValve” />
AuthContextValve 的验证机制只是对 URL 而没有对后续的 action 验证,
比如:请求 a.htm?action=x&event_submit_doXXX
AuthContext 只验证了 a.htm ,并没有验证后续的 action
而用户有可能篡改后续的 action ,比如:
a.htm?action=y&event_submit_doYYY

这样就执行到了 Y Action 里的逻辑。
分析一次页面请求经历的逻辑


假设我们执行 offer post 并转向成功页
面

1: 从 URL 的角度看
2: 从 Pipeline 的角度看
从 URL 的角度看:
           只关注 URL 的进和出


             根据规则              MappingService
Request     Url Rewrite        映射到物理路径




                                                业务执行模块


                          URIBrokerService
Response
                          构建要跳转的页面
详细的看这个过程 :


1: Webx 的初始化。
2: RunData 的构造。
3: Servlet 把逻辑交给 Pipeline
Service 容器是被 WebxControllerListener 所初始化
  的,该 Listener 在 Web 容器初始化时执行。创建好
  Service 容器后,将其保存在 ServletContext 中。

   Servlet 请求之前,先被 RundataFilter 拦截。它负责
   调用 RundataService 把 Req/Resp/Session 等封装成
   一个 RunData 对象,随后将其 setAttibute 为 req 的
   属性,方便以后通过 req 得到 RunData 。

                    RunData




                 经过多重包装的      经过多重包装的     Request
ServletContext                  Request   Attribute
                  Response
从 pipeline 的流程来看
     :
                                                            CheckCSRF
                       Hessian                                 可选
Logging    Auth                       AnalyzeURL
                       Remote



             Screen                                         GreenChanel
                             Action                            Trace
            Template

             Screen          Action
                                                   Choose
Redirect                 TBStore
                        CheckCode

                        ExpiredUrl
关于 PullServie
    实现 Pull-MVC 的设计模式
 怎么理解 Pull-MVC, 和 push 的不同之处?

 What this entails is the ability to create an
   object that is able to “pull” the required
information out at execution time within the
                   template.
2.4 WebX 业务层 (BIZ
        层)


 1 :业务层的 Service 容器。是如何创建的?

 2 : AO,BO,DAO 都在 Spring 容器中。
    AO 每次请求时都是一个新的实例?
    BO 是一些通用逻辑模块,可供多个 AO 调用。
用 Singleton 启动 Service
          容器

 为了分离 WEB 层和业务层的对象,我们常常
 将 WEB 层的 Service 容器和业务层的 Service
 容器彻底分开。这样, WEB 层的 Spring 容器
 也随之和业务层的 Spring 容器彻底分开了。如
              图所示:
Web 层和 BIZ 层分离
 Web 层 Service 容器
                   Car1               Car2

                    Spring 容器          Spring 容器

                    Dispatcher         Dispatcher




Biz 层 Service 容器


                    Spring 容器
                                 AO    BO
用 Singleton 启动 Service 容
            器


 上图中的 CommandDispather 在初始化中,
 会调用 SingletonServiceManagerLoader 来
 启动一个独立于 WEB 层的业务层 Service 容
 器,再从中取得业务层的 Spring 容器。所有
 业务层的对象,都配置在这个 Spring 容器中。
 请记住,这是一个 Singleton ,意味着业务
  层的 Spring 容器只会被初始化一遍。
1.5 表现层和业务层的交互

      CommandDispather
 使用命令模式,封装了从表现层到业务层
  的调用,开发人员可以透明的对待它。
 它有多种实现方式, Exodus2 用的那种方
           式?
简单方式 ?
改进方式 ?
远程方式 ?




虽然由此设计,实际上我们所有的 web 和 biz 都是部署在同一个 JVM
              中的。
异步方式 ?
在确认之前还要弄清另外一个问题
 :《 Service 框架指南》中说在
web 层的 spring 容器中包含 biz
  层的 spring 容器的引用。
        如何做到?
宝宝《 Webx Modules 的装载以及依赖注入》
中说:
……
然而还有一个问题。在我们的常见应用中,
web 层和 biz 业务层是分离的, web 层的
spring 容器和 biz 层的 spring 容器也是分离
的。上面的配置只能拿到 web 层 spring 容
器中的内容,不能拿到 biz 层 spring 容器的
内容,怎么办呢?方法很简单:在 web 层的
spring 容器中包含 biz 层的 spring 容器的引
用。
既然是分层的 (web 层和 Biz 层分别存在各自的 Service 容器中 ) 。
Web 层 spring 容器 又如何得到 biz 层的 Spring 容器引用呢?
 我看你后边的配置, web 层是通过获取 Biz 层的 Service 容器引
用 再去获得 Biz 层 Spring 容器的,
<beans>
   <bean id=“bizBeanFactory”
class=“com.alibaba.service.spring.support.SingletonBeanFactorySe
rviceBean”>
      <property name=“serviceConfig”
value=“biz/services.xml”/><!-- 指向 biz 层 service 容器 -->
   </bean>
</beans>

那样的话,两个 Service 容器不就完全耦合了吗,
还要 CommandDispatcher 干嘛。
实际在我们的 webx-default 中对 sub-instance 也存在一个对 biz
层 Spring 容器的引用:

  <service name=“BeanFactoryService”
class=“com.alibaba.service.spring.DefaultBeanFactoryService”>
        <property name=“bean.descriptors”>
              <value>exodus2/bean/biz-delegate.xml</value>
              <value>exodus2/bean/web-tool.xml</value>
         </property>
 </service>

web-tool.xml 里面配置了 WebApplicationContextUtilsBean ,里面 setter 了
serviceConfig:alibaba-biz-service.xml 。该 utilBean 初始化时会通过调用
SingletonServiceManagerLoader.getInstance(
                  bootstrapResourceLoaderService, serviceConfig, initAll);
获取 biz 层的 Service 容器的单实例引用,进而获取 biz 层的 Spring 容器引用。

我们就可以通过该 UtilBean 来访问 biz 层的 spring 容器。
Exodus2 的中实际场景(不完整)

    Car1                           Car2


  Spring 容器                   Spring 容器
   UtilBean                       UtilBean




              CommandDispatcher



    Biz 层 spring 容器


              AO         BO
思考:
这样岂不是将 web 层的 Service 容器和 Biz 层的 Service
容器耦合在了一起?

Michael zhou:
Command Dispatcher 是可以访问到业务层的代码的,按理说,这应
该是唯一的访问
业务层 spring 容器的方法。

你看到我把 bizBeanFactory 注入到 web 层容器中,说实在这种做法
是不太完美的。
但这也是对实际需求的一种妥协。因为有一些公用对象(非业务层
和数据访问层对
象,如 AO 、 DAO 等),需要放在一个大家都能访问到的地方。但
当你要访问业务对
象( AO 、 DAO 等)时,仍然应该通过 command dispatcher 来走
。
Exodus2 中 CommandDispatcher 用哪种方式和 biz 层通讯?
看一下 biz-delegate.xml :
<bean id="sessionDispatcher"
class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
      <property name="jndiName">
        <value>ejb/CommandDispatcherSLSB</value>
      </property>
      <property name="businessInterface">
        <value>com.alibaba.biz.command.dispatcher.CommandDispatcher</value>
      </property>
   </bean>

  <bean id="messageDispatcher"
class="com.alibaba.biz.command.dispatcher.ejb.mdb.CommandDispatcherClient">
      <property name="connectionFactory">
        <bean class="org.springframework.jndi.JndiObjectFactoryBean">
           <property name="jndiName">
             <value>AlibabaWebxConnectionFactory</value>
           </property>
        </bean>
      </property>
      <property name="destination">
        <bean class="org.springframework.jndi.JndiObjectFactoryBean">
           <property name="jndiName">
             <value>queue/AlibabaWebxQueue</value>
           </property>
        </bean>
      </property>
   </bean>
commandDispatcherSelector 会根据 Command 的名称来判断使用
哪个 dispatcher 。
可供选择的 dispatcher :
1, sessionDispatcher 使用 ejb 方式。默认选择此方式。

2, messageDispatcher 使用消息队列的方式。

3, commandDispatcherLogic 直接通过已持有 biz 层 spring 容器的
引用来找到 biz 层的 AO 来执行。顺藤摸瓜。
Exodus2 中的 CommandDispatcher 默认的方式
    是 远程方式。用 Ejb 实现远程调用。
Biz 层的 CommandDispatcher:
除了 web 层和 biz 之间使用 CommandDispatcher, biz 层内部之间也使
用了 CommandDispatcher

比如发邮件的情况, web 层 dispatcher 到 biz 层的 SendMailBO ,它
又会通过 biz 层的 dispatcher 交给 JMS
biz 层这时用的 dispatcher 是异步消息队列的方式。


          Web-CommandDispatcher

 EJB 容器

  Biz-Serverice 容器
    Spring 容器

                BO    Biz-dipatcher   AlibabaWebxQueue   ???
Web-CommandDispatcher
       (sessionDispatcher)

EJB 容器

                EJB
 (…ejb.slsb.CommandDispatherBean)



                                        messageDispatcher
 Biz-Serverice 容器
   Spring 容器

         AO/BO/DAO    Biz-dipatcher   AlibabaWebxQueue      EJB
SLSB 和 MDB 类型的 EJB
     分别是什么?
         com.alibaba.biz.command.dispatcher.ejb.slsb.
                   CommandDispatherHome
                   CommmandDispatherRemote
                   CommandDispatherBean

         com.alibaba.biz.command.dispatcher.ejb.mdb.
                   CommandDispatherClient
                   CommandDispatherBean

为什么 sessionDispather 用到 slsb, messageDispather 用到 mdb
  (slsb 可用作远程或本地调用,而异步处理只能用 mdb)
为什么这么配置?性能问题
► sessionDispatcher 配置的是远程方式。
► 就一定会走远程方法调用么?还是也有可能走 local
  方式?

► 如果走远程方法调用,是通过 socket 来进行么?
    它的端口? 既然我们已经可以直接得到 biz 层对象
    的引用;为何这样? 怎么看待这里的效率问题?

► 如果是,这些是否都是历史遗留原因?还是?
阿甘:
1 :虽然配置方式是远程调用, JBoss 内部会
对其优化,判断是同一 JVM ,会相当于本地
调用来对待。

3 :可能是历史原因,早期是支付宝有需要将
web 层和 biz 耦合起来, B2B 也保持了这样
的结构。但开发人员使用时应该按照
CommandDispatcher 的方式调用,保持这种
风格便于维护。
Main-instance 和 sub-instance 中都配
    置了 ComamndDispather 。
 Main-instance 中的 Dispatcher 有何
               用意?
      阿甘的答复: Main-instance 中的
  CommandDispather 是为了某些全局 Service
     所用的,某些全局 Service 也会通过
         Dispather 去访问 Biz 层

   宝宝:也可能是后续维护的人员弄错了。应
         该一个就够了。
3, Exodus2 的部署

JBoss 没有使用集群,当服务器比较多
时,相互之间的监控需要耗费很大性能

Exodus2 也没有实现集群。
前段负载均衡 F5




                                Exodus2
Exodus2             Exodus2

   Apache              Apache      。。。

                                 共 64+7 台
    JBoss               JBoss




     Memcached 集群
                                 DataBase
数据库的部署:双机热备

Oracle9.2    心跳检测    Oracle9.2
  DB1                  DB2




                                 DB 并没有使用集群
                                 ,放在两台小型机
            共享存储设备
                                 上。 DB2 同时还做
                                     回滚备份
Exodus2 的数据层

1, 数据存储方式,数据源。
2, 基于 iBatis 的 DAO
数据访问层

                      DAL




Memcache                    Search
             Oracle                  ViewCache
                            Engine




           LDAP 已经不再使用
数据库与搜索引擎
                       前端负载均衡 F5




Apache                  Apache
                                                     。。。
  搜索引擎                   搜索引擎




                          Dispatcher



         Build Index                   Delta Index
          每天晚上                          每 5 分钟



                           Oracle
ViewCache 缓存数据




Oracle

                       SCP     XML 文件
         Sync Engine                      ViewCacheService
                             ( 已不用 JOS)

Search
Engine
                                              Exodus2




   搜索引擎的数据:提供统计信息,相当于类目的属性

Más contenido relacionado

La actualidad más candente

Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出wang hongjiang
 
Java cpu
Java cpuJava cpu
Java cpuykdsg
 
Java线上应用问题排查方法和工具(空望)
Java线上应用问题排查方法和工具(空望)Java线上应用问题排查方法和工具(空望)
Java线上应用问题排查方法和工具(空望)ykdsg
 
并发编程交流
并发编程交流并发编程交流
并发编程交流bluedavy lin
 
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析wang hongjiang
 
Btrace intro(撒迦)
Btrace intro(撒迦)Btrace intro(撒迦)
Btrace intro(撒迦)ykdsg
 
IOS入门分享
IOS入门分享IOS入门分享
IOS入门分享zenyuhao
 
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Kris Mok
 
Rpc原理与实现
Rpc原理与实现Rpc原理与实现
Rpc原理与实现wavefly
 
Effective linux.1.(commandline)
Effective linux.1.(commandline)Effective linux.1.(commandline)
Effective linux.1.(commandline)wang hongjiang
 
为啥别读HotSpot VM的源码(2012-03-03)
为啥别读HotSpot VM的源码(2012-03-03)为啥别读HotSpot VM的源码(2012-03-03)
为啥别读HotSpot VM的源码(2012-03-03)Kris Mok
 
Mysql展示功能与源码对应
Mysql展示功能与源码对应Mysql展示功能与源码对应
Mysql展示功能与源码对应zhaolinjnu
 
高性能的Java代码编写及常见问题排查
高性能的Java代码编写及常见问题排查高性能的Java代码编写及常见问题排查
高性能的Java代码编写及常见问题排查bluedavy lin
 
线程与并发
线程与并发线程与并发
线程与并发Tony Deng
 
Docker進階探討
Docker進階探討Docker進階探討
Docker進階探討國昭 張
 
UseNUMA做了什么?(2012-03-14)
UseNUMA做了什么?(2012-03-14)UseNUMA做了什么?(2012-03-14)
UseNUMA做了什么?(2012-03-14)Kris Mok
 
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringSpring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringJustin Lin
 
Sun jdk 1.6内存管理 -使用篇
Sun jdk 1.6内存管理 -使用篇Sun jdk 1.6内存管理 -使用篇
Sun jdk 1.6内存管理 -使用篇bluedavy lin
 
Jboss连接池原理及调优
Jboss连接池原理及调优Jboss连接池原理及调优
Jboss连接池原理及调优zhenhua fan
 

La actualidad más candente (20)

Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出
 
Java cpu
Java cpuJava cpu
Java cpu
 
Java线上应用问题排查方法和工具(空望)
Java线上应用问题排查方法和工具(空望)Java线上应用问题排查方法和工具(空望)
Java线上应用问题排查方法和工具(空望)
 
并发编程交流
并发编程交流并发编程交流
并发编程交流
 
Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析Hash map导致cpu100% 的分析
Hash map导致cpu100% 的分析
 
Btrace intro(撒迦)
Btrace intro(撒迦)Btrace intro(撒迦)
Btrace intro(撒迦)
 
IOS入门分享
IOS入门分享IOS入门分享
IOS入门分享
 
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)
 
Rpc原理与实现
Rpc原理与实现Rpc原理与实现
Rpc原理与实现
 
善用工具
善用工具善用工具
善用工具
 
Effective linux.1.(commandline)
Effective linux.1.(commandline)Effective linux.1.(commandline)
Effective linux.1.(commandline)
 
为啥别读HotSpot VM的源码(2012-03-03)
为啥别读HotSpot VM的源码(2012-03-03)为啥别读HotSpot VM的源码(2012-03-03)
为啥别读HotSpot VM的源码(2012-03-03)
 
Mysql展示功能与源码对应
Mysql展示功能与源码对应Mysql展示功能与源码对应
Mysql展示功能与源码对应
 
高性能的Java代码编写及常见问题排查
高性能的Java代码编写及常见问题排查高性能的Java代码编写及常见问题排查
高性能的Java代码编写及常见问题排查
 
线程与并发
线程与并发线程与并发
线程与并发
 
Docker進階探討
Docker進階探討Docker進階探討
Docker進階探討
 
UseNUMA做了什么?(2012-03-14)
UseNUMA做了什么?(2012-03-14)UseNUMA做了什么?(2012-03-14)
UseNUMA做了什么?(2012-03-14)
 
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringSpring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
 
Sun jdk 1.6内存管理 -使用篇
Sun jdk 1.6内存管理 -使用篇Sun jdk 1.6内存管理 -使用篇
Sun jdk 1.6内存管理 -使用篇
 
Jboss连接池原理及调优
Jboss连接池原理及调优Jboss连接池原理及调优
Jboss连接池原理及调优
 

Destacado

深入剖析Concurrent hashmap中的同步机制(下)
深入剖析Concurrent hashmap中的同步机制(下)深入剖析Concurrent hashmap中的同步机制(下)
深入剖析Concurrent hashmap中的同步机制(下)wang hongjiang
 
Effective linux.2.(tools)
Effective linux.2.(tools)Effective linux.2.(tools)
Effective linux.2.(tools)wang hongjiang
 
Real world akka recepies v3
Real world akka recepies v3Real world akka recepies v3
Real world akka recepies v3shinolajla
 
中等创业公司后端技术选型
中等创业公司后端技术选型中等创业公司后端技术选型
中等创业公司后端技术选型wang hongjiang
 
Automatic Scaling Iterative Computations
Automatic Scaling Iterative ComputationsAutomatic Scaling Iterative Computations
Automatic Scaling Iterative ComputationsGuozhang Wang
 
Behavioral Simulations in MapReduce
Behavioral Simulations in MapReduceBehavioral Simulations in MapReduce
Behavioral Simulations in MapReduceGuozhang Wang
 
Apache Kafka at LinkedIn
Apache Kafka at LinkedInApache Kafka at LinkedIn
Apache Kafka at LinkedInGuozhang Wang
 
Apache Kafka, and the Rise of Stream Processing
Apache Kafka, and the Rise of Stream ProcessingApache Kafka, and the Rise of Stream Processing
Apache Kafka, and the Rise of Stream ProcessingGuozhang Wang
 
Building Realtim Data Pipelines with Kafka Connect and Spark Streaming
Building Realtim Data Pipelines with Kafka Connect and Spark StreamingBuilding Realtim Data Pipelines with Kafka Connect and Spark Streaming
Building Realtim Data Pipelines with Kafka Connect and Spark StreamingGuozhang Wang
 
Building a Replicated Logging System with Apache Kafka
Building a Replicated Logging System with Apache KafkaBuilding a Replicated Logging System with Apache Kafka
Building a Replicated Logging System with Apache KafkaGuozhang Wang
 
Building Stream Infrastructure across Multiple Data Centers with Apache Kafka
Building Stream Infrastructure across Multiple Data Centers with Apache KafkaBuilding Stream Infrastructure across Multiple Data Centers with Apache Kafka
Building Stream Infrastructure across Multiple Data Centers with Apache KafkaGuozhang Wang
 
Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...
Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...
Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...Helena Edelson
 
Introduction to Kafka Streams
Introduction to Kafka StreamsIntroduction to Kafka Streams
Introduction to Kafka StreamsGuozhang Wang
 
Scala function-and-closures
Scala function-and-closuresScala function-and-closures
Scala function-and-closureswang hongjiang
 

Destacado (19)

深入剖析Concurrent hashmap中的同步机制(下)
深入剖析Concurrent hashmap中的同步机制(下)深入剖析Concurrent hashmap中的同步机制(下)
深入剖析Concurrent hashmap中的同步机制(下)
 
聊一些电影
聊一些电影聊一些电影
聊一些电影
 
Effective linux.2.(tools)
Effective linux.2.(tools)Effective linux.2.(tools)
Effective linux.2.(tools)
 
Enum开锁
Enum开锁Enum开锁
Enum开锁
 
Real world akka recepies v3
Real world akka recepies v3Real world akka recepies v3
Real world akka recepies v3
 
中等创业公司后端技术选型
中等创业公司后端技术选型中等创业公司后端技术选型
中等创业公司后端技术选型
 
Automatic Scaling Iterative Computations
Automatic Scaling Iterative ComputationsAutomatic Scaling Iterative Computations
Automatic Scaling Iterative Computations
 
Behavioral Simulations in MapReduce
Behavioral Simulations in MapReduceBehavioral Simulations in MapReduce
Behavioral Simulations in MapReduce
 
Apache Kafka at LinkedIn
Apache Kafka at LinkedInApache Kafka at LinkedIn
Apache Kafka at LinkedIn
 
Apache Kafka, and the Rise of Stream Processing
Apache Kafka, and the Rise of Stream ProcessingApache Kafka, and the Rise of Stream Processing
Apache Kafka, and the Rise of Stream Processing
 
Building Realtim Data Pipelines with Kafka Connect and Spark Streaming
Building Realtim Data Pipelines with Kafka Connect and Spark StreamingBuilding Realtim Data Pipelines with Kafka Connect and Spark Streaming
Building Realtim Data Pipelines with Kafka Connect and Spark Streaming
 
Building a Replicated Logging System with Apache Kafka
Building a Replicated Logging System with Apache KafkaBuilding a Replicated Logging System with Apache Kafka
Building a Replicated Logging System with Apache Kafka
 
Building Stream Infrastructure across Multiple Data Centers with Apache Kafka
Building Stream Infrastructure across Multiple Data Centers with Apache KafkaBuilding Stream Infrastructure across Multiple Data Centers with Apache Kafka
Building Stream Infrastructure across Multiple Data Centers with Apache Kafka
 
Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...
Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...
Building Reactive Distributed Systems For Streaming Big Data, Analytics & Mac...
 
Introduction to Kafka Streams
Introduction to Kafka StreamsIntroduction to Kafka Streams
Introduction to Kafka Streams
 
Scala function-and-closures
Scala function-and-closuresScala function-and-closures
Scala function-and-closures
 
functional-scala
functional-scalafunctional-scala
functional-scala
 
泛型总结
泛型总结泛型总结
泛型总结
 
Scala类型系统
Scala类型系统Scala类型系统
Scala类型系统
 

Similar a Exodus2 大局观

中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料yiditushe
 
J2ee经典学习笔记
J2ee经典学习笔记J2ee经典学习笔记
J2ee经典学习笔记yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Wade Huang
 
Java华为面试题
Java华为面试题Java华为面试题
Java华为面试题yiditushe
 
中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料yiditushe
 
Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解zany_hui
 
Spring 2.0 技術手冊第十章 - 專案:線上書籤
Spring 2.0 技術手冊第十章 - 專案:線上書籤Spring 2.0 技術手冊第十章 - 專案:線上書籤
Spring 2.0 技術手冊第十章 - 專案:線上書籤Justin Lin
 
ASP.NET Core 2.1設計新思維與新發展
ASP.NET  Core 2.1設計新思維與新發展ASP.NET  Core 2.1設計新思維與新發展
ASP.NET Core 2.1設計新思維與新發展江華 奚
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing江華 奚
 
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架Justin Lin
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7javatwo2011
 
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001rainx1982
 
Ajax Lucence
Ajax LucenceAjax Lucence
Ajax LucenceRoger Xia
 
Flex 4.5 action custom component development
Flex 4.5 action custom component developmentFlex 4.5 action custom component development
Flex 4.5 action custom component developmentjexchan
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非Tony Deng
 
用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Servicesjavatwo2011
 
IKVM.NET 深入敵營的 Java
IKVM.NET 深入敵營的 JavaIKVM.NET 深入敵營的 Java
IKVM.NET 深入敵營的 Java建興 王
 
基于Ivy ant的java构建初探
基于Ivy ant的java构建初探基于Ivy ant的java构建初探
基于Ivy ant的java构建初探Anson Yang
 

Similar a Exodus2 大局观 (20)

中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料
 
J2ee经典学习笔记
J2ee经典学习笔记J2ee经典学习笔记
J2ee经典学习笔记
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有
 
Java华为面试题
Java华为面试题Java华为面试题
Java华为面试题
 
中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料
 
Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解
 
Spring 2.0 技術手冊第十章 - 專案:線上書籤
Spring 2.0 技術手冊第十章 - 專案:線上書籤Spring 2.0 技術手冊第十章 - 專案:線上書籤
Spring 2.0 技術手冊第十章 - 專案:線上書籤
 
ASP.NET Core 2.1設計新思維與新發展
ASP.NET  Core 2.1設計新思維與新發展ASP.NET  Core 2.1設計新思維與新發展
ASP.NET Core 2.1設計新思維與新發展
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
 
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
Spring 2.0 技術手冊第七章 - Spring Web MVC 框架
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
 
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001
 
Ajax Lucence
Ajax LucenceAjax Lucence
Ajax Lucence
 
Flex 4.5 action custom component development
Flex 4.5 action custom component developmentFlex 4.5 action custom component development
Flex 4.5 action custom component development
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
 
用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services用JAX-RS和Jersey完成RESTful Web Services
用JAX-RS和Jersey完成RESTful Web Services
 
IKVM.NET 深入敵營的 Java
IKVM.NET 深入敵營的 JavaIKVM.NET 深入敵營的 Java
IKVM.NET 深入敵營的 Java
 
基于Ivy ant的java构建初探
基于Ivy ant的java构建初探基于Ivy ant的java构建初探
基于Ivy ant的java构建初探
 

Exodus2 大局观

  • 1. Exodus2 大局观 内容纲要: 1 , Exodus2 的历史 2 , WebX 大局观 3 , Exodus2 的部署 4 ,数据访问层 hongjiang 2009.5.16
  • 2. 1, Exodus2 的历史 Exodus2 代号名称的由来: 不知道大家注意过没有, exodus 和 ezra(BOPS 的代号 ) 都是 出自圣经,容易联想到这两个产品的设计者可能是基督教信仰 者或者深谙圣经。 校长: Exodus 是《圣经》出埃及记那一章。摩西带领犹太人走出埃 及是一段非常艰辛的过程。早些年 ali 曾经比较崇拜国外的技 术,雇佣硅谷的一些工程师开发过一些东西,后来证明并不好 用,后由宝宝带领开发出一套新的框架。这个过程是有些类似 于出埃及的过程的。 exodus2 是 exodus 后来的重构版本。
  • 3. Exodus2 的历史 即使一些工作 2 , 3 年以上的同事,谈及 Exodus2 的时候,也会说“水很深”。越 深入的了解,发现它的确有很多模糊或者 困惑的地方可能是历史遗留原因,我们需 要弄清楚,避免一些错误。 这个框架不仅 ali 在用,淘宝,支付宝也在 用,有些因素可能是其他公司有特殊的需 求,使得框架有所妥协而违背原先的设计 。
  • 4. 2. WebX 大局观 2.1 , Spring 框架 2.2 , Service 框架 2.3 , WebX 的表现层 2.4 , WebX 的业务层 2.5 ,表现层和业务层的交互 : CommandDispatcher— 忧愁河上的桥
  • 5. 2.1 Spring 框架 核心: DI 和 AOP
  • 6. Spring 框架布局 J2EE应用程序 消除 基于 重复代 Spring应用框架 POJO 码 简单开 发 IoC容器 AOP框架 事务 远程 DAO JMS JNDI 支持企业服务
  • 7. Spring 容器: Spring 容器有多种实现,分两类 : 1: BeanFactory 2: ApplicationContext ( 扩展了 BeanFactory, 提供了更多功能, 绝大部分应用都使用 ApplicationContext)
  • 8. 依赖注入: 依赖注入是 Spring 运用反向控制 原则解决配置管理和对象关系管理 的手段。 依赖注入的方式: 1: setter 方式 2: 构造器方式 3: 方法注入,抽象方法
  • 9. 对 AOP 的支持, 用代理类包裹切面 代理 调用者 目标 Spring 基于代理实现对 AOP 的支持 通过 J2SE dynamic proxies ,可以代理任意 Java 接口。 通过 CGLIB 字节码生成,可以代理 Java 类。 Spring 的代理机制可以支持由 Spring 容器创建的 bean ,无法支持应用中自行 new 出来的 bean 。 Spring 只支持方法连接点。
  • 10. Bean 如何和 Spring 容器交 互 3 个 Ware 接口:《骇客帝国》中的红药丸 BeanNameAware : 了解 Bean 的名称 BeanFactoryAware: 了解容器 ApplicationContextAware: 了解容器
  • 11. 2.2 Service FrameWork 和 Spring 有些相似的一套框架, 用来管理 Service 对象,负责其生命周期,根 据配置来装载 Service ,可以确保 Service 之间 的耦合是松散的
  • 12. Service 是什么? 没什么特别的,就是一些对象 ( 实 现了 Service 接口而已 ) ,不过这 些对象在 WebX 中都是一些比较通 用的服务或者工具。
  • 13. Webx 正常运行所必须的 Service FormService 读取并验证用户 submit 的 form 表单的 service 。 JSPService JSP 模板引擎,用来渲染 jsp 写成的页面模板。需要 TemplateService 的支持。 MappingService 将一个名字映射到另一个名字的 service 。 ModuleLoaderService 装载 turbine module 的 service ,例如: screen 、 action 、 control 等。 PipelineService 用来创建 pipeline 的 service 。 PoolService 缓存以减少对象创建的开销。 PullService Pull model service ,自动创建一定作用域的对象,而不需要应用程序干预 ( push )。 ResourceLoaderService 用来装载资源的 Resource loader service 。 RunDataService Webx 核心 service 之一,用来保存每一个 HTTP 请求的状态。需要 PoolService 和 UploadService 的支持。 TemplateService 用来管理 template engine ,渲染页面的 service 。 ThreadContextService 线程空间的 singleton 服务,方便 service 存取 request scope 的对象。 URIBrokerService 自动生成 URI 的 service 。 UploadService 用来上传图片和文件的 service 。 VelocityService Velocity 模板引擎,用来渲染 velocity 写成的页面模板。需要 TemplateService 的 支持。
  • 14. Service 概念 ( 摘自《 Exodus2 代码分析初步》 ) 一个服务 (Service) 可以有多个服务实例 一个实例 (Instance) 可以包含多个服务,并有一个实例上下文 (InstanceContext) 同一个实例的所有服务共享该实例上下文 在 Webx 中: 每个 WebxComponent 都是一个实例 每个 WebxComponent 都由一个 webx.xml 配置其中的服务 每个 WebxComponent 都继承缺省实例的配置,缺省实例由 webx-default.xml 和 webx-turbine-default.xml 的来合并定义
  • 17. 假设我们有 2 个 car 。 我们为全局配置了 A,B 两个服 务;为 car1 配置了 C 服务 ;为 car2 配置了 D 服务。 ServiceManager 初始化后 容器中会是怎样?
  • 18. A B Car1 Car2 C D 是这样么 ?
  • 19. ServiceInstanceContext ServiceConfig ServiceInstance Service 注意: ServiceInstance 是对 Service 的包装
  • 20. ServiceInstancA ServiceInstanceB ServiceInstanceC ServiceInstanceD ServiceInstancA ServiceInstancA ServiceInstanceB ServiceInstanceB ServiceInstanceC ServiceInstanceC ServiceInstanceD ServiceInstanceD 它有一个将未申明 Service 补全的过程。是这样 ?
  • 21. ServiceInstance 是对 Service 的包装。那么从 ServiceInstance 中如何获取 Service 对象?不同的 ServiceInstance 会共享 Service 么?看一下代码中的注释: // 1. 如果是 main-instance ,并且指定了 classname ,则实例化 main-instance 。 // 2. 如果是 main-instance ,并且未指定 classname ,则返回 null 。 // 3. 如果是 sub-instance ,并且指定了 classname ,那么: // 3.1 如果是 MultiInstance ,如果和 main-instance 的类相同,则同 4.3 。 // 否则报错。(这样做是为了兼容性好,特别是当一个原来不是 MultiInstance 的类转换成 MIS 时) // 3.2 如果 main-instance 不存在,则实例化 service instance 。 // 3.3 如果 main-instance 存在,但不是 MultiInstance ,则实例化 service instance 。 // 3.4 如果 main-instance 存在,而且是 MultiInstance ,则报错。 // 4. 如果是 sub-instance ,并且未指定 classname ,那么: // 4.1 如果 main-instance 不存在,则返回 null // 4.2 如果 main-instance 存在,但不是 MultiInstance ,则用 main-instance 的 类实例化 service instance 。 // 4.3 如果 main-instance 存在,而且是 MultiInstance ,则调用 main- instance 的 getInstance 方法。
  • 22. 假设我们的 A 服务实现了 MultiInstance 接口, B 服务 没有。 InstanceA InstanceB InstanceC InstanceD A B null null A A B B C null null D
  • 23. 说明:可以参考 DefaultServiceManager 的 initMapping 函数,最后 一段逻辑。 Exdodus2 中一共配置了 12 个 car , 22 个 Service 。经过 initMapping 后, services 这个 Map 中一共有 286 个 entry 而实现 MultiInstance 接口的只有: BootstrapResourceLoaderService, DefaultIPSeekerService, DefaultRunDataService, DefaultViewCacheService, 这 4 个 Service ,也就是说大部分 Service 每个 car 都会再创建自己的实例。这样在全局定义那么多 Service 干嘛?比如全局的 PullService , TemplateService 有什么作 用? 另外 : 在 webx-turbine-default.xml 中对 sub-instance 定义了 FreeMarkerService ,会用到么?
  • 24. 配置级联的 Spring 容器 我们说过,每个 car 里的 service 都是一份独立的 实例。同样,作为一个普通的 Service ,每个 car 中都会创建一份自己的 Spring 容器。假如我有 10 个 car ,就有 10 个各不相干的 Spring 容器。
  • 25. 但是,有一些 Beans 是不能够这样做的,否则会占用不必要的 系统资源。例如,和 cache 有关的 beans 。怎么解决这个问题 呢?有办法!我们可以把 Spring 容器级联起来,使父容器被所 有的 car 共享。改进方案如图:
  • 26. 要配置这种级联的 Spring 容器非常简单: WAR └─ WEB-INF │webx.xml - 在此配置共享的父容器 │ ├─ car1 │webx.xml - 在此配置派生的子容器 └─ car2 webx.xml - 在此配置派生的子容器 配置文件的写法完全同前例。这样,当查找一个 bean 时 , Spring 会首先在子容器中查找,如果找不到,再到父 容器里查找。你可以自由地决定,哪些 beans 需要被共享 ,哪些 beans 需要被某个 car 独享。
  • 27. 看看 Service 接口定义的 getParentService 方法: 对于 sub-instance ,取得其 main-instance ,否则返回 null 。 注意:和 ServiceContext.getService 方法不同,即使 parent instance 初始化失败, getParentService 也不会抛出异常,而是将 parent instance 初始化失败的信息记录在 log 中。 ServiceContext( 全局 Service 容器 ) 中: getService(svcName) getService(svcName, instanceName) 注释中说:如果 service 不存在,或初始化失败抛出 ServiceInstantiationException 但实际代码并未声明 throws ServiceInstantiationException to fix: 代码中的注释应该也修改一下。
  • 28. Service 框架和 Spring 框架的异同 1: Spring 是个更通用的容器,容器装载的 Bean 可 以是任何类型对象。而 Service 容器中装载 的是 Service 对象。 2: Spring 容器中的对象可以不必知道容器,而 Service 容器中 service 对象是紧密和容器耦合的 。
  • 29. Service 框架究竟有没有实现“依 赖注入” 《 Service 框架指南》中说 Service 框架不支持“注入”,而 Module 中却 用到了注入。 宝宝的答复: Service 框架不支持注入。但是应工程师要求,在 screen/action/control 等部 件中加入了注入功能,是用 cglib 直接实现的,和 service 框 架无关。 另外,我目前在做的工作是,将 webx 移植到纯 spring 框架 中,抛弃 service 框架, 因此注入从此不是问题了。
  • 30. 2.3 WebX 表现层 1, RunData :对 Req,Resp,Session 的封 装 2, Module :页面编程模块 3, Pipeline: 逻辑流程 4, 分析一个页面请求的流程
  • 31. RunData: 简化对 http 请求操作 RunData 实现了 RequestContext 接 口。 RequestContext 体系是一个用装饰 模式实现对功能的层层扩展。
  • 32. RequestContext 的构建 : 封装了哪些功能? 看看配置文件,对 RunDataService 的装配: 构建一个 ChinaRunData, 它通过一个个的工厂类来进行装配 (Decorate) ,负责调用这些工厂的是 RequestContextChainService 这些工厂的设置顺序: BufferedRequestContextFactory ↓ LazyCommitRequestContextFactory ↓ ParserRequestContextFactory ↓ SessionRequestContextFactory ↓ SetLocaleRequestContextFactory ↓ RewriteRequestContextFactory
  • 33. ChinaRunData: 注意包装的顺序 RewriteRequestContext SetLocaleRequestContext SessionRequestContext ParserRequestContext LazyCommitRequestContext BufferedRequestContext RequestContextImpl
  • 34. HttpSession 中的问题: 通过 BufferedRequestContext LazyCommitRequestContext 防止了 HttpResponse 的“自动输出”,使 得我们可以一直控制 http 头,有机会改写 cookie 信息,实现 session 的存储。 BufferedRequestContext 是缓冲了整个 http 的 head 和 content 还是只缓冲了 head ? 如果遇到一个很大的页面会如何?
  • 35. WebX 中的 Module Webx 中的页面逻辑编程模块。 Screen, Action,Control,Layout 都实现 了 Module 接口。所有的 Module 都是通 过 ModuleLoaderService 装载的。
  • 36. ModuleLoaderService 的装载 和依赖注入 装载 Module: 将创建各种 module 的任务转交给 ModuleFactory 去做。它可以为每一种 module ( screen/control/action )指定一个或多个 ModuleFactory 来创建。 Module 中的依赖注入 : 1: setter 方式。 2 : abstract getter 方式。 注入究竟是怎么实现的?
  • 37. 如果不加特别的配置,那么 DefaultModuleFactory 已经可以支持将 Service 注入到 module 中。例如在 module 中定义下面的 abstract getter :   protected abstract URIBrokerService getURIBrokerService(); 这句话告诉 DefaultModuleFactory :将 URIBrokerService 注入到 module 中 去。 对于抽象类,通过 CGLIB 动态生成子类 。 在获取 Module 实例时,调用 DefaultModuleFactory 的 getModule instantiateModule(String moduleClassName) 判断 Module 是否 abstract class, 如果是则用 CGLIB 来创建 Module 子 类。 ( 非 abstract 则用反射方式 newInstance) 随后 instantiateModule 函数中,如果 module 实例不为 null 则调用 injectDependences 函数,加载所创建的 module 实例依赖的对象。 injectDependences 调用 propertySetter.invoke 来注入依赖对象
  • 38. 如果 注入的不是 Service, 而是一个 Bean, 则需要利用 ReferenceResolver 接口 我们实现了 SpringReferenceResolver ,用来从 Spring 容器中取得对 象。 也就是说 Module 中注入 Service 对象, Webx 框架直 接实现,因为框架本身是一个 Service 容器,很容易获 取到 Service 对象。 而 Module 中注入 Bean 对象,则需要借助 Spring 容器 来获取,非 Service 对象都是通过 Spring 容器托管的。 比如 CommandDispather 这样的非 Service 对象还有 Biz 层的 AO,BO 等都是用 Spring 容器来托管的。
  • 39. 模板的渲染: TemplateEngineService TemplateService JspService VelocityService FreeMarkerService TemplateServer 通过注册一个 Engine 来实现渲染 。 渲染的顺序是: Screen->Layout->Control 渲染过程需要 TemplateContext , module 是从 rundata 中获取 templateContext 的, rundata 中需要通过 PullService 来获取。
  • 41. WebX 中的 Pipeline Pipeline 是表现层逻辑流程的核心。 它是一种责任链模式, (X 它的代码实现上并不 是) 把处理从一个 Valve 流向下一个 Valve ,主要响 应 action module 的 Valve 是 可以改变现有的 valve ,例如:改变分析 URL 的方法 PerformActionValve 。 可以插入新的 valve ,例如: Session 处理、权限验证等 。
  • 42. 根据返回值 ValveForward 进行跳转 内部重定向的实现方式: RedirectTargetValve processModule (ChooseValve 根据条件 RedirectTargetValve 选择 PerformValve)
  • 43. TryCacheFinallyValue: try{ tryPipeline: }catch(Exception e){ cachePipeline: }finally{ finallyPipeline: }
  • 45. 金立的补充: 在 pipeline.xml 配置中,第二个 valve: <valve class=“com.alibaba.exodus2.web.common.webx.valve.AuthContextValve” /> AuthContextValve 的验证机制只是对 URL 而没有对后续的 action 验证, 比如:请求 a.htm?action=x&event_submit_doXXX AuthContext 只验证了 a.htm ,并没有验证后续的 action 而用户有可能篡改后续的 action ,比如: a.htm?action=y&event_submit_doYYY 这样就执行到了 Y Action 里的逻辑。
  • 46. 分析一次页面请求经历的逻辑 假设我们执行 offer post 并转向成功页 面 1: 从 URL 的角度看 2: 从 Pipeline 的角度看
  • 47. 从 URL 的角度看: 只关注 URL 的进和出 根据规则 MappingService Request Url Rewrite 映射到物理路径 业务执行模块 URIBrokerService Response 构建要跳转的页面
  • 48. 详细的看这个过程 : 1: Webx 的初始化。 2: RunData 的构造。 3: Servlet 把逻辑交给 Pipeline
  • 49. Service 容器是被 WebxControllerListener 所初始化 的,该 Listener 在 Web 容器初始化时执行。创建好 Service 容器后,将其保存在 ServletContext 中。 Servlet 请求之前,先被 RundataFilter 拦截。它负责 调用 RundataService 把 Req/Resp/Session 等封装成 一个 RunData 对象,随后将其 setAttibute 为 req 的 属性,方便以后通过 req 得到 RunData 。 RunData 经过多重包装的 经过多重包装的 Request ServletContext Request Attribute Response
  • 50. 从 pipeline 的流程来看 : CheckCSRF Hessian 可选 Logging Auth AnalyzeURL Remote Screen GreenChanel Action Trace Template Screen Action Choose Redirect TBStore CheckCode ExpiredUrl
  • 51. 关于 PullServie 实现 Pull-MVC 的设计模式 怎么理解 Pull-MVC, 和 push 的不同之处? What this entails is the ability to create an object that is able to “pull” the required information out at execution time within the template.
  • 52. 2.4 WebX 业务层 (BIZ 层) 1 :业务层的 Service 容器。是如何创建的? 2 : AO,BO,DAO 都在 Spring 容器中。 AO 每次请求时都是一个新的实例? BO 是一些通用逻辑模块,可供多个 AO 调用。
  • 53. 用 Singleton 启动 Service 容器 为了分离 WEB 层和业务层的对象,我们常常 将 WEB 层的 Service 容器和业务层的 Service 容器彻底分开。这样, WEB 层的 Spring 容器 也随之和业务层的 Spring 容器彻底分开了。如 图所示:
  • 54. Web 层和 BIZ 层分离 Web 层 Service 容器 Car1 Car2 Spring 容器 Spring 容器 Dispatcher Dispatcher Biz 层 Service 容器 Spring 容器 AO BO
  • 55. 用 Singleton 启动 Service 容 器 上图中的 CommandDispather 在初始化中, 会调用 SingletonServiceManagerLoader 来 启动一个独立于 WEB 层的业务层 Service 容 器,再从中取得业务层的 Spring 容器。所有 业务层的对象,都配置在这个 Spring 容器中。 请记住,这是一个 Singleton ,意味着业务 层的 Spring 容器只会被初始化一遍。
  • 56. 1.5 表现层和业务层的交互 CommandDispather 使用命令模式,封装了从表现层到业务层 的调用,开发人员可以透明的对待它。 它有多种实现方式, Exodus2 用的那种方 式?
  • 59. 远程方式 ? 虽然由此设计,实际上我们所有的 web 和 biz 都是部署在同一个 JVM 中的。
  • 61. 在确认之前还要弄清另外一个问题 :《 Service 框架指南》中说在 web 层的 spring 容器中包含 biz 层的 spring 容器的引用。 如何做到?
  • 62. 宝宝《 Webx Modules 的装载以及依赖注入》 中说: …… 然而还有一个问题。在我们的常见应用中, web 层和 biz 业务层是分离的, web 层的 spring 容器和 biz 层的 spring 容器也是分离 的。上面的配置只能拿到 web 层 spring 容 器中的内容,不能拿到 biz 层 spring 容器的 内容,怎么办呢?方法很简单:在 web 层的 spring 容器中包含 biz 层的 spring 容器的引 用。
  • 63. 既然是分层的 (web 层和 Biz 层分别存在各自的 Service 容器中 ) 。 Web 层 spring 容器 又如何得到 biz 层的 Spring 容器引用呢?  我看你后边的配置, web 层是通过获取 Biz 层的 Service 容器引 用 再去获得 Biz 层 Spring 容器的, <beans> <bean id=“bizBeanFactory” class=“com.alibaba.service.spring.support.SingletonBeanFactorySe rviceBean”> <property name=“serviceConfig” value=“biz/services.xml”/><!-- 指向 biz 层 service 容器 --> </bean> </beans> 那样的话,两个 Service 容器不就完全耦合了吗, 还要 CommandDispatcher 干嘛。
  • 64. 实际在我们的 webx-default 中对 sub-instance 也存在一个对 biz 层 Spring 容器的引用: <service name=“BeanFactoryService” class=“com.alibaba.service.spring.DefaultBeanFactoryService”> <property name=“bean.descriptors”> <value>exodus2/bean/biz-delegate.xml</value> <value>exodus2/bean/web-tool.xml</value> </property> </service> web-tool.xml 里面配置了 WebApplicationContextUtilsBean ,里面 setter 了 serviceConfig:alibaba-biz-service.xml 。该 utilBean 初始化时会通过调用 SingletonServiceManagerLoader.getInstance( bootstrapResourceLoaderService, serviceConfig, initAll); 获取 biz 层的 Service 容器的单实例引用,进而获取 biz 层的 Spring 容器引用。 我们就可以通过该 UtilBean 来访问 biz 层的 spring 容器。
  • 65. Exodus2 的中实际场景(不完整) Car1 Car2 Spring 容器 Spring 容器 UtilBean UtilBean CommandDispatcher Biz 层 spring 容器 AO BO
  • 66. 思考: 这样岂不是将 web 层的 Service 容器和 Biz 层的 Service 容器耦合在了一起? Michael zhou: Command Dispatcher 是可以访问到业务层的代码的,按理说,这应 该是唯一的访问 业务层 spring 容器的方法。 你看到我把 bizBeanFactory 注入到 web 层容器中,说实在这种做法 是不太完美的。 但这也是对实际需求的一种妥协。因为有一些公用对象(非业务层 和数据访问层对 象,如 AO 、 DAO 等),需要放在一个大家都能访问到的地方。但 当你要访问业务对 象( AO 、 DAO 等)时,仍然应该通过 command dispatcher 来走 。
  • 67. Exodus2 中 CommandDispatcher 用哪种方式和 biz 层通讯? 看一下 biz-delegate.xml : <bean id="sessionDispatcher" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"> <property name="jndiName"> <value>ejb/CommandDispatcherSLSB</value> </property> <property name="businessInterface"> <value>com.alibaba.biz.command.dispatcher.CommandDispatcher</value> </property> </bean> <bean id="messageDispatcher" class="com.alibaba.biz.command.dispatcher.ejb.mdb.CommandDispatcherClient"> <property name="connectionFactory"> <bean class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>AlibabaWebxConnectionFactory</value> </property> </bean> </property> <property name="destination"> <bean class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>queue/AlibabaWebxQueue</value> </property> </bean> </property> </bean>
  • 68. commandDispatcherSelector 会根据 Command 的名称来判断使用 哪个 dispatcher 。 可供选择的 dispatcher : 1, sessionDispatcher 使用 ejb 方式。默认选择此方式。 2, messageDispatcher 使用消息队列的方式。 3, commandDispatcherLogic 直接通过已持有 biz 层 spring 容器的 引用来找到 biz 层的 AO 来执行。顺藤摸瓜。
  • 69. Exodus2 中的 CommandDispatcher 默认的方式 是 远程方式。用 Ejb 实现远程调用。
  • 70. Biz 层的 CommandDispatcher: 除了 web 层和 biz 之间使用 CommandDispatcher, biz 层内部之间也使 用了 CommandDispatcher 比如发邮件的情况, web 层 dispatcher 到 biz 层的 SendMailBO ,它 又会通过 biz 层的 dispatcher 交给 JMS biz 层这时用的 dispatcher 是异步消息队列的方式。 Web-CommandDispatcher EJB 容器 Biz-Serverice 容器 Spring 容器 BO Biz-dipatcher AlibabaWebxQueue ???
  • 71. Web-CommandDispatcher (sessionDispatcher) EJB 容器 EJB (…ejb.slsb.CommandDispatherBean) messageDispatcher Biz-Serverice 容器 Spring 容器 AO/BO/DAO Biz-dipatcher AlibabaWebxQueue EJB
  • 72. SLSB 和 MDB 类型的 EJB 分别是什么? com.alibaba.biz.command.dispatcher.ejb.slsb. CommandDispatherHome CommmandDispatherRemote CommandDispatherBean com.alibaba.biz.command.dispatcher.ejb.mdb. CommandDispatherClient CommandDispatherBean 为什么 sessionDispather 用到 slsb, messageDispather 用到 mdb (slsb 可用作远程或本地调用,而异步处理只能用 mdb)
  • 73. 为什么这么配置?性能问题 ► sessionDispatcher 配置的是远程方式。 ► 就一定会走远程方法调用么?还是也有可能走 local 方式? ► 如果走远程方法调用,是通过 socket 来进行么? 它的端口? 既然我们已经可以直接得到 biz 层对象 的引用;为何这样? 怎么看待这里的效率问题? ► 如果是,这些是否都是历史遗留原因?还是?
  • 74. 阿甘: 1 :虽然配置方式是远程调用, JBoss 内部会 对其优化,判断是同一 JVM ,会相当于本地 调用来对待。 3 :可能是历史原因,早期是支付宝有需要将 web 层和 biz 耦合起来, B2B 也保持了这样 的结构。但开发人员使用时应该按照 CommandDispatcher 的方式调用,保持这种 风格便于维护。
  • 75. Main-instance 和 sub-instance 中都配 置了 ComamndDispather 。 Main-instance 中的 Dispatcher 有何 用意? 阿甘的答复: Main-instance 中的 CommandDispather 是为了某些全局 Service 所用的,某些全局 Service 也会通过 Dispather 去访问 Biz 层 宝宝:也可能是后续维护的人员弄错了。应 该一个就够了。
  • 76. 3, Exodus2 的部署 JBoss 没有使用集群,当服务器比较多 时,相互之间的监控需要耗费很大性能 Exodus2 也没有实现集群。
  • 77. 前段负载均衡 F5 Exodus2 Exodus2 Exodus2 Apache Apache 。。。 共 64+7 台 JBoss JBoss Memcached 集群 DataBase
  • 78. 数据库的部署:双机热备 Oracle9.2 心跳检测 Oracle9.2 DB1 DB2 DB 并没有使用集群 ,放在两台小型机 共享存储设备 上。 DB2 同时还做 回滚备份
  • 80. 数据访问层 DAL Memcache Search Oracle ViewCache Engine LDAP 已经不再使用
  • 81. 数据库与搜索引擎 前端负载均衡 F5 Apache Apache 。。。 搜索引擎 搜索引擎 Dispatcher Build Index Delta Index 每天晚上 每 5 分钟 Oracle
  • 82. ViewCache 缓存数据 Oracle SCP XML 文件 Sync Engine ViewCacheService ( 已不用 JOS) Search Engine Exodus2 搜索引擎的数据:提供统计信息,相当于类目的属性

Notas del editor

  1. Spring2.5 整合了 AspectJ6 ,根据动态生字节码方式支持字段等其他的连接点
  2. 杨亮:能不能把 BeanFactoryService 也实现 MultiInstance 接口,让 car 的每个 BeanFactoryService 实例都引用 main 的 BeanFactoryService 的实例 阿甘:一些全局的 Service 比如 RunDataService 会依赖其他 Service ,所以全局会设置很多 Service
  3. 宝宝意思是 service 容器并没有实现 service 之间的注入功能,比如: ServiceA 依赖于 ServiceB 的,需要通过 ServiceManager.getService(ServiceB.class) 。但 ModuleLoaderService 利用 ModuleFactory 实现对 Module 的依赖注入功能
  4. 缓冲了整个页面。等页面中全部元素都渲染完成,再开始向客户端 response 。 如果遇到一个很大的页面,那么应该是这个 Screen 设计的不合理。假设真有这种需要,那么应该关闭 buffer ,要特殊对待。
  5. WebX 中并没有用到 ReferenceResolver
  6. 同一一个请求中 Screen 和 layout 和 action 都是引同一个 TemplateContext 对象实例。而每一个 control 都有一个以 control 名字做为 key 的 TemplateContext 。如果 control 需要用 Screen 中 TemplateContext 中对象时。可以在 screen 模板调用 contorl 时用 setParameter 方法注入。 例: $ control.setTemplate(&amp;quot;alipayManagerRegister.vm&amp;quot;).setParameter(&amp;quot;registerError&amp;quot;,$registerError).setParameter(“email&amp;quot;,$!email) 多个就直接往后加 setParameter(“xxx”,$!xxx)
  7. 关于 Push MVC Model The current encouragement that Turbine gives to developers is to do a mapping between one Screen (Java) and one Template (WM or V). The way it works is that you build up a Context object that is essentially a Hashtable that contains all of the data that is required to render a particular template. Within the template, you refer to that data in order to format it for display. I will refer to this as the &amp;quot;Push MVC Model.&amp;quot;
  8. 杨亮: AO 是 prototype ,每次请求都新建一个实例,因为他有个 command 引用。 Command 就是 web 调用 biz 时新建 CommandSupport 实例。 里面存储着 web 层传过来的参数集。
  9. 我还是没理解他说的妥协是怎么回事? 宝宝后来举了一个 DWR(java 层 ) 的用法,假设 car1 和 car2 都需要使用 DWR 这个对象,并且 DWR 又会操作 Biz 层的对象。 那么最简单的方式就是把 DWR 放到 Biz 层的 Spring 容器中,并提供 car1 和 car2 到 DWR 的访问途径。 Web 层到 Biz 层 Spring 容器的引用,决不能被当作 CommandDispatcher 的快捷方式来使用。
  10. sessionDispatcher 引用一 个 ejb/CommandDispatcherSLSB 的 ejb 实例。而这个 ejb 实例 ( com.alibaba.biz.command.dispatcher.ejb.slsb.CommandDispatcherBean ) 也只是代理了 commandDispatcherLogic 。 public Result execute(Command command) { Result result = getCommandDispatcherLogic().execute(command); }
  11. 宝宝:也可能是后续维护的人员弄错了。应该一个就够了。 阿甘:如果只用一个全局的话,也不排除有没有其他陷阱,比如会否用到 ResourceLoaderService ,每个 car 是不同的。
  12. Apache 除了打点用到,有其他作用么? Exodus2 中应该没有静态页面吧?
  13. iBatis 的配置,似乎只对少量业务使用了高速缓存。 Type=LRU
  14. Delta Index 增量索引,索引的信息并不完整,所以还不能替代每天晚上的 Build Index 目前数据库 offer 数据在 2 亿多,还能承受 Build Index ,未来可能会面临压力。
  15. X 项目二期发布后, XML 文件比以前大了很多,目前大概有将近 30m 。