- 浏览: 518848 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
u011165335:
distinct不影响使用半连接
(转)关于semi-join/anti-join的一点探讨 -
353790060:
redo 记录事务执行后的日志 undo 记录事务回滚的日志 ...
Oracle redo与undo浅析 -
jayxigua:
redo用于在失败时重放事务(即恢复事务),undo则用于取消 ...
Oracle redo与undo浅析 -
aa_qq110:
Openbravo有中文包吗
Openbravo开发手册 -
iocaop:
不错,写的很清晰易懂
JAVA 服务提供者框架介绍
在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框架将会自动找到这些初始化类,当初始化数据库访问层的时候。
发表评论
-
Openbravo 论坛
2014-03-12 20:55 67大家好, 新开了一 ... -
Openbravo与淘宝对接文档二
2014-01-01 17:49 4088这篇文章介绍消息服务的使用 1. 登陆沙箱用户 ... -
openbravo与淘宝对接文档一
2013-12-31 21:53 1900首先进入沙箱首页:http://www.tbsandbox ... -
How to automatically populate search keys
2013-05-20 21:13 1002Introduction Search keys are ... -
How to create an Alert
2013-05-12 22:24 1255Objective The objective of t ... -
Openbravo 如何给窗口添加新字段
2012-12-17 21:04 1419以薪资表为例,假设我们现在有生效日期,还没有失效日期,支付时 ... -
Openbravo3.0 服务端技术--数据访问层(Data Access Layer)
2012-10-24 23:46 1938Data Access Layer(DAL)描述 ... -
Openbravo3.0 客户端代码开发与API
2012-10-04 18:13 2551一. 客户端代码开发工具 ... -
Openbravo3.0 组织机构设置介绍
2012-06-24 17:31 2625一. 简要介绍 ... -
Openbravo3.0 用户操作界面介绍
2012-06-12 22:57 1788一. Openbravo3.0 新颖特征介绍 ... -
Openbravo3.0 怎样新建一个窗口
2012-03-15 21:28 2608一.需求背景 假设我们在开发一个人力资源模 ... -
Openbravo3.0与Eclipse集成简介
2012-01-07 22:30 3561... -
Openbravo 3.0 销售管理组织机构消失问题
2011-06-09 18:43 1075请参考如下文章: http://wiki.openbravo ... -
Openbravo 3.0汉化包
2011-05-26 22:30 8134附件有openbravo3.0的汉化包下载,不过不完 ... -
Openbravo ERP 3.0安装指南
2011-05-22 16:21 20286Openbravo ERP 3.0已经发布有一段时间 ... -
Openbravo 手工导入商品库存与价格
2011-05-19 16:36 1598由于Openbravo自带的导入功能 不能够导入商 ... -
Openbravo 窗口字段自定义
2011-05-19 16:00 1468假如openbravo的添加产品页面有很多字段,我 ... -
Openbravo ERP 定制菜单
2011-05-10 12:15 1714一. 删除菜单节点 1.点击 ... -
Openbravo ERP 通过数据字典定制属性
2011-04-29 11:13 2077有些时候,openbravo并不 ... -
OB汉化包
2010-09-08 12:01 1300上传一个OB2.4汉化包,供日后下载。
相关推荐
Openbravo 3.0 会计文件,适用与openbravo 3.x所有版本
100%汉化过的Openbravo 3.0 mp26 中文语言包
Openbravo3.0二次开发部署步骤
openbravo 汉化包,目前只汉化了80%左右的文字,不过主要的部分都以及汉化了。
Openbravo-3.0PR18Q3.2汉化包本人亲测,90%的汉化率。
openbravo-3.0PR19Q3
NULL 博文链接:https://liwenshui322.iteye.com/blog/1054473
OpenBravo销售,财务,仓存等系统的 数据库结构基本分析,
《OpenbravoPOS 2.3汉化包详解与应用》 OpenbravoPOS,全称为Openbravo Point of Sale,是一款开源的销售点管理软件,专为零售业设计,旨在提供灵活、高效且易用的销售解决方案。2.3版本的汉化包是针对中国用户特别...
Openbravo数据库关系表
综上所述,Openbravo 不仅提供了一款强大的ERP软件,还为开发者提供了一整套完善的支持体系,帮助他们轻松地进行定制化开发,满足不同企业的需求。通过理解和掌握上述核心知识点,开发者可以更高效地利用Openbravo ...
Openbravo 3 30.3 中文汉化包是一个专门为Openbravo企业资源计划系统(ERP)设计的语言转换工具,旨在为中文用户提供更友好的界面和操作体验。Openbravo是一个开源的ERP解决方案,它涵盖了财务管理、供应链管理、...
Openbravo ERP 的插件体系非常灵活,可以通过安装不同的扩展模块来满足特定行业的特殊需求。此外,还提供了多种语言包和垂直行业包,使得系统能够在全球范围内得到广泛应用。 #### 三、其他特性 除了上述关键技术...
Openbravo_ERP 的中文介绍,帮你快速走入 Openbravo_ERP 的世界
openbravoPOS 实操 底层数据库写入逻辑 业务推测
- **主树结构**:介绍了 Openbravo ERP 的目录结构,包括各个模块的位置和作用。 - **风格指南**:提供了一些关于编码风格的指导原则,以保持代码的一致性和可读性。 **5.6 风格指南** - **逻辑比较**:推荐使用...
Openbravo erp 实施笔记
与openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关的openbravo 安装相关...
Openbravo数据库的pdm图,使用PowerDseigner打开,可以作为数据库设计或者ERP研究之用
开源ERP OpenBravo的数据库关系图。