ImageVerifierCode 换一换
格式:DOC , 页数:25 ,大小:149.50KB ,
资源ID:8899114      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/8899114.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(元数据引擎设计思考.doc)为本站上传会员【s4****5z】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

元数据引擎设计思考.doc

1、java meta-date 元数据 7.2  关于元数据 系统开发中存在各种各样的数据,比如Tom是一个年龄为30岁的男性员工、Liliy是一个21岁的女性员工、这张报表是今年第三季度的利润表、那张报表是今年上半年的销售波动图、对话框上有三个按钮控件、窗口上有一个多行文本控件和一个保存按钮、这个WebService提供了股票实时情况查询的服务、那个WebService提供了查询天气预报的服务。 以上数据存在很多共性的特征,这些特性都可以通过某种形式进行抽象。 对于“Tom是一个年龄为30岁的男性员工”、“Liliy是一个21岁的女性员工”,在数据库级别就会抽象成含有FId Var

2、char(50)、FName Varchar(50)、FAge(int)、FSex(int)四个字段的数据库表T_Employee,在Hibernate中就被抽象成含有id、name、age、sex四个字段的JavaBean以及对应的hbm配置文件。 这些数据是平台无关的,在描述“Tom是一个年龄为30岁的男性员工”这条数据的时候,它即可以是保存在数据库中的,也可以是保存在XML配置文件中的,甚至有可能只是写在一张便条上的。与此相反的是,对这些数据的抽象方式大都是与特定平台相关的,是无法移植的。比如要把数据的存储方式由数据库改为XML文档,那么就必须针对XML文件的存取特点重新进行抽象。由于

3、抽象方式是平台相关的,这些抽象出来的模型就不具有通用性,无法通过统一的方式来读取它们。比如要读懂T_Employee这张表中的字段的含义就要去查阅数据字典,要读懂便条上的“Tom 30 m”就要去询问写便条的人。 元数据(MetaData)是MDA中非常重要的概念。它通过统一的、平台无关的、规范的方式对数据的模式特征进行描述,通过一个模型结构来表达通用的信息,它集设计模型、开发模型与运行模型为一体。元数据具有如下几个作用。 (1) 元数据是独立于平台的,无论使用什么技术平台,元数据本身是不受影响的,这保证了先期工作成果的效用最大化。 (2) 元数据是生成平台相关模型的基础,可以使用代码生

4、成器等工具将元数据转换成平台相关代码。 (3) 元数据为运行时系统提供了统一的可读的系统模型,系统运行时可以使得实体对象通过运行时元数据模型来得知自身的结构、自身的特征、在系统模型中的位置以及与其他对象之间的关系等。这样就可以从一个新的角度来观察、设计、开发系统。 (4) 元数据模型是系统运行不可或缺的部分,如果直接修改平台相关代码而不修改元数据,就会造成系统运行异常,这就强迫保证元数据模型与代码同步,保证了设计模型和实现代码的一致性。 (5) 元数据本身就是一个设计模型。系统设计人员可以使用元数据进行系统建模,在某种程度上元数据可以取代UML图等传统的设计模型。设计人员将设计完成的元数

5、据模型交给开发人员,开发人员使用代码生成器将元数据转换成平台相关代码,然后就可以基于这些平台相关代码进行开发了。元数据起到了设计人员和开发人员沟通桥梁的作用,设计人员的工作立即就可以转换为可以运行的平台相关代码。 7.2.1  元数据示例 枚举类型在不同的系统中有不同的表示方式,而且有不同的模型描述方式(即枚举有哪些项、项的值是多少等信息),有的平台还没有提供足够的模型描述方式。客户类型包括:普通客户、会员客户、VIP客户。 在JDK 1.5中可以表示为enum CustomerTypeEnum{Normal, Member, VIP},取得CustomerTypeEnum枚举类型中定义

6、的所有枚举项的方法为CustomerTypeEnum.values(),取得“Normal”这个字符串对应的枚举项的方法为Enum.valueOf(CustomerTypeEnum.class, "Normal")。 在JDK 1.4中使用Apache Commons包提供的Enum类可以表示为: public class CustomerTypeEnum extends mons.lang.enums.Enum {     public static DataTypeEnum Normal= new DataTypeEnum("Normal");     public static

7、 DataTypeEnum Member= new DataTypeEnum("Member");     public static DataTypeEnum VIP= new DataTypeEnum("VIP");     private DataTypeEnum(String name)     {         super(name);            } } 取得CustomerTypeEnum枚举类型中定义的所有枚举项的方法为EnumUtils.get- EnumList(CustomerTypeEnum.class),取得“Normal”这个字符串对应的枚

8、举项的方法为EnumUtils.getEnum(CustomerTypeEnum.class, "Normal")。 在C#中,可以表示为enum CustomerTypeEnum{Normal, Member, VIP},取得Customer- TypeEnum枚举类型中定义的所有枚举项的方法为Enum.GetNames(typeof(CustomerTypeEnum)),取得“Normal”这个字符串对应的枚举项的方法为Enum.Parse(typeof(CustomerTypeEnum), "Normal")。 在Delphi中,可以表示为type CustomerTypeEnum=

9、Normal, Member, VIP);没有提供取得CustomerTypeEnum枚举类型中定义的所有枚举项的方法,取得“Normal”这个字符串对应的枚举项的方法也没有直接提供,必须借助RTTI。  要将一个平台上的CustomerTypeEnum移植到另一个平台,必须用目标平台的枚举语法重新改写,而且使用的取得枚举类描述信息的方式也要发生变化,这都给系统的移植带来了很大的工作量。 【例7.1】元数据示例。 为了解决这个问题,我们设计一个元数据模型:     CustomerTypeEnum            

10、                     提供一个描述这个元数据模型的描述类: //枚举描述类 public class EnumInfo {     …     //得到所有的枚举项     public EnumItemInfo[] getEnumItems();

11、     //得到名字为name的枚举项的信息     public EnumItemInfo getEnumItem(String name);   } //枚举项描述类 public class EnumItemInfo() {     …     //枚举项的名字     public String getName();     //枚举项的显示信息     public String getDisplayName();     } 提供一个读取元数据模型的API: public class EnumMetaDataLoader {     …    

12、//加载元数据类型enumTypeName对应的元数据模型     public EnumInfo loadEnum(String enumTypeName)     {         …     } } 枚举元数据模型的描述类和读取元数据模型的API的实现代码仍然是平台相关的,因为这些类都是要被特定平台使用的。因为XML解析在各个平台是大同小异的,所以这些描述类和API的实现方式的移植是非常简单的。 使用这样的元数据模型我们还可以定义其他的枚举类型,比如:     SexEnum        

13、me="Male" displayName="男">         在JDK 1.4平台下,使用代码生成器将SexEnum的元数据模型转换成JDK 1.4下的枚举代码: public class SexEnum extends mons.lang.enums.Enum {     public static SexEnum Male= new DataTypeEnum("Male");     public static SexEnum Fe

14、male= new DataTypeEnum("Female");     private SexEnum String name)     {         super(name);            } } 当要得到所有SexEnum 定义的枚举项的时候,按如下方式调用: EnumInfo enumInfo = EnumMetaDataLoader.getInstance().loadEnum("SexEnum"); EnumItemInfo[] itemInfos = enumInfo.getgetEnumItems(); for(int i=0,n=itemIn

15、fos.length;i

16、不正常,因为没有修改SexEnum 元数据。这样就限制了开发人员直接修改SexEnum 类,这样开发人员只能去修改SexEnum 元数据,然后用代码生成器来重新生成SexEnum 类代码。这规范了开发人员的行为,保证了设计模型与实现代码的一致性。    若某一天,公司决定将开发平台从Java迁移到C#,那么对于枚举这部分需要做的改造工作就是用C#重写元数据模型描述类和元数据读取API,并开发一个针对C#枚举的元数据转换器,系统所有的枚举就都可以自动转换成C#下的了。这保证了前期对于枚举元数据模型的设计开发成本利用的最大化。 由于枚举在各个平台之间差异并不算大,而且一个平台整体从Java迁移

17、到C#的可能性也非常小,所以元数据在这里起到的作用并不大。但是在Java平台上ORM工具的迁移倒是很有可能的,要想体会元数据的更重要的作用就要看案例系统的实体元数据了。 7.2.2  元元数据 元数据是对数据共性的抽象,而不同的元数据本身也是具有共性的,以上一节的两个枚举元数据来说,客户类型枚举元数据与性别枚举元数据为共同的模式:     枚举名称                 …     可以定义

18、一种模型来描述所有枚举元数据的共性特征,也就是枚举元数据的元数据(Metadata of metadata)。这种对元数据进行抽象描述的形式被称为元元数据(MetaMetaData)。 7.2.3  设计时与运行时 元数据的直接表示形式被称为设计时元数据,而在运行的时候能被系统读取的形式(比如上边的EnumInfo)被称为运行时元数据。通常,运行时元数据描述的特性是设计时元数据的特性的子集。 系统承担着设计模型与运行时模型的多重责任,而且元数据还作为代码生成器的“源”,承载着描述目标代码的作用。这些责任之间有相交的部分,也有自己独特的部分。举例来说,一个描述实体对象的元数据,它描述这个实

19、体对象有哪些字段、字段的类型是什么、和其他实体对象之间有什么关系等信息,而作为代码生成器的“源”,它还要描述一些目标平台特有的东西,比如当目标平台为Hibernate的时候,就需要指定主键字段的生成策略、关联字段的LazyLoad策略、Casade策略等。从严格意义上来讲,为了维持元数据的平台无关性,这些平台相关的特性是不能放在元数据中的,而应该放在一个描述平台相关属性的地方,不过这样就使得元数据模型过于复杂。一个较好的策略是在元数据中增加一个专门存放这些平台相关属性的区域。       运行时的元数据是要被平台相关代码访问的,如果运行时元数据中包含平台相关特性的话,就会导致以后平台移植难度

20、加大,而且也混淆了设计时语义与运行时语义之间的界限。所以运行时的元数据中一定不能包含平台相关特性。 7.2.4  元数据设计的基本原则 除了上边提到的运行时的元数据中一定不能包含平台相关特性之外,在元数据的设计中,“适可而止”也是需要铭记在心的核心原则。对元数据描述的范围要适可而止,不要试图包罗万象。运行时元数据是能够给运行时的系统提供元数据的信息的,这在一定程度上简化了系统的开发,但是切不可把应该写在代码中或者写到配置文件中的信息写到元数据中。比如在实体对象元数据中,给字段增加了“allowNull”特性来表示此字段是否允许为空。系统保存实体对象的时候,可以读取此实体对象对应的元数据,进

21、而取得所有字段的是否为空的特性,从而对数据进行校验。这是对运行时元数据非常合理的运用。但是如果试图把字段为空时提示什么样的信息、字段最大长度是多少、字段是否进行加密操作等特性加入元数据的话就会使得元数据模型过于庞大,这也违反了“适可而止”这一基本原则。如果元数据直接驱动系统的运行过程,并且有取代程序代码的趋势的话,就说明设计人员对元数据概念理解错误了,用元数据驱动系统运行虽然减少了代码的编写,但是这些本不应该放在元数据中的特性是不完备的,一旦需要扩展就会遇到难以逾越的鸿沟。 由于客户需求的复杂性,模型结构不能表达出所有业务的处理过程,仍然存在需要利用编程语言才能完成的业务功能。元数据模型解决

22、大多数通用的问题,而对于具有差异性的问题还是要通过编码来完成的,不应该让运行时元数据承担过多的运行时语义。 7.2.5  此“元数据”非彼“元数据” 元数据这个词汇并不是MDA发明的,在其他领域“元数据”早已经被使用了,在软件开发领域,“元数据”也不是MDA中才有的。 JDK 5.0的annotation机制也被称为元数据,它为属性的物理驻留位置提供了新的选择。annotation使得代码具有自解释的能力,代码变成能同时提供行为及自我描述能力的实体,也就是说代码从一维变成二维的了。使用JDK提供的API就可以从代码中读取到这些描述信息。 /** *@ filedName = "FNa

23、me" type = "Varchar(44)" */ public String getName(){…} 这段代码中类似JavaDoc的东西就是annotation,它描述了name这个属性对应着数据库中的类型为“Varchar(44)”名称为“FName”的字段。Hibernate3、EJB3都推荐并且支持这种方式。 在Hibernate本身也有元数据机制,在Hibernate的包org.hibernate.metadata中的类就是提供元数据支持的API,通过它们能读取到一个实体对象有哪些字段、字段的类型是什么、是否允许为空、是否关联其他的实体对象等。 JDK的annotat

24、ion、Hibernate中的元数据都符合元数据的定义,它们也是真正的元数据。它们与MDA中的元数据的最主要区别就是是否具有平台无关性。很显然JDK的annotation、Hibernate中的元数据都不能脱离它们所依赖的平台,元数据中有很多描述平台专有属性的东西,无法作为一个跨平台的元数据引擎使用。不过这些元数据能反应平台的更多的细节,如果合理利用将极大地提高开发效率。在后边关于HibernateDTOGenerator的分析中读者将会看到我们是如何使用Hibernate的元数据来实现DTO产生器的。 图7.4  元数据编辑器 (5) 单击add按钮增加id字段,在如图7.5所示的属

25、性视图中编辑字段属性。 图7.5  属性视图 (6) 按照同样方式增加number、name字段。 在PrimaryKey下拉列表框中选择id作为主键。然后单击Eclipse的保存图标完成商品元数据的建模。 按照同样的步骤建立SaleBill实体元数据,增加id、number、saleDate属性。在增加saler属性的时候,此属性关联着系统中已经建立的Person元数据,因此设置isLinkProperty为true,设置完毕后属性视图中的属性比普通属性多了一些内容,主要是linkEntity、linkType、casadeType等。单击linkEntity属性右边的浏览按钮,

26、如图7.6所示,选择系统中已经定义好的“Person元数据”。 选择linkType属性为MANYTOONE。SaleBillDetail元数据没有建立,所以暂时不增加details属性。 (7) 按照同样步骤增加“SaleBillDetail”实体元数据。 回到SaleBill实体元数据编辑界面,增加details属性,设置linkedEntity指向SaleBillDetail实体,设定linkType属性为OneToMany,从keycolumn属性的下拉列表框中选择FHeadId属性,表示SaleBillDetail实体通过FHeadId字段指向SaleBill实体。   图

27、7.6  选择关联元数据 (8) 建模完毕,下面开始生成代码和配置文件。同时选中Goods.emf、SaleBill.emf、SaleBillDetail.emf三个文件,右击,在弹出的快捷菜单中选择CownewStudio∣Generate Code from Model File命令,弹出如图7.7所示的界面。 图7.7  代码生成选项 (9) Target ORM为生成的文件对应的ORM类型,目前支持Hibernate2和Hibernate3。按照图7.7进行设置,单击【完成】按钮,然后在Eclipse中就可以看到生成的文件了,如图7.8所示。hbm配置文件生成在bizLaye

28、r包下,JavaBean生成在common包下。 前边介绍了元数据在系统设计和平台相关代码生成中的应用,本节介绍元数据的运行时模型,这部分也是整个元数据中最复杂的部分。 7.4.1  实体元数据运行时模型 元数据中定义了很多丰富的属性,但并不是元数据所有的属性都对运行时系统有用,而且有的属性也不应该放到运行时模型中,图7.9是运行时的元数据模型。 图7.9  运行时的元数据模型 DataTypeEnum是数据类型枚举,LinkTypeEnum是关联类型枚举,EntityFieldModelInfo为实体字段模型,EntityModelInfo为整体的实体元数据模型。可以看到实体字

29、段模型中去掉了实体元数据中的“CascadeType”、“Constrained”、“Inverse”等属性,这些字段是Hibernate平台特有的,所以是不能放到运行时模型中的。 为了解析元数据文件以生成运行时元数据模型,我们开发了元数据解析器类EntityMetaDataParser(在包com.cownew.PISmon.metaDataMgr下),此类对外提供了一个静态方法:public static EntityModelInfo xmlToBean(Document doc)。将元数据XML文件的Dom4j对象Document 作为参数调用,返回值就是这个实体元数据的模型Enti

30、tyModelInfo。因为XML文件中包含运行时元数据模型不需要的东西,所以此处不能使用XStream等OXMapping工具,而是使用Dom4j完成XML的解析。 7.4.2  分包及命名规范 在多层架构中,各个层之间有自己独立的不应被其他层访问的类,也有在层之间共享的类。对这些不同共享层次的类进行分包可以保证清晰的系统分层,也可以简化各层的配置安装。在案例系统中分为4种包:应用服务器包、Swing Client端包,Web Client端包,公共包。比如,有一个提供天气预报服务的Remoting Service,定义了服务接口IWeatherForecast,此服务接口是应用服务器、

31、Swing Client、Web Client都要访问的,所以要将它放到公共包中;此接口的实现类WeatherForecastImpl只有应用服务器需要,因此定义在应用服务器包中;如果编写了一个Swing客户端WeatherForecastUI访问此服务,WeatherForecastUI就要定义在Swing Client端包中;如果编写一个Web页面,此页面有WeatherForecastForm和WeatherForecastAction两个类,这两个类就要放到Web Client端包中。在案例系统中,应用服务器包命名为bizLayer、 为了简化系统的开发及规范文件管理,案例系统对文件

32、目录结构做了如下约定,如果实体元数据DemoEntity的名称(name)为DemoEntity,包名(packageName)为com.cownew. Demo,那么: l   生成的hbm配置文件DemoEntity.hbm.xml保存在com.cownew.Demo.bizLayer目录下。 l   生成的JavaBean文件必须以实体名加“Info”命名,即DemoEntityInfo.java,它保存在com.cownew.Dmon目录下。 l   此实体对应的DAO实现接口IDemoEntityDAO保存在com.cownew.Demo.bizLayer目录下。 l   此

33、实体对应的DAO实现类DemoEntityDAOImpl保存在com.cownew.Demo.bizLayer目录下。 l   访问此接口的Swing客户端文件保存在com.cownew.Demo.client目录下。 l   访问此接口的Web端源码保存在com.cownew.Demo.web目录下。 前三条是必须遵守的规范,其他是建议遵守的规范。 系统运行时可能需要根据实体的JavaBean得到其对应的接口或者根据元数据的位置得知接口的位置,只要根据上述规则就可以在JavaBean、接口、元数据之间互相转换。为了简化此操作,系统提供了一个工具类NameUtils,位于包com.co

34、wnew.PIS. mon.metaDataMgr下,各个方法的作用如下。 l   public static String getVOClassName(String entityPath):将实体路径名转化为VO类名,比如getVOClassName("/com/cownew/Person.emf")将返回“mon. PersonInfo ”。 l   public static String getPackageName(String entityPath):从实体路径名得到包路径名,比如getPackageName("/com/cownew/Person.emf")将返回“com.

35、cownew”。 l   public static String getEntityName(String entityPath):从实体路径名得到实体名,比如getEntityName("/com/cownew/Person.emf")将返回“Person”。 l   public static String getEntityPath(String infoClassName):将VO类名转化为实体路径名,比如getEntityPath("mon.PersonInfo")将会返回“/com/cownew/ Person.emf”。 7.4.3  元数据加载器接口 元数据加载器最基

36、本的功能就是根据给出的元数据路径返回对应的元数据运行时模型,比如调用者想得到“人员”元数据运行时模型,只要将“/com/cownew/PIS/basedata/ Person.emf”作为参数传递给元数据加载器,加载器就可以返回对应于“人员”的EntityModelInfo类的实例。 为了方便调用,元数据加载器还提供一些辅助功能,比如根据VO类加载元数据、根据VO类名加载元数据、一次性加载系统中所有的元数据模型。元数据的解析是非常耗时且耗用内存的,最好提供元数据缓存以及缓存的持久化功能。 【例7.3】设计元数据加载器接口。 代码如下: // 元数据加载器接口 public inter

37、face IMetaDataLoader {     /**      * 根据元数据路径加载元数据运行时模型      */     public EntityModelInfo loadEntityByEntityPath(String path) throws          MetaDataException;         /**      * 根据VO类加载元数据运行时模型      */     public EntityModelInfo loadEntityByVOClass(Class voClass) throws          MetaD

38、ataException;         /**      * 根据VO类名加载元数据运行时模型      */     public EntityModelInfo loadEntityByVOClass(String voClass) throws          MetaDataException;         /**      * 加载所有的实体元数据的path,List中元素的类型为String      */     public List loadAllEntityPath() throws MetaDataException;        

39、/**      * 保存元数据缓存      */     public void saveCache(); } 7.4.4  元数据热部署 元数据的热部署指的是当对元数据进行修改以后,无须重启服务器就能在系统中得到修改以后的运行时元数据模型。元数据的热部署功能主要是考虑到应用服务器的启动过程以及Spring、Hibernate等的初始化过程都是需要一定的时间的,如果开发人员每次对元数据进行修改都需要重启服务器就会降低开发效率。 7.4.5  元数据部署方式 元数据在系统中存在的方式可以有3种:①元数据和.class二进制字节码文件放到一起;②把metadata文件夹直接放到

40、系统的目录下;③把所有元数据单独打包成一个jar文件。 元数据是和二进制字节码文件用途不同的文件,如果将它们混放则不利于管理,第一种方式很自然地被否决了。 第二种方式将元数据单独管理,比第一种方式具有优势。当元数据数量变多以后,metadata文件夹占据的空间也会变大,从文件夹中检索文件的速度也会较慢。 第三种方式将元数据打包,减小了元数据占据的空间并且加快了文件的检索速度。但是在开发环境中采用此方式的话,开发人员每次新增、删除或者修改元数据以后都要对元数据重新打包,这是非常低效和不现实的。 为了同时兼顾开发环境和运行环境的要求,元数据引擎将同时支持第二、第三种方式。当处于开发环境时就

41、采用第三种方式,当处于正式运行环境的时候则采用第二种方式。具体采用哪种方式可以在配置文件中配置。 为了提高元数据的加载速度,元数据在客户端和服务器端各存在一份,并且客户端和服务器端都有自己的元数据加载器实例。 7.5  元数据引擎实现 前面我们设计了元数据引擎,这一节将看一下元数据引擎的具体实现。 7.5.1  根据元数据路径加载元数据 IMetaDataLoader接口中定义了根据元数据路径加载元数据运行时模型的方法public EntityModelInfo loadEntityByEntityPath(String path),实现此方法有两种思路: l   编写一个专用的文

42、件加载器,可以按照元数据路径从文件夹(开发环境部署模式)或者Jar文件(正式运行环境部署模式)中加载元数据文件,然后再对元数据文件进行解析。 l   将元数据所在的文件夹(开发环境部署模式)或者jar文件(正式运行环境部署模式)放入类路径(ClassPath)中,这样在程序中就可以通过getClass().getResource- AsStream("/com/cownew/PIS/demo/Person.emf")这样的方式来加载元数据文件了。 很显然,第二种方式实现起来最简单,所以在系统中将元数据所在的文件夹或者jar文件放入类路径(ClassPath)中。 7.5.2  元数据枚举

43、器 IMetaDataLoader接口中定义了加载所有的实体元数据的path的方法public List loadAllEntityPath()。JDK没有提供枚举类路径中某一类文件的方法,我们必须开发这样的功能,我们称其为元数据枚举器。其接口定义如下: public interface IMetaDataEnumerator {     public List listAll(); } 接口只定义了一个listAll方法,它返回所有的元数据的路径列表。 元数据有文件夹和Jar文件两种部署模式,为了同时支持这两种方式的元数据枚举,可以编写一个元数据枚举器,在这个枚举器的listA

44、ll方法中判断是哪种部署模型,然后进行不同的处理。这样实现违背了面向对象开发的基本原则,应该将这两种不同的行为分别都定义在不同的枚举器中:DirectoryMetaDataEnumerator类负责在文件夹中进行元数据枚举,而JarFileMetaDataEnumerator类负责在Jar文件中进行元数据枚举。 【例7.4】元数据枚举器抽象类。 为了抽象出这两种枚举器的公共行为,首先编写一个实现了IMetaDataEnumerator接口的抽象类AbstractMetaDataEnumerator: // 元数据枚举器抽象类 public abstract class Abstract

45、MetaDataEnumerator implements IMetaDataEnumerator {     protected List list;     public List listAll()     {         // 进行惰性初始化处理,子类是要实现fillList方法,         // 在这个方法中向list中填充元数据路径即可,不用管惰性初始化问题         if (list == null)         {             fillList();         }         return list;    

46、}     protected abstract void fillList(); } 抽象类中进行了惰性初始化处理,子类只要实现fillList方法即可。 【例7.5】Jar文件元数据枚举器。 接着编写从AbstractMetaDataEnumerator继承的JarFileMetaDataEnumerator类: // Jar文件元数据枚举器 import java.util.ArrayList; import java.util.Enumeration; import java.util.jar.JarFile; public class JarFileMetaDat

47、aEnumerator extends AbstractMetaDataEnumerator {     protected JarFile jarFile;     protected String suffix;         public JarFileMetaDataEnumerator(JarFile jarFile, String suffix)     {         super();         this.jarFile = jarFile;         this.suffix = suffix;     }     public void

48、fillList()     {         list = new ArrayList();         Enumeration entries = jarFile.entries();         while (entries.hasMoreElements())         {             Object obj = entries.nextElement();             String e = obj.toString();             if (e.endsWith(suffix))             {    

49、             list.add("/" + e);             }         }     } } JarFileMetaDataEnumerator 的构造函数接受两个参数jarFile为元数据所在的Jar包,suffix为待匹配文件的扩展名,一般传递“.emf”。 通过JarFile 类的public Enumeration entries()方法即可得到遍历Jar文件中所有文件的枚举器,在遍历文件过程中判断文件扩展名,若等于suffix的话,就认为它是元数据文件。 【例7.6】目录元数据枚举器。 接着编写目录元数据枚举器,代码如下: // 目录元数据枚举器 public class DirectoryMetaDataEnumerator extends AbstractMetaDataEnumerator {     private File dir;     private String suffix;     public DirectoryMetaDataEnumerator(File dir, String suffix)     {

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服