资源位置:
资源门面位置的字符串类似于URL的构成方式:协议,主机,可选端口和文件名。它支持标准的java URL协议(http https ftp jar file).同样也支持一些扩展的协议:
- classpath:// java类路径的资源
- content://内容仓库的资源(JCR 经由Jackrabbit客户端):路径中协议前缀后的第一个元素是内容仓库的名称,其在Moqui的XML配置文件中被repository.name属性指定。
- component://相对于组件所在位置的路径。无论组件位于何处(文件系统,,内容仓库等)
- dbresource://由于一个虚拟的文件系统,通过moqui.resource.DbResource和DbResourceFile实体在数据库中持久化实体门面。
其他的协议可以通过实现org.moqui.context.ResourceReference接口,并添加一个resource-facade.resource-reference元素到Moqui XML配置文件来完成。
已经支持的协议配置在MoquiDefaultConf.xml文件中。
使用资源
按照已支持的协议使用一个资源,就是直接去读取文本或者二进制内容。从一个资源位置获得文本使用ec.resource.getLocationText(String location,boolean cache)方法。获取二进制输入流或者大文本资源使用ec.resource.getLocationStream(String location).
除了直接读取资源,还有相当多的操作可以使用ec.resource.getLocationReference(String location)方法获得org.moqui.context.ResourceReference接口的一个实例,这个接口类似于资源门面方法一样,有从资源中获取文本和二进制流数据的一些方法。接口还有一些方法用于目录资源获得下级资源,按照名称递归查找所有下级文件或目录,写文本或者二进制流数据以及移动资源到其他的位置。
模板渲染和运行脚本
单独的方法去渲染某个资源路径下的模板:
ec.resource.renderTemplateInCurrentContext(String location,Writer writer).这个方法不返回任何东西,只是简单的输出模板到writer,。默认支持FTL(Freemaker Template Language)和Gstring(Grovvy String)模板。
其他的模板可通过实现org.moqui.context.TemplateReader接口,并在Moqui XML配置文件中添加resource-facade.template-renderer元素来完成。
通过资源门面运行脚本使用Object ec.resource.runScriptCurrentContext(String location,String method)方法。脚本的位置以及脚本中要运行的方法作为指定的入参,将会返回脚本对应的方法返回值或者计算结果的Object对象。在资源门面中这个方法还有变异的用法,它可以方便的接受一个Map类型的additionalContext参数。通过javax.script.ScriptEngineManager.Moqui框架默认支持Grovvy XML动作,javascript以及任意脚本引擎支持的脚本。
添加脚本执行器的方法:
1.javax.script的方式为任何脚本语言去实现javax.script.ScripeEngine接口,并可以通过javax.script.ScriptEngineManager去发现脚本。Moaui框架就是使用这种扩展方式,基于脚本的文件名去发现将会编译脚本,并为了在一个给定的位置更快速的反复执行一个脚本,以编译的形式缓存脚本。
2.实现org.moqui.context.ScriptRunner接口,并在MoquiXML配置文件中添加一个resource-facade.script-runner元素节点,Moqui框架通过这个接口使用Grovvy的XML操作是因为他提供了额外的便利性,但通过javax.script接口无法使用。
由于Grovvy是Moaui框架中默认的表达式语言,这里有一些资源门面的方法可用于简单的不同目的的表达式计算:
- boolean evaluateCondition(String expression ,String debugLocation)用于计算一个Grovvy条件表达式并返回bolean结果。
- Object evaluateCondition(String expression ,String debugLocation)用于计算表达式返回上下文中的一个字段,通常更多的用于计算人额好Grovvy表达式并返回结果。
- String evaluateCondition(String expression ,String debugLocation)用于扩展输入的字符串,将其当成一个GString(Grovvy String)并返回扩展后的字符串
都接受了一个debugLocation参数用于处理错误信息。为了计算速度,这些都被缓存起来了。
数据模型定义:
<entity entity-name="DataSource" package-name="moqui.basic" cache="true"> <field name="dataSourceId" type="id" is-pk="true"/> <field name="dataSourceTypeEnumId" type="id" /> <field name="description" type="text-medium" /> <relationship type="one" title="DataSourceType" related-entity-name="Enumeration"> <key-map field-name="dataSourceTypeEnumId"/> </relationship> <seed-data> <moqui.basic.EnumerationType description="Purchased Data " enumTypeId="DataSourceType" enumId="DST_PURCHASED_DATA"/> <moqui.basic.EnumerationType description="Data Source Type" enumTypeId="DataSourceType"/> </seed-data> </entity>
就像一个java类,实体有一个包名,实体的全名就是包名加上实体名,${package-name}.${entity-name}
基于这种模式,实体的全名就是:moqui.basic.DataSource
这个例子中有个entity.cache属性设置为true,这意味着实体将会被缓存,除非代码另外指定去查找。
第一个字段(dataSourceId)的is-pk属性设置为true,意味着这个字段是实体的其中一个主键字段。
第三个字段(description)是一个用于保存数据的简单字段,它不是主键的一部分,并且也不是起亚实体的外键。
field.tyoe用于指定字段的数据类型,MoquiDefaultConf.xml文件中通过database-list-dictionary-type元素定义了默认的选项。这些元素为每个字典类型都指定了默认的类型设置,并且可以使用database.database-type元素为每种数据库去重新定义覆盖类型的设置。
第二个字段(dataSourceTypeEnumId)是枚举实体的外键,通过实体定义中的relationship元素来表示。seed-data元素下的两条记录里定义了枚举类型(EnumerationType)去组成枚举(Enumeration)选项,并且其中一个枚举选项是为dataSourceTypeEnumId字段设置的。seed-data元素下的记录通过seed类型使用命令行的load操作进行加载。
这里有个很重要的模式,允许框架知道使用哪个枚举类型enumTypeId来自动生成的表单中过滤一个字段的枚举Enumeration选项,注意relationship.title属性的值匹配enumTypeId.换句话说,无论如何对于枚举来说这里有这个约定:relationship.title的值就是类型的ID用来过滤下拉列表。
本例中有一个key-map元素位于relationship元素下面,这仅对于这个实体的字段名称和相应的关联实体的字段名称不匹配才需要。由于外键字段名字是dataSourceTypeEnumId而不是简单的enumId,所以我们需要告诉框架使用哪个字段去关联。框架知道关联实体的主键字段,但除非字段的名称匹配主键字段的名称,否则框架不知道实体的哪些西段对应哪些字段。
可以不适用key-map元素。简单的如下使用
<relationship type="one" related-entity-name="Enumeration"/>
seed-data元素允许你定义使用实体式必要的一些基本数据,并且也可以定义数据模型的一个方面,这些记录通过在entity-facade-xml文件中将type属性设置为seed,来呗加载到数据库中。
<entity-facade-xml type="seed"> <Tutorial tutorialId="TestOne" description="Test one description"/> <Tutorial tutorialId="TestTwo" description="Test two description"/> </entity-facade-xml>
其他实体属性:
group-name:实体门面(entity-facade)用来将一个实体为某个数据库放入分组中,所有数据库都可用。这个值应当匹配Moqio xml配置文件 中的moqui-conf.entoty-facade.datasource.group-name元素。如果没有值被指定,那么将使用默认的moqui-conf.entity-facade.default-group-name元素的值。配置默认可用的值包括:transaction(默认的),analytical,tenantcommon以及nosql.
sequence-bank-size:保存在内训中的序列储库的大小。每当在SequenceValueItem记录中的序列号seqNum被序列中的储库消耗完了,将按照这个数量进行增加。
sequence-primary-stagger:最大数量的交错就是序列ID。入伙增长序列为1则会增加1,此外,当前的序列号ID还可以按照一个1和最大间隔之间的随机数来进行增长
sequence-secondeondary-padded-length:如果能指定了前垫部分,后面都以零进行填充到本属性指定的长度默认的长度为2.
optimistic-lock:当设置为true,实体门面在更新记录时,会比较在内存中的lastUpdateStamp字段和数据库中相同的字段,如果时间戳不匹配那么就会产生一个错误,默认为false。
no-update-stamp:实体门面默认为每个实体添加一个字段用于乐观锁机制以及数据同步。如果不想创建可设置为false
cache:可以设置以下值,默认为false
true:使用缓存查找-代码可覆盖
false:不要缓存查找-代码可覆盖
never:不要缓存查找-代码不可覆盖
authorize-skip:能设置以下值:默认为false
true:掠过这个实体所有的权限校验
false:不掠过权限校验
create:为新建操作掠过权限校验
view: 为查询和只读操作掠过权限校验
view-create:为查询和新建操作略过权限校验
其他字段属性:
encrypt:当设置为true时,在数据库加密该字段。默认为false
enable-audit-log:设置为true时,将日志记录本字段的所有变化及变化时间和修改人。日志数据记录在EntityAuditLog实体中。默认为false。
enable-localization:当实体属性被设置为itrue,获取本字段值时将会同时查看LocalizsdEntityField实体。如果其中有匹配的记录,那么将返回本地化的记录而不是原始记录。由于展现的原因默认为false,只有当字段属性设置为true时才会进行翻译。
实体扩展-XML
实体可以无需修改原来额实体定义XML文件来进行扩展。尤其当你想在不同的组件中扩展例如地幔通用数据模型或甚至Moqui框架中的实体的一部分,并且保持你的扩展部分相对独立,这种方式就特别的有用。
可以在实体定义XML文件中使用extend-entity元素并可以混合使用entity元素去达到效果。这个元素拥有和entity元素很多的相同的属性去定义扩展原来的实体,简单的保证entity-name以及package-name属性和原来的entity实体元素的属性一致,
实体扩展-DB
可以使用UserField实体通过数据库记录来扩展实体,这种方式和通过extend-entity XML元素扩展实体有些不同,因为这种方式是一种虚拟的扩展,并且数据存入了独立的UserFieldValue实体数据结构中。
这种差异的主要原因就是通常添加的用户字段是为了一组用户还是单个用户,以及除了本组用户,关联的外部用户无法访问。你可以使用ALL-USERS用户组来使一个用户字段作用于所有的用户。
尽管在后台运行,但是EntityValue对象用实体对待其他任何字段一样的方式去处理这些字段,
Eample中的例子:
<moqui.entity.UserField entityName="moqui.example.Example" fieldName="testUserField" userGroupId="ALL_USERS" fieldType="text-long" enableAuditLog="Y" enableLocalization="N" encrypt="N"/>