运行时目录以及Moqui的xml配置文件
Moqui框架部署运行主要有三个核心部分:
可执行的war包文件
运行时目录
Moqui配置文件XML格式
不管怎么使用这个可执行的war文件,你必须拥有一个运行时的目录,同时你也许会重写Moqui默认配置文件MoquiDefaultConf.xml里的配置信息,例如在运行时目录或者conf目录中的MoquiProductionConf.xml文件里面重写。
运行时目录主要防止的是你想要的组建/应用系统的入口文件以及配置文件。同时,框架会在这个目录下存放日志文件,Derby数据库文件。
运行时,需要指定如下两个属性:
可执行的WAR文件:
运行时配置moqui.runtime和moqui.conf属性的例子来源于编译路径下的MoquiInit.properties文件/
在WAR文件中内嵌运行时目录:
Moqui框架能够运行加载一个外部的运行时目录,也支持运行时目录打包在WAR文件内部的方式。内嵌的方式特别适用于类似Amazon ElasticBeanstalk这种WAR部署方式的容器。创建一个内嵌运行时目录的WAR文件:
编译Moqui框架:
使用自动编译工具Gradle去编译源码
在gradle里面,加载load和运行run都依赖于构建build任务。由于这种依赖存在。最简单的方式去在一个流行的数据库上创建一个新的开发环境可以通过执行这个命令:$gradle load run
数据库配置:
数据库的安装配置已经在Moqui框架的XML配置文件的moqui-conf.entity-facade.datasource元素中完成。这里有个元素用来为每个实体分组使用,并且datasource.group-name属性与entity.group-name属性想对应匹配
默认的Apache Derby数据库配置:
Moqui代码中一些常用的表达式:
作为web请求(HttpServletRequest)的一部分,一个创建的ExecutionContext实例有一个特殊的门面叫做web门面。这个门面用于访问上下文的servlet环境信息,包括请求,响应,绘画以及应用(ServletContext).它同样用于访问servlet环境中各个部分的状态(属性),包括请求参数,请求属性,会话属性和应用属性。
web参数:
请求参数“map”(ec.web.request.Parameters)是一个特别的map,它包含了源于URL参数字符串的承诺书,内联URL参数,以及源自提交的多个部分。这里还有个特殊的参数,ap(ec.web.parameters),它按照以下的顺序将所有的map组合在一起:请求参数,应用属性,回话属性和请求属性。参数map类似于上下文是一个请求属性map的栈,所以如果你要对其进行写入,数值将会放在栈的顶部。
为了安全的因素,请求参数map使用OWASP WSAPI类库进行规范化转换以及过滤。它和服务门面校验一起有助于防止跨站脚本攻击(XSS)和注入攻击。
工厂,Servlet&监听器:
执行上下文实例通过执行上下文工厂(Execution Context Factory)进行创建,当有需要的时候可以直接通过编码的方式直接其创建,但通常都是通过Moqui框架锁运行的容器去创建。
在部署Moqui项目的时候。Moqui的跟web应用都会被加载,冰球WEB-INF目录下的web.xml文件会告诉你servlet容器去加载MoquiServlet MoquiSessionListener 和MoquiContextListener。这些都是框架中包含的末人类,并且如果要改变ExecutionContextFactory和ExecutionContext的生命周期,可以创建自己的类。
MoquiContextListener在contextInitialized()事件中创建了ExecutionContextFactory对象,并在contextDestroyed()事件中销毁它/MoquiServlet的工厂为每个请求在doGet()和doPost()方法中创建了ExecutionContext对象,同时在每个请求的最后,使用相同的方法去销毁这个对象。
资源和缓存门面:
资源门面用于访问和执行资源。例如脚本,模板和内容。缓存门面用于缓存上的常规操作,并作为一个缓存Cache接口的实现去获取一个缓存的属性。与支持的基本get/put/remove等操作在一起,你可以获得每个缓存的统计以及修改缓存的属性,例如超时,大小限制以及清理算法。默认的缓存界面实现就是ehcache的一个封装,除了在MoquiXML配置文件中队缓存门面进行配置,你可以使用ehcache.xml文件进行额外的配置选项。
资源门面使用缓存门面按照文件源的位置(通过getLocationText()方法获得)去获得缓存纯文本,通过路径位置去编译Grovvy和XML动作脚本(使用runScriptCurrentContext里的方法),以及同样通过路径位置去编译FreeMaker(FTL)模板(通过readerTemplateCurrentContext()方法)。
同样有缓存用于贯穿在界面XML和表单定义中的分散的小型Groovy表达式,冰球缓存以表达式实际的文本作为键而不是表达式来源的位置(通过evaluateCondition(),evaluateContextField()和evaluateStringExpand()方法)。
为了更通用的资源访问,getLocationReference()方法返回一个ResourceReference接口的实现。它可以用于读取资源内容(包括文件和目录),并获得关于内容类型,最后修改时间及其所在的位置等信息。框架生育的部分使用这些资源引用以一种通用的扩展的方式去访问资源。ResourceReference接口可以按需进行实现,并且一存在的默认实现包含了后面的协议/*:http https file ftp jar classpath component以及content。
界面门面:
界面门面的API主要就是充当了ScreenRender接口实现的工厂。通过ScreenRender接口你可以在各种上下文中渲染界面,最常见的就是在服务中不依赖Servlet容器进行渲染,或使用便利的ScreenRender.render(request,response)方法在响应一个HttpServletRequest请求时进行呈现。
通常进行渲染时,将指定根界面的位置来渲染根界面,同时可选的指定一个子界面路径去渲染自界面。对于web请求来说,自界面的路径就是简单的pathinfo请求
界面定义:
在界面定义的XML文件中。每个界面都可以指定web设置,参数,响应转换,子界面,展现前动作以及部件。部件包括子界面菜单/激活/面板。截面,rom后期,容器面板,指定渲染式模式的内容(html xml csv text xsl-fo等)以及表单。
表单分为:单个表单和列表表单。虽然界面表单主要定义在界面XML中,但是他们同样也可以使用DbForm和关联实体去为不同的用户组进行扩展。
基于服务auto-fields-service元素的表单非常重要的一点是,各种客户端的校验基于服务中与表单字段相关的校验定义,将会被自动的添加。
界面/表单渲染模板
ScreenReader的输出,通过为界面和表单定义的XML元素而运行的宏定义模板创建。如果模板是通过ScreenReader.macroTemplate()方法指定的,那么他将会被使用,否则模板的呈现将决定于渲染模式renderMode,以及Moqui XML配置文件中的screen-facade.screen-text-output元素配置。你可以创建自己的模板去覆盖默认模板或简单的忽略他们,同时在Moqui XML配置文件中配置他们来获得你想要的输出
服务门面:
服务门面通过大量的同步的,异步的,计划的以及特殊的服务调用接口取调用服务。
服务命名:
服务命名由三部分组成:路径,动词和名词。当引用一个服务时,他们的组合形式为:"${path}.${verb}#${noun}",路径应当是一个java包分割的路径,例如org.moqui.impl.UserServices指的就是文件classpath://service/org/moqui/impl/UserServices/xml.虽然指定路径的方式有点不方便,但是它更易于去组织服务,基于服务的调用去找到定义,并提供性能以及进行缓存(懒加载)
服务定义文件将会给予框架的位置模式路劲被查找到:"classpath://service/$1"和"component://.*/service/$1"这里的$1就是路径,"."会被转换为'/',同时在路径的最后加上".xml"
服务名称的动词(必须项)和名称(可选项)部分分割开来是为了跟呵呵的描述服务做什么和服务执行在哪个实体上
服务门面唯一的基于实体定义支持CrUD操作。使用这些实体隐士服务需要使用由一个无路径的,一个增加/修改/删除的名词,一个哈希(#)标识,以及实体的名字锁组成的服务名称。例如更新一条UserAccount的记录使用的服务名称为update#UserAccount。当定义实体自动entity-auto服务时,名词必须为实体的名称,同时服务门面将会使用出入参及实体定义去觉得做什么
完整服务的名称:org.moqui.impl.UserServices.update#UserAccount
实体门面:
用于普通的数据库交互,包括新增/修改/删除以及查找操作,以及用于更专门的操作,如加载和创建视图XML数据文件。。虽然 这些操作 是通用 的并覆盖了 典型 应用中大 部分的数据库交互需求 ,但有时 ,你需要底层访问 你可以通过 你可以通过 Moqui XML配置文件中 基于 entity facade数据库配置 的实体门面来获得一个 获得一个 JDBC连接对象。
尸体相当于数据库中的表,并主要被定义在XML文件中。这些定义包含了罗列实体中的字段,实体间的关系,指定索引等。实体可以使用UserField及其关联实体的数据库记录来进行扩展。
每天单条记录都通过EntityValue接口的实例来表现。这个接口为了方便起见扩展了M ap的接口,同时添加了额外的方法用于获得指定的数据集合,例如主键值。接口通用有用于数据库交互的方法对指定记录进行增删改查,获取/设置主/次要序列ID值,以及基于实体定义里的关联关系去查找关联记录。使用EntityFacade.makeValue()方法去创建一条新的EntityValue对象,大部分的时候会通过查询获得EntityValue实例。
使用EntityValue接口进行实体记录的查询。通过EntityFacade.makeFind()方法获得这个接口的实例。这个查询接口允许为查询设置各种的条件(用于where和having关键字,更多边界的方法用于where)指定选择的字段和排序字段,设置偏移和限制数值,以及包括使用缓存,更新及去重的标记。一旦操作设置完成,你就可以调用方法进行实际的欻性能,包括one() list() iterator() count() updateAll()以及deleteAll()
多租户:
当从执行上下文ExecutionContext中获得一个实体门面EntityFacade实例时,这个重新取回的实例将会用于当前上下文ExecutionContext(它将在指定的用户认证之前或通过servlet,亦或是请求执行前的监听器去进行设置)中活跃的租户tenantld如果没有tenantld实体门面EntityFacade江湖用于默认的DEFAULT租户使用MoquiXML配置文件中的设置,否则,它将会使用活跃的tenantld去查找Tenant*实体上的设置,去覆盖MoquiXML配置文件中默认的数据源设置。
连接池和数据库
实体门面使用Atomikos TransactionsEssentials或Bitronix BTM用于XA-aware数据库连接池。使用jta.properties文件去配置Atomikos,bitronix-default-config-properties文件去配置Bitronix。通过Moqui XML配置文件中entity-facade元素的配置,你可以修改默认的连接池并使用任何的DataSource或替代的JNDI XADataSource
Moqui框架中包含的默认数据库是Apache Derby。它很容易通过Moqui XML配置文件中entity-facade元素的配置去改变。添加一个新的database-list.database元素可以新增一个在MoquiDefaultConf.xml文件中尚不支持的数据库。当前默认支持的数据库包括Apache Derby ..DB2 HSQL MySql Postgres Oracle以及MS SQL Server.
数据库元数据:
事物门面:
食物主要用于服务和界面。服务定义上有事物设置,基于此服务调用者可以按需去暂停/回复以及开始/提交/回滚事务。对于界面来说,事务总是开始于转换,并用于渲染实际的界面,事务仅胡开始与如果界面设置使用了事务。
也可以使用事务门面TransactionFacade去手动划分事务姐main。JavaDoc文档中有一些推荐模式的代码样例使用了try/catch/finally自居去开始/提交/回滚以及暂停恢复事务,来确保事务被合理的管理。
当调试事务的问题时。例如会追踪一个仅回滚的设置在何处,事务门面TransactionFacade同样可以使用,因为当调用setRollbackOnly()方法时事务门面保持了一盒追踪堆栈。它将在售后的错误中自动进行日志记录,同时也可以在其他时间手动的去获得这些日志记录信息。
事务管理JTA
事务门面默认使用Bitronix TM类库。使用bitronix-default-config.properties文件配置Bitronix.Moqui框架同样开箱即用的支持Atomikos,通过jta.properties文件配置
任何例如来源于应用服务器的一个JTA事务管理,可用于替代配置与Moqui XML配置文件里entity-facade元素中UserTransaction和TransactionManager实现的JNDI方式。
构件执行门面
被其他门面所调用,用于保持追踪执行上下文ExecutionContext声明周期中哪些构件正在运行。它保持了所有构件的一个历史遗迹当前运行构件的一个堆栈。力图:如果一个界面调用了一个自界面,同时自界面调用了一个实体查询的服务,堆栈将为第一个界面,然后是第二个界面,接着是服务,最后是实体。