金蝶时期的那些笔记.docx
《金蝶时期的那些笔记.docx》由会员分享,可在线阅读,更多相关《金蝶时期的那些笔记.docx(24页珍藏版)》请在冰豆网上搜索。
金蝶时期的那些笔记
晚上睡不着,打开电脑翻到了一些当年在金蝶时写的笔记,还是让它们出来透透气吧,要不连我都忘记自己曾经写过这些东西了。
金蝶是我第一个东家,也是我技术能力提升最快的地方,真心祝福金蝶能高飞。
EAS开发环境部署
一.开发环境的搭建
由于现场开发环境与研发中心的差异,搭建环境会有差异,为了保证最后环境的搭建成功,我们分步骤进行搭建,以方便其中的一步如果出错,方便好定位问题
1.1使用BOS启动客户端
启动BOS,新建一个工程
加载EASJar包(D:
\kingdee\eas\server\lib\下的所有目录的jar包,有些麻烦,所以可以考虑把所有jar包拷贝到一个目录下)
这里我把所有的jar包都拷贝到了我自己建的目录allJars
然后BOS加载
添加外部JAR
设置JVM参数
-DEAS_HOME=D:
\kingdee\eas(EAS_HOME相当于JDK_HOME)
-DEAS_SERVER=tcp:
//localhost:
11034(服务端的IP)
-Dlog4j.configuration=file:
D:
\kingdee\eas\client\deploy\client\log4j.properties(Log4j日志配置文件路径,可以没有这个参数)
Ok,jar包加载了,启动参数设置了后还需要修改几个地方
D:
\kingdee\eas\client\deploy\client\vmoptions.properties
增加客户端启动的元数据加载路径,这部非常关键
OK,现在可以启动试试了
OK,搞定(这只是万里长征的第一步)
1.2部署自己的代码和元数据到环境中
这一步也就是让你的代码和元数据要优先于EAS原有代码和元数据的加载
代码优先的设置方法:
虚拟W盘,命令:
substw:
你要虚拟的目录(相应的去掉W盘的命令是
substw:
/d)
W盘建立好后,在W盘创建dev目录,并建立两个文件server-user.liblist和client-user.liblist
这两个文件用于记录优先加载的目录是那些,因为我开发的代码都会编译到D:
\MyCode\EAS_01\bin,所以我制定客户端优先加载这个目录,服务端是一样的道理
然后我们设置元数据的优先加载方式
客户端,修改D:
\kingdee\eas\client\deploy\client\vmoptions.properties,修改部分见红线,因为我的元数据会发布到D:
\kingdee\apusic\metas;,所以这里可以设置为优先加载
服务端
修改D:
\kingdee\eas\server\bin\\common.pm
这个文件,原理和客户端修改类似
这个时候,基本都差不多了,我们尝试下看我们的单据是否能够被优先加载(这里有点文档思路写的有点跳跃,大家将就着看把,时间紧迫,顾不得字斟句酌了,J)
1.3启动EAS,看我们的单据能否使用
首先用administrator登陆
增加到EAS菜单中去
重新用用户登陆,可以看到我们的菜单项了
EAS是MVC架构的么?
2006年3月
EAS是MVC架构的么?
逐一分析,先看看EAS是否具备M、V、C这三个元素
Modle--xxxControllerBean,在ControllerBean中除了定义了对实体的CRUD(addnew,getValue,update,delete)操作外,还包括实体相关的业务操作方法,如submit,audit,freeze等,应该算的上标准的Modle,下边是摘抄的一些对Model的定义
模型(Model):
就是业务流程/状态的处理以及业务规则的制定。
业务流程的处理过程对其它层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。
业务模型的设计可以说是MVC最主要的核心。
目前流行的EJB模型就是一个典型的应用例子,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件,但它不能作为应用设计模型的框架。
它仅仅告诉你按这种模型设计就可以利用某些技术组件,从而减少了技术上的困难。
对一个开发者来说,就可以专注于业务模型的设计。
MVC设计模式告诉我们,把应用的模型按一定的规则抽取出来,抽取的层次很重要,这也是判断开发人员是否优秀的设计依据。
抽象与具体不能隔得太远,也不能太近。
MVC并没有提供模型的设计方法,而只告诉你应该组织管理这些模型,以便于模型的重构和提高重用性。
我们可以用对象编程来做比喻,MVC定义了一个顶级类,告诉它的子类你只能做这些,但没法限制你能做这些。
这点对编程的开发人员非常重要。
业务模型还有一个很重要的模型那就是数据模型。
数据模型主要指实体对象的数据保存(持续化)。
比如将一张订单保存到数据库,从数据库获取订单。
我们可以将这个模型单独列出,所有有关数据库的操作只限制在该模型中。
View-xxxEditUI,EditUI也应该算是标准的View,用于数据展示、数据采集、触犯用户事件等
视图(View)代表用户交互界面,对于Web应用来说,可以概括为HTML界面,但有可能为XHTML、XML和Applet。
随着应用的复杂性和规模性,界面的处理也变得具有挑战性。
一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上的业务流程的处理。
业务流程的处理交予模型(Model)处理。
比如一个订单的视图只接受来自模型的数据并显示给用户,以及将用户界面的输入数据和请求传递给控制和模型。
Controller-?
?
?
EAS的控制器在哪里,我一直没想明白,控制器的主要作用是接受客户请求,然后将模型与视图匹配在一起,共同完成用户的请求。
但我没有在EAS的框架中找到类似的东东,大胆的想了一下,我觉得不光是EAS没有Controller,可能所有C/S架构的都不太可能会有这样的东东,C/S架构不同于B/S,B/S的View和Modle同处于服务器端,可以进行协作处理,选择什么样的模型,选择什么样的视图,你可以在服务端完成,而C/S架构不是这样架构的,所以EAS并不是标准的MVC体系架构
EAS学习-UI体系
2006年3月
下边这个集成体系是一个典型单据编辑界面的集成体系
HouseForRentEditUI为自定义的单据编辑界面
不同的父类UI有着不同的功能,这个可以从单据上的Action可以看到
下图为CoreBillEditUI的功能列表
下图为EditUI的功能列表
下图为CoreUI的功能列表
另外,单据的状态有以下几种
publicclassOprtState
{
publicOprtState()
{
}
publicstaticStringADDNEW="ADDNEW";
publicstaticStringVIEW="VIEW";
publicstaticStringEDIT="EDIT";
publicstaticStringCOPYADDNEW="COPYADDNEW";
publicstaticStringEXITING="EXITING";
}
CoreUIObject
处理一些UI底层的功能,类似与JDK中的Component
比如:
列表界面体系
EAS框架(CoreUI,EditUI,CoreBillEditUI)实现了一些最基本的功能
AbstractXXXUI做了什么事情呢?
1.构造界面的代码
2.构造事件
3.构造事务
4.让实现更单纯化
一个单据的编辑界面主要的几个方法:
1.onLoad()
2.loadField()
3.Action....
DAO模式在EAS中的应用
2006年5月
DAO(DataAccessObject):
为什么使用DAO:
通过这种模式将底层数据访问操作与高层业务逻辑分离开。
底层数据访问操作包括那些:
如创建、更新或者删除数据
下图IORMappingDAO为EAS定义的DAO接口
看下DAO模式下的一个时序图
EAS中DAO接口(IORMappingDAO)的实现只有一个ORMappingDAO,它实现了对数据对象和数据库层间的增删改查的底层业务操作
数据对象的操作并没有封装在数据对象内,而是通过DAO对象来完成的,这样可以避免不同的数据对象都实现类似的数据访问操作.
关于数据对象,有不同的定义方式,有如下的把数据属性以类变量的形式出现的
publicclassCustomerimplementsjava.io.Serializable{
//membervariables
intCustomerNumber;
Stringname;
StringstreetAddress;
Stringcity;
...
//getterandsettermethods...
...
}
但EAS做法不是这样的,EAS把数据对象封装到数据Info中,数据Info实际上是封装了一个Map,通过这个Map来管理数据对象中所有类别的数据,当然获取数据和修改数据的方式还是通过setter和getter,只不过内部的实现是一个Map的数据修改和数据获取
DAO接口定义数据操作的方法,然后有具体的子类来根据不同的需要实现,可以是JDBC方式的DAO,也可以是通过O/RMapping工具的DAO
EAS学习-EAS类的体系架构
2007年12月
一个实体会生成下边几个类
业务实现:
com.kingdee.eas.fi.mipe.HouseForRent
业务接口:
com.kingdee.eas.fi.mipe.IHouseForRent
值对象:
com.kingdee.eas.fi.mipe.HouseForRentInfo
值对象集合:
com.kingdee.eas.fi.mipe.HouseForRentCollection
控制器:
com.kingdee.eas.fi.mipe.app.HouseForRentController
控制器Bean:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerBean
控制器Home:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerRemoteHome(已经作废)
控制器LocalHome:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerLocalHome(已经作废)
控制器Remote:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerRemote(已经作废)
控制器Local:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerLocal(已经作废)
其中,开发人员真正需要实现的类是com.kingdee.eas.fi.mipe.app.HouseForRentControllerBean
我们这里首先看下各个类的体系架构
1.业务实现:
com.kingdee.eas.fi.mipe.HouseForRent
HouseForRent继承于IHouseForRent,为客户端和服务端所共有,相当于一个字典,记录着服务端那些方法可以被调用
2.业务接口:
com.kingdee.eas.fi.mipe.IHouseForRent
见1
3.值对象:
com.kingdee.eas.fi.mipe.HouseForRentInfo
实际上Info是EAS构造的一个类似于HashMap的东东,用于记录Key-Value,Info和数据库表的字段有相应的对应
比如:
在HouseForRent实体中定义了一个number字段,在HouseForRentInfo中就会有
/**
*Object:
房产项目(出租)'s编码property
*/
publicbooleangetNumber()
{
returngetString("number");
}
publicvoidsetNumber(Stringitem)
{
setBoolean("number",item);
}
4.值对象集合:
com.kingdee.eas.fi.mipe.HouseForRentCollection
Info的集合
5.控制器:
com.kingdee.eas.fi.mipe.app.HouseForRentController
ControllerBean的接口
6.控制器Bean:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerBean
真正的业务实现是在这个里边的
7.控制器Home:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerRemoteHome(已经作废)
8.控制器LocalHome:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerLocalHome(已经作废)
9.控制器Remote:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerRemote(已经作废)
10.控制器Local:
com.kingdee.eas.fi.mipe.app.HouseForRentControllerLocal(已经作废)
EAS典型的服务端SQL语句
2005年9月
privatevoidfreezeCustomerOtherInfo(Contextctx,StringcustomerId)
throwsBOSException
{
Connectionconn;
StringupdateCompanySql;
Statementstatement;
conn=null;
updateCompanySql="";
StringupdateSaleSql="";
statement=null;
try
{
conn=super.getConnection(ctx);
statement=conn.createStatement();
updateCompanySql="updateT_BD_CustomerCompanyInfosetFIsTicketFreezed=1,FFreezeOrgUnitID='"+ContextUtil.getCurrentOrgUnit(ctx).getId().toString()+"'whereFCustomerId='"+customerId+"'";
statement.addBatch(updateCompanySql);
StringupdateSaleSql="updateT_BD_CustomerSaleInfosetFIsFreezeOrder=1,FIsFreezeDelivery=1,FConsignFreezeOrgUnitID='"+ContextUtil.getCurrentOrgUnit(ctx).getId().toString()+"',FOrderFreezeOrgUnitID='"+ContextUtil.getCurrentOrgUnit(ctx).getId().toString()
+"'"+"whereFCustomerId='"+customerId+"'";
statement.addBatch(updateSaleSql);
statement.executeBatch();
}
catch(SQLExceptionexc)
{
thrownewBOSException("Sqlexecuteexception:
"+updateCompanySql,exc);
}
SQLUtils.cleanup(statement);
SQLUtils.cleanup(conn);
breakMISSING_BLOCK_LABEL_222;
Exceptionexception;
exception;
SQLUtils.cleanup(statement);
SQLUtils.cleanup(conn);
throwexception;
}
EAS的两大异常--BOSExceptionEASBizException
2005年12月
BOSExceptionEASBizException
BOSException是系统级别的异常,比如,创建远程连接的时候,都会声明可能抛出这个异常
EASBizException是业务异常,基本上所有的业务异常都要求继承于这个异常,所以一般情况下服务段的业务方法都会实现先声明可能会这个异常
publicclassEASBizExceptionextendsNumericException
{
privatestaticfinalStringMAINCODE="10";
publicstaticfinalNumericExceptionSubItemCHECKTEXTLENGTH1=newNumericExceptionSubItem("10","CHECKTEXTLENGTH1");
publicstaticfinalNumericExceptionSubItemCHECKTEXTLENGTH2=newNumericExceptionSubItem("11","CHECKTEXTLENGTH2");
publicstaticfinalNumericExceptionSubItemCHECKINT=newNumericExceptionSubItem("20","CHECKINT");
publicstaticfinalNumericExceptionSubItemCHECKBLANK=newNumericExceptionSubItem("22","CHECKBLANK");
publicstaticfinalNumericExceptionSubItemCHECKDUPLICATED=newNumericExceptionSubItem("23","CHECKDUPLICATED");
publicstaticfinalNumericExceptionSubItemCHECKDUPNUMBER=newNumericExceptionSubItem("31","CHECKDupNumber");
publicstaticfinalNumericExceptionSubItemCHECKPARENTDELETED=newNumericExceptionSubItem("41","CHECKPARENTDELETED");
publicstaticfinalNumericExceptionSubItemCHECKPARENTUNEFFECTED=newNumericExceptionSubItem("42","CHECKPARENTUNEFFECTED");
publicstaticfinalNumericExceptionSubItemCHECKPARENTBEUSED=newNumericExceptionSubItem("43","CHECKPARENTBEUSED");
publicstaticfinalNumericExceptionSubItemCHECKNAMEBLANK=newNumericExceptionSubItem("221","CHECKNAMEBLANK");
publicstaticfinalNumericExceptionSubItemCHECKNUMBLANK=newNumericExceptionSubItem("222","CHECKNUMBLANK");
publicstaticfinalNumericExceptionSubItemCHECKNAMEDUP=newNumericExceptionSubItem("231","CHECKNAMEDUP");
publicstaticfinalNumericExceptionSubItemCHECKNUMDUP=newNumericExceptionSubItem("232","CHECKNUMDUP");
publicstaticfinalNumericExceptionSubItemCHECKEXIST=newNumericExceptionSubItem("321","CHECKEXIST");
publicstaticfinalNumericExceptionSubItemDBDEADLOCK=newNumericExceptionSubItem("400","DBDEADLOCK");
public