`
liwenshui322
  • 浏览: 520601 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Openbravo3.0 体系结构

 
阅读更多

   在Openbravo 3.0中,我们由一个传统的servlet结构转换到了一个全新的富因特网应用程序结构(Rich Internet Application (RIA))。在这种富客户端结构中,请求页面与请求数据是分开的。第一次点击的时候,请求到了页面,如果不关闭这个页面的话,这个页面一直可以重用,只需要继续请求你需要的数据填充到页面即可。与js框架jquery,ext,还有flex雷同,只是openbravo里面用的是另外一种技术叫做smartclient。

 

         一. 体系构架图

 

         1. JSON模块

         用于客户端与服务器端数据交换,是一种约定的数据交换的格式。

 

         2. Weld模块

         该模块提供独立的注入与组件的的管理。

 

         3. kernel模块

         该模块专注于一些基础任务,比如:请求的处理,事件的处理,压缩信息,缓存。

 

         4. datasource模块

         该模块使用json模块提供的数据,将这些数据整理成客户想要的结果。

 

         5. smartclient模块

         提供smartclient用户客户端库类

 

         6. application模块

         该模块管理导航栏,表格,单据等客户端组件的生成以及服务器端代码

 

 

 

         二. 操作界面主要概念: 控件和控件提供者

 

         openbravo3.0前台界面是由各种控件组成的,控件可以是一个多选框,一个文本框,或者仅仅是一个布局或者一个表格。

         控件是在模块里面实现的。在模块中,控件是由控件提供者管理的,它负责创建控件,并且将控件提供给Openbravo kernel模块。控件提供者也负责一些静态内容的注册,下面会提到。

 

          控件可以通过一个URL获取,比如下面一个URL可以获取销售发票窗口的javascript脚本:

http://localhost:8080/openbravo/org.openbravo.client.kernel/OBUIAPP_MainLayout/View?viewId=_167

 

         OBUIAPP_MainLayout 标志请求的是客户端模块,模块中的控件提供者知道怎么通过剩下的那段URL:View?viewId=_167来创建控件,也就是请求的javascript。下面这个图演示了这个流程:

 


 

        整个请求流程有如下步骤:

 

        1. 一个控件请求(包含控件类型和ID)到达客户端Kernel模块

 

        2. 基于控件类型,kernel模块找到负责处理这类请求的模块(后面称之为A模块),将这个请求转发过去。于是A模块根据控件ID来创建模块。

 

        3. A模块从数据库表,或者其他资源读取到控件的定义,然后实例化这个控件。

 

        4. 这个控件会创建返回客户端的形式,如果是一个模板控件,这个控件会调用一个模板程序来创建一个模板。

 

        5. 返回的“视图”是由模板创建的或者由java后台代码生成的一段字符串。

 

        6. 返回的视图被客户端kernel模块接收,kernel模块会检查结果的语法和压缩要返回的结果。

 

        7. 将压缩的结果返回给请求者。

 

 

        三. Weld模块介绍

 

        Weld 是一个实现了JSR-299标准的框架,JSR-299定义了java上下文依赖注入的标准。Openbravo使用weld框架来实现独立注入,控件管理以及业务事件管理。首先,定义控件和控件的生命周期。然后,将定义的控件注入其他控件当做。需要注意的是,如果要使用weld独立注入功能,我们不可以通过原始的构造器来创建对象。

 

         1. 生命周期定义

          控件的生命周期可以有三种类型:ApplicationScope,SessionScope,RequestScope。生命周期是通过声明的形式表达的。比如:

 

 

@SessionScoped
public class MenuManager implements Serializable {
....
}
 

 

          2. 注入

          定义好的控件可以被自动注入到其他的控件里面,通过使用注入声明。比如:

 

 

@Inject
private MenuManager menuManager;
 

 

          3. Weld实例化对象

          weld框架在新建对象的时候通常要注入一些控件,也就意味着不能通过new 这样的方式创建对象。其实,通常我们不需要直接通过new的方式创建对象,对象一般都是通过注入的方式来传递的。不过如果你的对象不能够注入的方式传递,Openbravo提供了一个工具方法来帮助你:

           org.openbravo.base.weld.WeldUtils.getInstanceFromStaticBeanManager(Class<T> type);

           会返回一个实例化的对象。

 

          4. 分析路径

           Weld 根据路径来找到哪些控件有声明为注入方式(路径被定义在META-INF/beans.xml),为了避免搜索所有的class文件,beans.xml文件定义了哪些路径不进行搜索。

 

 

           四. Etags,Caching(缓存)和Compressing(压缩)

 

           为了提高用户的访问速度和体验,我们需要在浏览器端和服务端提供缓存机制。

           Openbravo实现了几种不同类型的缓存在不同的应用层次,它利用了模块管理的优点,一个模块是否在开发状态,缓存机制是不同的。如果一个模块在开发状态,会阻止使用缓存,因为我们不想要缓存影响了我们的测试结果。但是,如果不是处于开发状态,就会最大化使用缓存机制。

 

            1. 静态JS文件缓存与更新

             一个静态的JS文件包含了控件使用的一个文本库或者一个标准的控件。通常浏览器会缓存这个JS文件,不过与这个JS文件相关的模块更新时,这个静态的JS文件也会更新。过程如下:

            JS静态文件是由模块提供的,模块通过它的控件提供者(ComponentProvider)发布它的静态资源,ComponentProvider通过GetGlobalResources方法获得资源,Openbravo将所有相关联的静态资源整合到一个大的JS文件当中,整合的顺序与根据模块间的关系有关. 这个JS文件的名称是一串字符串,比如:088afd247a8fe06c91a654891a1358a2.js 名称与内容相关。如果内容发生改变,名称也会变,这样浏览器也就会重新加载。这个静态的JS文件生成在web/js/gen下面。(如果模块属于开发状态,JS文件将不会被压缩)

 

             2. 控件的缓存与更新

             控件是动态的,包含运行时从数据库读取的数据。所以控件是在用户请求的时候生成的,缓存在服务器端。服务器端可以验证一个控件是否已经改变,从最后一次请求开始。在客户端,是不可以进行验证的。

             为了验证服务器端缓存的控件是否与客户端的缓存的一致,我们使用了一个概念Etag,Etag类似于一个hashcode。用于验证,服务端缓存的控件的内容是否改变,自从浏览器最后一次请求之后。

             Etag生成方式:

             a. 模块不属于开发状态,Etag=用户名称+模块版本

             b. 模块属于开发状态,Etag=用户名称+当前时间(精确到毫秒)

 

             3. 压缩与语法检查

             模块输出的内容在发给客户端前,可以进行语法检查和压缩。压缩用的是jsmin, 语法检查用的是JSLint和JSLint4Java. 如果模块属于开发状态,会进行语法检查但是不会压缩。但是,如果模块不属于开发状态,只进行压缩,不进行语法检查。

 

 

             五. 模块的代码构架

 

              一个模块在openbravo里面的代码结构是固定的,参考如下图:


          

 

        1. java代码放在src目录下面

        2. 静态的JS文件放在:web/[modulepackage]/js

        3. 样式文件(css, images, js)所在目录:web/org.openbravo.userinterface.smartclient/3.00/[modulepackage]             

 

         六. 控件提供者

 

          每一个module都会实现一个控件提供者,一个控件提供者(componet provider)完成如下二个任务:

          1. 用户的请求从kernel模块发过来后,它负责创建用户请求的控件(componet)

          2. 它负责将module中的注册静态的资源到openbravo kernel。

 

          控件提供者(componet provider)是一个weld控件,一个控件提供者类必须有2个声明:

          1. @ApplicationScoped标志, 标明这个类是一个单例。

          2. @ComponetProvider.Qualifier 为这个类注册一个唯一的标识

          比如:

 

@ApplicationScoped
@ComponentProvider.Qualifier(ExampleComponentProvider.EXAMPLE_VIEW_COMPONENT_TYPE)
public class ExampleComponentProvider extends BaseComponentProvider {
  public static final String EXAMPLE_VIEW_COMPONENT_TYPE = "OBEXAPP_ExampleViewType";

         PS:控件提供者类必须跟它的module处于同一个包下面。

 

        控件提供者还有另外一个事情,实例化一个控件。

        比如:

 

public Component getComponent(String componentId, Map<String, Object> parameters) {
  if (componentId.equals(ExampleViewComponent.EXAMPLE_VIEW_COMPONENT_ID)) {
    final ExampleViewComponent component = new ExampleViewComponent();
    component.setId(ExampleViewComponent.EXAMPLE_VIEW_COMPONENT_ID);
    component.setParameters(parameters);
    return component;
  }
  throw new IllegalArgumentException("Component id " + componentId + " not supported.");
}

         PS:这个方法是在你有动态内容的时候才有用处,如果你的module只有静态的JS/CSS,这个方法可以为空,或者直接抛异常。

 

         控件可以很简单,如果它集成系统的BaseComponet类,只需要实现generate方法即可。

 

         控件提供者最后一个事情是,注册静态资源(CSS,JS).这些静态资源会被Openbravo kernel 关联压缩。比如:

 

public List<ComponentResource> getGlobalComponentResources() {
  final List<ComponentResource> globalResources = new ArrayList<ComponentResource>();
  globalResources.add(createStaticResource(
      "web/org.openbravo.client.application.examples/js/example-view-component.js", true));
  globalResources
        .add(createDynamicResource("org.openbravo.client.kernel/"
            + ExampleViewComponent.EXAMPLE_VIEW_COMPONENT_ID + "/"
            + ExampleViewComponent.EXAMPLE_VIEW_COMPONENT_ID));
  globalResources.add(createStyleSheetResource(
        "web/org.openbravo.userinterface.smartclient/openbravo/skins/"
            + KernelConstants.SKIN_VERSION_PARAMETER
            + "/org.openbravo.client.application.examples/my-styles.css", false));
  return globalResources;
}
 

 

       七. 服务端处理客户端请求集散中心

 

       openbravo提供一种方便客户端发送给服务端请求的机制,叫做ActionHandler(请求控制中心)。

 

       服务器端代码示例:

 

 

package org.openbravo.client.application.examples;
 
....
 
public class MyActionHandler extends BaseActionHandler {
  /**
   * Needs to be implemented by a subclass.
   * 
   * @param parameters
   *          the parameters obtained from the request. Note that the request object and the session
   *          object are also present in this map, resp. as the constants
   *          {@link KernelConstants#HTTP_REQUEST} and {@link KernelConstants#HTTP_SESSION}.
   * @param content
   *          the request content (if any)
   * @return the return should be a JSONObject, this is passed back to the caller on the client.
   */
  protected JSONObject execute(Map<String, Object> parameters, String content) {
    try {
       // create the result
       JSONObject json = new JSONObject();
       json.put("result", "success");
 
       // and return it
       return json;
     } catch (Exception e) {
       throw new OBException(e);
     }
   }
}
 

       客户端代码示例:

 

// define the callback function which shows the result to the user
var callback = function(rpcResponse, data, rpcRequest) {
    isc.say('The result is : ' + data.result);
};
        
// and call the server
OB.RemoteCallManager.call('org.openbravo.client.application.examples.MyActionHandler', {}, {}, callback);
 

 

       八.  应用初始化

 

        当我们的一个应用启动的时候,我们通常要初始化一些事情。比如注册SQL当我们使用hibernate的HQL的时候。Openbravo提供一种机制来实现这种初始化工作。需要做到两点:

        1. 创建一个实现了org.openbravo.client.kernel.ApplicationInitializer接口的类 

        2. 声明这个接口为@ApplicationScoped

        比如:

 

@ApplicationScoped
public class KernelApplicationInitializer implements ApplicationInitializer {
 
  public void initialize() {
    OBDal.getInstance().registerSQLFunction("ad_column_identifier_std",
        new StandardSQLFunction("ad_column_identifier_std", StandardBasicTypes.STRING));
  }
}

        Weld框架将会自动找到这些初始化类,当初始化数据库访问层的时候。

 

 

 

 

 

 

 

  • 大小: 89.4 KB
  • 大小: 27.5 KB
分享到:
评论
1 楼 ithinkopen 2013-03-27  
     楼主甚是强大

相关推荐

    Openbravo 3.0 会计文件

    Openbravo 3.0 会计文件,适用与openbravo 3.x所有版本

    Openbravo 3.0 mp26 中文语言包

    100%汉化过的Openbravo 3.0 mp26 中文语言包

    Openbravo3.0二次开发部署步骤

    Openbravo3.0二次开发部署步骤

    Openbravo3.0汉化包(80%汉化)

    openbravo 汉化包,目前只汉化了80%左右的文字,不过主要的部分都以及汉化了。

    openbravo-3.0PR19Q3

    openbravo-3.0PR19Q3

    Openbravo-3.0PR18Q3.2汉化包

    Openbravo-3.0PR18Q3.2汉化包本人亲测,90%的汉化率。

    Openbravo ERP 3.0安装指南

    NULL 博文链接:https://liwenshui322.iteye.com/blog/1054473

    OpenBravo 数据库结构基本分析

    OpenBravo销售,财务,仓存等系统的 数据库结构基本分析,

    openbravoPOS2.3汉化包

    《OpenbravoPOS 2.3汉化包详解与应用》 OpenbravoPOS,全称为Openbravo Point of Sale,是一款开源的销售点管理软件,专为零售业设计,旨在提供灵活、高效且易用的销售解决方案。2.3版本的汉化包是针对中国用户特别...

    Openbravo数据库关系表

    Openbravo数据库关系表

    00-Openbravo开发手册

    综上所述,Openbravo 不仅提供了一款强大的ERP软件,还为开发者提供了一整套完善的支持体系,帮助他们轻松地进行定制化开发,满足不同企业的需求。通过理解和掌握上述核心知识点,开发者可以更高效地利用Openbravo ...

    Openbravo 3 30.3 中文汉化包

    Openbravo 3 30.3 中文汉化包是一个专门为Openbravo企业资源计划系统(ERP)设计的语言转换工具,旨在为中文用户提供更友好的界面和操作体验。Openbravo是一个开源的ERP解决方案,它涵盖了财务管理、供应链管理、...

    Openbravo ERP 技术简介(中文)

    Openbravo ERP 的插件体系非常灵活,可以通过安装不同的扩展模块来满足特定行业的特殊需求。此外,还提供了多种语言包和垂直行业包,使得系统能够在全球范围内得到广泛应用。 #### 三、其他特性 除了上述关键技术...

    Openbravo_ERP介绍

    Openbravo_ERP 的中文介绍,帮你快速走入 Openbravo_ERP 的世界

    openbravoPOS操作记录

    openbravoPOS 实操 底层数据库写入逻辑 业务推测

    Openbravo技术评测

    - **主树结构**:介绍了 Openbravo ERP 的目录结构,包括各个模块的位置和作用。 - **风格指南**:提供了一些关于编码风格的指导原则,以保持代码的一致性和可读性。 **5.6 风格指南** - **逻辑比较**:推荐使用...

    Openbravo erp 实施笔记.pdf

    Openbravo erp 实施笔记

    Openbravo-POS-2.20.exe

    与openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关...

    Openbravo数据库PDM图

    Openbravo数据库的pdm图,使用PowerDseigner打开,可以作为数据库设计或者ERP研究之用

    OpenBravo ERP E-R图

    开源ERP OpenBravo的数据库关系图。

Global site tag (gtag.js) - Google Analytics