ofbiz 之minilang解析
编写一个simple method 首先我们需要对输入参数进行验证 ,判断参数是否完整。
1. 验证
1.1. Login-required
:这是一个simple-method的属性,对是否需要登陆进行设置,默认值为true ,即默认需要先登陆。(加上service 定义中的auth 定义,所以如果你不希望一个simple service 必须登陆才能调用的话,那么首先得将service 定义中的auth设为false ,再将此处的login-required 设为false),后续会陆续多种子权限判断的用法,关于权限判断都是首先需要登陆的。
1.2. use-transaction
:设置此simple method 是否使用事务。根据业务需求来判断具体设置。
1.3. check-permission
:判断权限是否具有某一权限,一般用法为:
<check-permission permission="person" action="_update">
<alt-permission permission="person" action="_view"/>
<fail-property resource="WebtoolsUiLabels" property="doNotHavePermission"></fail-property>
</check-permission>
<check-errors></check-errors>
使用check-permission前提条件是当前service 环境中必须存在用户的登陆信息,即能获取到userLogin . service 的调用场景有很多,controller.xml中,screen中,simple method 中,bsh文件中,ftl 文件中,java 文件中,groovy文件中等,其中前三项系统会自动将userLogin,locale 等信息自动封装到service context 中去,所以不需要我们手段传值,所以我们在其他环境中调用service的时候就需要对需要的隐性参数进行传值,比如fail-property中会用到locale, check-permission会用到userLogin 等,调用举例如下:
dispatcher.runSync("TestServiceOnSimple",UtilMisc.toMap("param3","TestServiceOnJava","userLogin",userLogin,"locale",locale)); //java文件中
check-permission中有个属性error-list-name="error_list" ,这条属性的意思是意义是将错误信息放到error_list这个list 中。配合check-errors的共同使用。
其中check-permission判断是否具有”${permission的值}_ADMIN” 权限,如果action的值不为null,则会首先判断当前用户是否具有”${permission的值}_ADMIN”权限,如果有则权限判定符合要求,否则判断是否具有”${permission的值}_${action的值}”,如果check-permission判断权限要求都不满足的话,会进行alt-permission 权限判断,判断规则和check-permission一样, check-permission 和 alt-permission 两者的关系是or的关系,即只要两者有一个满足权限要求即可。如果两者条件都不满足的话那么将会把fail-property 写进错误信息中,fail-property错误信息来源于”${ resource的值}.xml”中key值为”${property的值}”所对应的value 值。系统会自动根据客户端浏览器的locale从文件中获取对象的提示信息。
当然你也可以直接将来报错提示信息写在当前simple methord 中,使用
<check-permission permission="person" action="_update">
<alt-permission permission="person" action="_view"/>
<fail-message message="you do not have XXX permission !!"/>
</check-permission>
fail-message 与 fail-property 是不能共存的,二者只能存其一。
所有上面的内容只会对权限进行判断,权限不满足的话收集提示信息,<check-errors></check-errors>则是返回错误信息。如果没有check-errors那么service method 将会继续往下执行。有check-errors的话则会中断simple method 的执行。
如果非要用java 语言进行翻译的话,我觉得应该是这样的。
<check-permission permission="person" action="_update">
<alt-permission permission="party" action="_view"/>
<fail-property resource="WebtoolsUiLabels" property="doNotHavePermission"></fail-property>
</check-permission>
<check-errors></check-errors>
翻译成java service 应该是这样的.
Security security = dctx.getSecurity();
if (!(security.hasPermission ("person_ADMIN", userLogin)
|| security.hasPermission ("person_update", userLogin)
|| security.hasPermission ("party_ADMIN", userLogin)
|| security.hasPermission ("party_view ", userLogin))
) {Return ServiceUtil.returnError(
UtilProperties.getMessage("WebtoolsUiLabels","doNotHavePermission",locale));
}
另:check-permission 中还有个子节点accept-userlogin-party ,似乎不很常用,后待研究
1.4. if-has-permission
<if-has-permission permission="person_view" >
<set field="hasPermission" type="Boolean" value="true"/>
<field-to-result field="hasPermission"/>
<log level="info" message="you have ACCTG_FX_ENTRY!"/>
<else>
<set field="hasPermission" type="Boolean" value="false"/>
<property-to-field
resource="CommonUiLabels" property="CommonGenericPermissionError" field="failMessage"/>
<field-to-result field="hasPermission"/>
<field-to-result field="failMessage"/>
</else>
</if-has-permission>
if-has-permission判断权限的规则和check-permission的规则是一样的。不重复了,if-has-permission和check-permission最大的不同在于if-has-permission可以进行if-else 的逻辑判断.当然如果不需要else判断的话可以把else节点整个去掉,即:
<if-has-permission permission="person_view" >
<set field="hasPermission" type="Boolean" value="true"/>
<field-to-result field="hasPermission"/>
<log level="info" message="you have ACCTG_FX_ENTRY!"/>
</if-has-permission>
翻译一下前边的if-has-permission的例子.
首先判断当前用户是否具有person_view的权限,如果有这个权限那么执行:
<set field="hasPermission" type="Boolean" value="true"/>
创建Boolean 变量 hasPermission 值为true
<field-to-result field="hasPermission"/>
将hasPermission这个变量赋值到result结果集中
<log level=" info" message="you have ACCTG_FX_ENTRY!"/>
输出info级别日志,” you have ACCTG_FX_ENTRY!”.
判断权限如果没有这个权限则执行:
<set field="hasPermission" type="Boolean" value="false"/>
创建Boolean 变量 hasPermission 值为false
<property-to-field
resource="CommonUiLabels" property="CommonGenericPermissionError" field="failMessage"/>
从CommonUiLabels.xml文件中获取key为CommonGenericPermissionError的国际化内容并赋值到变量failMessage中
<field-to-result field="hasPermission"/>
将hasPermission这个变量赋值到result结果集中
<field-to-result field="failMessage"/>
将failMessage这个变量赋值到result结果集中
1.5. if-compare
<if-compare field="statusId"
operator="equals" value="INVOICE_PAID">
<log level="info"
message="The compare conditions are met"></log>
<else>
<log level="info"
message="The compare conditions are not met"></log>
</else>
</if-compare>
if-compare,把某一参数的值与一特定的值进行比较。比较的逻辑类型通过operator进行设置,种类主要有less,greater,less-equals,greater-equals,equals,not-equals,contains等,不挨个解释了无非是大于,等于,大(小)于等于,包含等。
if-compare中另外还有两个参数format、type . type指比较参数双方的数据类型,比较之前系统会将比较双方的参数转化成你指定的type类型。
format指比较参数双方的格式,一般用在日期格式中,和日期有关的type类型主要有Time,Date,Timestamp三种,针对这三种子日期类型format类型有三个默认值
分别是"HH:mm:ss","yyyy-MM-dd","yyyy-MM-dd HH:mm:ss.SSS" 。使用时间进行比较的时候参数的格式最好和默认的format相同,否则容易出现不可预料的问题。
与if-has-permission类似,当满足if条件的情况下执行<if-compare 与 <else>中间的内容,否则则执行<else>与</else>中间的内容,当然和if-has-permission一样,也可以不使用<else></else>(以后类似情况不再提了,自己类推吧。).即
<if-compare field="statusId"
operator="equals" value="INVOICE_PAID">
<log level="info"
message="The compare conditions are met"></log>
</if-compare>
1.6. if-compare-field
if-compare-field与if-compare用法规则相同,唯一的不同在于if-compare是一个参数与固定值之间的比较,而if-compare-field是两个参数之间的比较。
1.7. if-empty
<if-empty field="param5">
<log level="info" message="the parameter param5 is empty"></log>
<else>
<log level="info" message="the parameter is not empty "></log>
</else>
</if-empty>
判断一个参数是否为null,如上判断参数param5是否为null.
1.8. if-not-empty
<if-not-empty field="param5">
<log level="info" message="the parameter is not empty "></log>
<else>
<log level="info" message="the parameter is empty "></log>
</else>
</if-not-empty>
顾名思义这个是和if-empty反着用的。
1.9. if-instance-of
<if-instance-of field="param5" class="String">
<log level="info" message="the parameter is a String"></log>
<else>
<log level="info" message="the parameter is not a String"></log>
</else>
</ if-instance-of>
OR
<if-instance-of field="param5" class="java.util.List">
<log level="info" message="the parameter is a List"></log>
<else>
<log level="info" message="the parameter is not a List"></log>
</else>
</if-instance-of>
if-instance-of判断某一参数是否属于指定的参数类型。类似于java 中的instanceof 。
1.10. if-regexp
<if-regexp field="param5" expr="^[a-zA-Z_0-9]+$">
<log level="info" message="expr validate success"></log>
<else>
<log level="info" message="expr validate Fail"></log>
</else>
</if-regexp>
使用正则表达式对参数进行验证。
1.11. if-validate-method
<if-validate-method field="param5" method="isEmail">
<log level="info" message="param5 is a Email"></log>
<else>
<log level="info" message=" param5 is not a Email"></log>
</else>
</if-validate-method>
使用验证方法对参数进行验证,if-validate-method有个class属性,其默认值为
"org.ofbiz.base.util.UtilValidate",使用${class}类中的${method}方法对参数param5进行验证。
1.12. if
<if>
<condition>
<and>
<if-compare field="param1" operator="equals" value="value1"/>
<if-compare field="param2" operator="equals" value="value2"/>
</and>
</condition>
<then>
<log level="info" message="condition1 validate success"></log>
</then>
<else-if>
<condition>
<if-compare field="param3" operator="equals" value="value3"/>
</condition>
<then>
<log level="info" message="condition2 validate success"></log>
</then>
</else-if>
<else>
<log level="info" message="condition1 and condition2 validate Fail"></log>
</else>
</if>
If 一般情况下配合condition 使用,进行多条件的组合判断,使用<and></and> 或者<or></or>组织多个条件的逻辑关系,如果condition 条件满足,那么执行then ,否则执行 else-if 或者 else . 此用法是minilang 中唯一可以使用else if 逻辑判断的地方。
1.13. check-id
<check-id field="parameters.orderId" error-list-name="error_list">
</check-id>
对参数进行特殊字符验证,判断orderId 中是否含有空格、“、‘、&、?、<、>、\、/等。针对每种不同的特殊字符,check-id 提供了一种默认错误提示信息与之对应,所以错误信息可以不用设置,当然也可以使用fail-message 和 fail-property提供错误信息(用法同check-permission ,后续用到将不再重复),将错误信息放到${error-list-name}中,供check-errors使用。
1.14. add-error
<add-error error-list-name="error_list">
<fail-message message="error Need a reason?"/>
</add-error>
OR
<add-error error-list-name="error_list">
<fail-property resource="WebtoolsUiLabels" property="errorKey">
</fail-property>
</add-error>
向一个错误结果list中添加错误信息,错误结果list的name 可以指定,错误信息的来源可以来自来源于国家化xml文件.而可以是直接写死的message。一般用在之前介绍的那么多if-XXXX判断中,如果条件不满足(<else></else>中间)那么将错误信息写入错误信息结果list中,再通过check-errors 将错误信息返回。
1.15. check-errors
<check-errors error-code="resultPage" error-list-name="error_list">
</check-errors>
前边已经讲到很多,是将错误信息进行返回,如果错误信息结果${error-list-name}中存在错误那么将返回错误信息并终止当前simple method 的运行。
error-list-name指定要返回的错误信息结果list名称,MethodContext中可能会包含多个错误结果信息list,根据业务需要而定, error-code 返回错误状态码,一般用在controller.xml 中,
<request-map uri="testServiceTest">
<security https="false" auth="false"/>
<event type="service" invoke="TestServiceOnJava"/>
<response name="success" type="view" value="toSuccess"/>
<response name="error" type="view" value="toError"/>
<response name="resultPage" type="view" value="toResult"/>
</request-map>
系统会根据其返回的code 而指向不同的request 或者 view 。
check-errors 另有4个节点,(已过期,源码已经被注释)
<message-suffix resource="WebtoolsUiLabels" property="doNotHavePermission2"></message-suffix>
<message-prefix resource="WebtoolsUiLabels" property="doNotHavePermission2"></message-prefix>
<error-prefix resource="WebtoolsUiLabels" property="doNotHavePermission2"></error-prefix>
<error-suffix resource="WebtoolsUiLabels" property="doNotHavePermission2"></error-suffix>
1.16. assert
assert:断言待确定。
calculate
1.17. calculate
calculate:待确定
2. 数据操作
2.1. clone-value
<clone-value value-field="lookedUpValue" new-value-field="newLookedUpValue"/>
clone-value克隆参数。以${value-field}参数对象为模板,创建一个新的参数对象。value-field的值必须是一个GenericValue对象或者是能够转化成GenericValue的对象。
2.2. clear-field
<if-not-empty field="param6">
<log level="info" message="the value of param6 is not empty"></log>
</if-not-empty>
<clear-field field="param6"/>
<if-empty field="param6">
<log level="info" message="the value of param6 is empty"></log>
</if-empty>
运行结果
[CommonServices.xml#TestServiceOnSimple line 85] the value of param6 is not empty
[CommonServices.xml#TestServiceOnSimple line 89] the value of param6 is empty
clear-field 将参数${field}从simple method 运行环境中methodContext清除掉。
2.3. create-object
待确定
2.4. clear-cache-line
待确定
2.5. clear-entity-caches
待确定
2.6. entity-one
<set field="UserLogin" value="admin"/>
<entity-one entity-name="UserLogin" value-field="adminUserLogin"
auto-field-map="true" use-cache="true">
</entity-one>
<log level="info" message="${adminUserLogin}"></log>
entity-one根据给定主键对某一特定实体进行主键查询。如上例:根据实体UserLogin 主键userLoginId的值进行主键查询,并将查询结果定义为adminUserLogin。
由于entity-one 的属性auto-field-map的值设置为true,所以系统会从simple method 的运行环境MethodContext中自动寻找实体的主键。use-cache 是关于是否首 先从缓存中获取数据的设置。
如果auto-field-map的值设置为false,那么系统将不会自动从封装实体主键,那么需要我们手动给参,如下:
<entity-one entity-name="UserLogin" value-field=" adminUserLogin " auto-field-map="false">
<field-map field-name="userLoginId" value="admin"/>
</entity-one>
<set field="userLoginId" value="admin"/> 即为给主键传参。参数可以为固定的value 值,也可为已经存在与运行环境中的参数值。如下:
<set field="userLoginId" value="admin"/>
<entity-one entity-name="UserLogin" value-field=" adminUserLogin " auto-field-map="true">
<field-map field-name="userLoginId" from-field=" userLoginId "/>
<select-field field-name="currentPassword"/>
<select-field field-name="disabledDateTime"/>
</entity-one>
select-field为非主键选择性输出,即将实体字段中用到的字段写入查询结果adminUserLogin中,用不到的则不写入。select-field 不得设置主键,且使用select-field时不能与use-cache="true" 同时使用。
2.7. entity-and
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList">
<field-map field-name="partyId" value="admin"/>
<select-field field-name="workEffortId"/>
<order-by field-name="+workEffortId"/>
</entity-and>
<log level="info" message="${wepaList}"></log>
entity-and 非主键多条件查询。
use-cache 是关于是否首先从缓存中获取数据的设置。不能和select-field共同使用。
为了容易查看效果这里使用select-field(用法同entity-one 中select-field)限制查询字段只显示输出了workEffortId
字段。输出结果如下:
{
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9000(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9002(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9100(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,OneOffMeeting(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,STAFF_MTG(java.lang.String)]
}
entity-and 中属性 limit-range 效果展示 :
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList">
<field-map field-name="partyId" value="admin"/>
<select-field field-name="workEffortId"/>
<order-by field-name="+workEffortId"/>
<limit-range size="3" start="2"/>
</entity-and>
<log level="info" message="${wepaList}"></log>
输出结果:
{
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9002(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9100(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)]
}
可以发现limit-range的功能为截取查询结果,从第${start}(包括此条)数据起,截取${size}条数据做为最终结果。
entity-and 中属性 limit-view 效果展示 :
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList">
<field-map field-name="partyId" value="admin"/>
<select-field field-name="workEffortId"/>
<order-by field-name="+workEffortId"/>
<limit-view view-size="2" view-index="2"/>
</entity-and>
<log level="info" message="${wepaList}"></log>
输出结果:
{
[GenericEntity:WorkEffortPartyAssignment][workEffortId,9100(java.lang.String)],
[GenericEntity:WorkEffortPartyAssignment][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)]
}
可以发现limit-view 类似于分页,将查询结果划分为每页${view-size}条数据,取第${view-index}页数据,如果用limit-view 来实现相同功能的话,需要设置start="3",size="2"
entity-and 中属性 use-iterator 效果展示 :
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList">
<field-map field-name="partyId" value="admin"/>
<select-field field-name="workEffortId"/>
<order-by field-name="+workEffortId"/>
<use-iterator/>
</entity-and>
<if-instance-of ass="org.ofbiz.entity.util.EntityListIterator"
ield="wepaList">
<log level="info" message="the wepaList is a Iterator"></log>
</if-instance-of>
<if-instance-of class="java.util.List" field="wepaList">
<log level="info" message="the wepaList is a List object"></log>
</if-instance-of>
设置<use-iterator/>时输出结果为:
the wepaList is a Iterator
不设置时输出结果为:
the wepaList is a List object
可见设置<use-iterator/>使输出参数结果的格式发生了变化。如果设置了use-iterator ,却不使用EntityListIterator结果对象的话,会报错(待查验)
总结:use-iterator、limit-view、limit-range 三者不能两两共存,且此三者所处位置必须在其他同级节点的后面。
2.8. entity-condition
<entity-condition list="partyAssignments" entity-name="WorkEffortPartyAssignment" filter-by-date="true">
<condition-list combine="and">
<condition-expr field-name="workEffortId" from-field="workEffortId"/>
<condition-expr field-name="partyId" from-field="userLogin.partyId"/>
<condition-expr field-name="statusId" value="PRTYASGN_ASSIGNED"/>
<condition-list combine="or">
<condition-expr field-name="roleTypeId" value="CAL_OWNER"/>
<condition-expr field-name="roleTypeId" value="CAL_ORGANIZER"/>
<condition-expr field-name="roleTypeId" value="CAL_DELEGATE"/>
</condition-list>
</condition-list>
</entity-condition>
entity-condition 对实体${entity-name}进行多条件组合逻辑查询。
ofbiz 很多实体在创建的时候都会有两个字段,分别为fromDate 和 thruDate.
这两个字段一般被用来代表当前数据的有效期间,既当前数据的有效期为大于等于fromDate 且 小于 thruDate 。 当fromDate 为null 时 则表示前端无限制, thruDate表示后端无限制。
属性distinct很好理解,剔除重复数据。需要注意的是如果配合select-field 共同使用的时候,判断重复的条件是判断select-field 需要显示字段是否重复,而不是判断当前实体所有的字段,即SQL 执行顺序是 先select-field 再distinct。
属性filter-by-date即为对记录表数据时间有效性的过滤,使用前提是当前实体必须有fromDate 和 thruDate这两个字段,且不能使用缓存进行查询 ,即use-cache="false",转化成sql 表示为
((thruDate IS NULL OR thruDate > '当前时间') AND (fromDate IS NULL OR fromDate <= '当前时间'))
condition-expr为单个条件的逻辑判断,逻辑判断类型通过operator 进行设置,用法和if-compare类似。ignore-if-empty="true",当前字段为“”时是否忽略,
意思是如果当前进行判断的字段为””则忽略此判断。同理ignore-if-null="true"意思是如果当前进行判断的字段为null则忽略此判断.
condition-list为多个条件的逻辑组合,通过combine对condition-list节点中的多个condition-expr 进行逻辑组合,逻辑关系主要有 “and” 和 “or” 两种。
condition-object为使用当前simple 运行环境中已经存在的org.ofbiz.entity.condition.EntityCondition 类型的对象进行逻辑判断。
having-condition-list一般用于带有group-by 查询的视图实体查询,首先对根据condition-list查询条件进行查询,然后再根据having-condition-list查询条件进行限制查询。 比如:
<view-entity entity-name="WorkEffortPartyAssignmentView" package-name="org.ofbiz.workeffort.workeffort">
<member-entity entity-alias="wepa" entity-name="WorkEffortPartyAssignment"></member-entity>
<alias-all entity-alias="wepa">
<exclude field="partyId"/>
</alias-all>
<alias entity-alias="wepa" name="partyId" group-by="true">
</alias>
<alias entity-alias="wepa" name="quantityTotal" field="partyId" function="count"/>
</view-entity>
此视图实体全部使用WorkEffortPartyAssignment的参数,根据partyId进行分组,然后获取每组的数量。
查询使用:
<entity-condition list="wepaListTwo" entity-name="WorkEffortPartyAssignmentView">
<condition-list combine="or">
<condition-expr field-name="partyId" operator="equals" value="admin"/>
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee2"/>
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee3"/>
</condition-list>
<having-condition-list>
<condition-expr field-name="quantityTotal" operator="equals" value="3"/>
</having-condition-list>
<select-field field-name="partyId"/>
<select-field field-name="quantityTotal"/>
<use-iterator/>
</entity-condition>
首先根据三个partyId条件进行逻辑或进行分组查询,然后再对查询结果进行having-condition-list筛选。Sql 解析结果为:
SELECT wepa.PARTY_ID, COUNT(wepa.PARTY_ID) FROM OFBIZ.WORK_EFFORT_PARTY_ASSIGNMENT wepa WHERE ((wepa.PARTY_ID = 'admin' OR wepa.PARTY_ID = 'DemoEmployee3' OR wepa.PARTY_ID = 'DemoEmployee2')) GROUP BY wepa.PARTY_ID HAVING (COUNT(wepa.PARTY_ID) = 3)
having-condition-list 用法同condition-list。
总结:entity-condition当使用缓存进行查询时,不能使用distinct、having-condition-list、select-field。entity-condition查询限制条件最外层必须为condition-list、condition-expr、condition-object中的一个,三者不能两两并存。entity-condition的几个子节点配置先后顺序分别为:[condition-list、condition-expr、condition-object]三者中的一个、[having-condition-list]、[select-field],[order-by]、[use-iterator、limit-view、limit-range]三者中的一个。
2.9. entity-count
<entity-count count-field="num" entity-name="WorkEffortPartyAssignment">
<condition-list combine="or">
<condition-expr field-name="partyId" operator="equals" value="admin"/>
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee2"/>
<condition-expr field-name="partyId" operator="equals" value="DemoEmployee3"/>
</condition-list>
</entity-count>
entity-count 查询${entity-name}中符合条件的数据条数并赋值到 ${count-field}参数。条件配置与 entity-condition 一样。不罗嗦。
2.10. entity-data
待确定
2.11. find-by-primary-key
<set field="fieldsToSelect[]" value="currentPassword"/>
<set field="fieldsToSelect[]" value="partyId"/>
<set field="inParma.userLoginId" value="admin"/>
<!—- 此处以上都是参数的处理以及设置 -->
<find-by-primary-key entity-name="UserLogin" value-field="outResult" map="inParma" fields-to-select-list="fieldsToSelect" />
<log level="info" message="---${outResult}---"></log>
find-by-primary-key功能与entity-one 相同,不同的是find-by-primary-key需要将主键字段封装到一个map中,然后使用,显示字段slelect-field 也是需要先将需要显示的字段封装到一个list 中。
: entity-name:查询实体名称。
:value-field:查询结果得到的实体对象名称。
:map: 一个map ,其中包含了主键字段。作为主要查询的依据。如果主键由多个字段组合而成,那么此map中需要包含所有的主键的字段信息。
:fields-to-select-list: 一个list,配置查询结果中所包含的非主键字段,主键字段就不要再这里设置了。
:use-cache:与entity-one 不同,这里的use-cache可以和选择性显示字段fields-to-select-list共同使用
2.12. find-by-and
<clear-field field="inParma"/>
<set field="inParma.partyId" value="admin"/>
<set field="orderList[]" value="+partyId"/>
<set field="orderList[]" value="-workEffortId"/>
<find-by-and list="outResult" map="inParma" entity-name="WorkEffortPartyAssignment" order-by-list="orderList" use-cache="true" use-iterator="true"/>
<iterate entry="out" list="outResult">
<log level="info" message="iterator---${out}---"></log>
</iterate>
功能同entity-and,多条件查询。
:map:map 类型,其中放置了查询条件,map中多条查询条件之间的逻辑关系是and的关系。由于输入参数inParma这个map不能包含所查询实体${entity-name}之外的字段,在之前程序中我们可能已经使用过这个inParma参数,其中可能已经包含一些其他数据,所以我们使用之前最好将inParma参数清除一下。即<clear-field field="inParma"/>
:order-by-list:list 类型,排序的依据。需要提前封装。
:use-cache:是否使用缓存查询,与entity-and中use-cache会与其他节点或者属性有冲突不同,这里use-cache与其他节点属性可以共存。
:use-iterator:是否使用iterator类型返回参数。
2.13. get-related-one
<make-value value-field="userNew" entity-name="UserLogin"/>
<set field="userNew.partyId" value="admin"/>
<get-related-one relation-name="Party" to-value-field="partyNew" value-field="userNew"/>
get-related-one根据外键实体获取外键所对应主键的实体。
实体与实体之间存在一中relation关系,如果把relation的方称为 甲实体 ,被relation的实体称为乙实体 。那么这里是根据 甲实体对象对乙方实体对象进行业务操作(查询)。使用get-related-one的前提是 甲实体 对乙方实体 relation 的type类型为one 或者 one-noFK 。
:value-field:甲方实体对象名称,查询依据。此实体必须包含relation 字段的值,
即甲方实体对象相对应乙方的外键值必须不能为null值。否则获得结果集为null;
:relation-name:查询实体名称。
:to-value-field:查询结果实体对象名称。
后面将会介绍到remove-related ,这个和 get-related-one 的关系有点相反。
remove-related 是根据乙方实体对象对甲方实体对象进行业务操作(删除)。
把这两个结合起来看吧 。(相关relation 的操作建议熟悉实体的relation 再看)
2.14. get-related
<clear-field field="partyNew"/>
<make-value value-field="partyNew" entity-name="Party"/>
<set field="partyNew.partyId" value="AUTHOR_MADMAX"/>
<get-related relation-name="UserLogin" list="userLoginList" value-field="partyNew"/>
待定。。。。。。
2.15. filter-list-by-and
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList">
<field-map field-name="partyId" value="admin"/>
<select-field field-name="workEffortId"/>
<select-field field-name="partyId"/>
<select-field field-name="roleTypeId"/>
<order-by field-name="+workEffortId"/>
</entity-and>
<iterate entry="wepaL" list="wepaList">
<log level="info" message="before filter --- ${wepaL}"></log>
</iterate>
<clear-field field="inParma"/>
<set field="inParma.workEffortId" value="9000"/>
<set field="inParma.roleTypeId" value="PROVIDER_MANAGER"/>
<filter-list-by-and list="wepaList" map="inParma" to-list="wepaListFilter"/>
<iterate entry="wepa" list="wepaList">
<log level="info" message="after filter wepaList --- ${wepa}"></log>
</iterate>
<iterate entry="wepa" list="wepaListFilter">
<log level="info" message="after filter wepaListFilter----${wepa}"></log>
</iterate>
输出结果如下:
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9000(java.lang.String)]
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9002(java.lang.String)]
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9100(java.lang.String)]
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_OWNER(java.lang.String)][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)]
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,OneOffMeeting(java.lang.String)]
before filter --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,STAFF_MTG(java.lang.String)]
after filter wepaList --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9000(java.lang.String)]
after filter wepaList --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9002(java.lang.String)]
after filter wepaList --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9100(java.lang.String)]
after filter wepaList --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_OWNER(java.lang.String)][workEffortId,CALENDAR_PUB_DEMO(java.lang.String)]
after filter wepaList --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,OneOffMeeting(java.lang.String)]
after filter wepaList --- [GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,CAL_ATTENDEE(java.lang.String)][workEffortId,STAFF_MTG(java.lang.String)]
after filter wepaListFilter----[GenericEntity:WorkEffortPartyAssignment][partyId,admin(java.lang.String)][roleTypeId,PROVIDER_MANAGER(java.lang.String)][workEffortId,9000(java.lang.String)]
filter-list-by-and 的功能为对存放GenericValue对象的list ,使用一个存放有一个或者多个list 中GenericValue对象的字段的键值对,对list进行筛选。
如果list中GenericValue对象的字段能够和map中的对象(map中多个对象关系为and,必须全部满足。)对应起来那么则满足条件。
<filter-list-by-and list="wepaList" map="inParma" to-list="wepaListFilter"/>
如果 to-list有值,那么则过滤后的结果放到${to-list}中去,否则过滤后结果覆盖${to-list}.
Map中key 值必须为list 中GenericValue对象中存在的字段,否则过滤后结果为null。
2.16. filter-list-by-date
<entity-and entity-name="WorkEffortPartyAssignment" list="wepaList">
<field-map field-name="partyId" value="admin"/>
<order-by field-name="+workEffortId"/>
</entity-and>
<set field="DateNow" type="Timestamp" value="2009-07-04 10:53:25.546"/>
<filter-list-by-date list="wepaList" to-list="wepaListFilter" all-same="false" from-field-name="fromDate" thru-field-name="thruDate" valid-date="DateNow"/>
<iterate entry="wepa" list="wepaList">
<log level="info" message="after filter wepaList --- ${wepa}"></log>
</iterate>
<iterate entry="wepa" list="wepaListFilter">
<log level="info" message="after filter wepaListFilter----${wepa}"></log>
</iterate>
filter-list-by-date 对含有GenericValue对象的list 集合中数据进行时间有效性验证。
:list:要进行过滤验证的list 的名称.其中包含对象必须为GenericValue对象.
: to-list:过滤后结果输出集合名称,如果不设置此值,结果会覆盖输入集合。
:from-field-name:时间有效性验证开始时间字段。
:thru-field-name:时间有效性验证结束时间字段。
:all-same:无效字段。
:valid-date:时间有效性验证的标准,此值必须是一个在运行环境中存在的时间类型的参数。如果不设置此值,默认使用当前时间。炎症规则请参考 entity-condition 的filter-by-date。
2.17. make-value
<clear-field field="inParma"/>
<set field="inParma.userLoginId" value="djtao"/>
<make-value value-field="user" entity-name="UserLogin" map="inParma"/>
<log level="info" message="make-value----${user}"></log>
输出结果: make-value----[GenericEntity:UserLogin][userLoginId,djtao(java.la ng.String)]
Make-value : 创建一个GenericValue对象. entity-name是所要创建对象的实体的名称,value-field是所创建对象的参数名称, map会将其中自动与实体字段相对应的值赋到实体对象中。
2.18. set-pk-fields
<clear-field field="inParma"/>
<set field="inParma.partyId" value="admin"/>
<set-pk-fields value-field="wepaNew" set-if-null="true" map="inParma"/>
set-pk-fields 用于给一个GenericValue对象 赋主键值。如果${map}参数中所包含的内容中key有GenericValue对象主键的字段相同的,那么将此key所对象的value赋到GenericValue对象。
:value-field:GenericValue对象 名称。将要被赋予值的参数名称。
:map:主键值来源。
:set-if-null:其目的是想如果map 中某主键对应的值为null的话,是否对此主键进行赋值,如果此设置为“true”的话,主键对应的值为null 或者 “”的话,程序都会给此主键赋值为null 。如果此如果此设置为“false”的话,null值则会忽略,其他原样赋值。
2.19. set-nonpk-fiels
<set-nonpk-fields value-field="wepaNew" map="inParma" set-if-null="true"/>
给非主键赋值,规则和set-pk-fields一样 不重复。
2.20. create-value
<create-value value-field="wepaNew" do-cache-clear="true" or-store="false"/>
在经过make-value、set-pk-fields、set-nonpk-fields之后一个完整的实体对象 就被创建起来了,那么我们将使用create-value将这个实体对象保存到数据库中。
:value-field:要保存对象的名称。
:do-cache-clear:清除缓存。
:or-store:如果数据库中已存在此主键对应数据,是否根据实体对数据进行update更新。
2.21. store-value
<set field="user.currentPassword" value="321"/>
<store-value value-field="user" do-cache-clear="true"/>
解析后执行SQL
UPDATE OFBIZ.USER_LOGIN SET CURRENT_PASSWORD=?, LAST_UPDATED_TX_STAMP=?, LAST_UPDATED_STAMP=? WHERE USER_LOGIN_ID=?
minilang 中更新数据和我们用SQL 直接更新不同。首先我们必须获得包含主键信息的实体对象,这个获取实体对象的方式可以是我们用make-value手动生成,也可以根据主键信息查询数据得到的实体对象,然后对实体对象中字段进行set修改。然后使用store-value就可以将改动些到数据库中了。Update 字段只修改实体对象中的非主键字段。
:do-cache-clear:清除缓存。
2.22. store-list
<set field="listUser[]" from-field="user" />
<set field="listUser[]" from-field="user" />
<set field="listUser[]" from-field="user" />
<set field="listUser[]" from-field="user" />
<set field="listUser[]" from-field="user" />
<store-list list="listUser" do-cache-clear="true"/>
store-list批量修改数据。${list}是一个list 其中放的是要被写入数据库的实体对象。
store-list 与 store-value 不同的地方在于 , 如果store-list 中的实体对象在数据库中不存在时,他会首先创建一条记录,而store-value 却不会。
2.23. remove-value
<remove-value value-field="user" do-cache-clear="true"/>
根据包含主键字段的实体删除数据。
2.24. remove-list
<remove-list list="listUser" do-cache-clear="true"/>
批量删除。将一个包含多个实体对象的list 中所代表的数据行全部删除。
2.25. remove-by-and
<set field="whereMap.partyId" value="djtao"/>
<set field="whereMap.userLoginId" value="djtao"/>
<set field="whereMap.currentPassword" value="djtao"/>
<remove-by-and map="whereMap" entity-name="UserLogin" do-cache-clear="true"/>
SQL解析后结果为:
DELETE FROM OFBIZ.USER_LOGIN WHERE (PARTY_ID = 'djtao' AND USER_LOGIN_ID = 'djtao' AND CURRENT_PASSWORD = 'djtao')
根据多条条件删除实体数据。Map中各个条件之间逻辑关系为and 关系。
2.26. remove-related
<make-value value-field="partyObject" entity-name="Party"/>
<set field="inMap.partyId" value="djtao"/>
<set-pk-fields value-field="partyObject" map="inMap"/>
<remove-related relation-name="UserLogin" value-field="partyObject"/>
SQL解析后结果为:
DELETE FROM OFBIZ.USER_LOGIN WHERE (PARTY_ID = 'djtao')
remove-related 根据外键所对应主键的实体的对象删除外键实体记录。如上例:UserLogin 实体中,partyId为外键,根据外键的实体对象进行删除。
2.27. sequenced-id
<make-value value-field="newEntity" entity-name="WorkEffort"/>
<sequenced-id sequence-name="WorkEffort" field="workEffortId"/>
<set field="newEntity.workEffortId" from-field="workEffortId"/>
sequenced-id 一般用于获取实体的自增长字段。
:sequence-name:实体名称。
:field:获取到的自增长字段值的名称。
:get-long-only:待确定。
:stagger-max:待确定。
当然也可以这样用,可以节省一行代码,如下:
<make-value value-field="newEntity" entity-name="WorkEffort"/>
<sequenced-id sequence-name="WorkEffort" field="newEntity.workEffortId"/>
2.28. make-next-seq-id(待验证)
<make-value value-field="newEntity" entity-name="WorkEffort"/>
<make-next-seq-id seq-field-name="workEffortId" value-field="newEntity"/>
功能和sequenced-id 差不多,但由于其自增长字段是通过程序获得并写入数据库的方法获得的,所以在高并发或者一次获取多条自增长的情况下,自增长的值可能会重复。但似乎sequenced-id能避免此问题,待验证。
:value-field:想要获得自增长字段的实体对象。
:seq-field-name:实体的自增长字段。
:increment-by:待确定
:numeric-padding:待确定
3. 逻辑操作
3.1. set
<set field="inMap.num" value="2"/>
<set field="newValue" default-value="1" from-field="inMap.num" set-if-empty="true" set-if-null="true" type="String"/>
Set 为变量参数赋值 。
: field: 变量参数的名称.
: from-field:变量参数值来源来源于环境中已经存在的变量.当然也可以使用value
赋固定值。
:default-value:默认值,当from-field和value都不存在时,使用默认值。
:set-if-empty:如果变量的值为””是否仍然赋””于变量。
:set-if-null:如果变量的值为null,是否仍然赋变量null。所以如果此属性配置为false(默认为false) 的话,那么使用set 的话,如果不赋值那么此set 无效。如:
<set field="inMap.num" />此行代码无任何意义。
3.2. set-calendar
创建calendar 日期对象,待确定。
3.3. set-current-user-login
<set field="ulLookup.userLoginId" value="system"/>
<find-by-primary-key entity-name="UserLogin" map="ulLookup" value-field="newuserLogin"/>
<set-current-user-login value-field=" newuserLogin"/>
<log level="info" message="${parameters.userLogin}"></log>
<log level="info" message="${userLogin}"></log>
set-current-user-login 改变当前simple context 中的userLogin .
parameters中的userLogin 不发生改变。
3.4. string-append
<string-append string="456" field="newString" arg-list="newList" prefix="prefix" suffix="suffix"/>
将String 字符串拼接起来。
效果类似于 :
newString = “${newString}”+”${prefix}”+”${string}”+”${suffix}”
:arg-list:待确定
3.5. string-to-list
<set field="newList" type="List"/>
<string-to-list string="a" list="newList"/>
<string-to-list string="b" list="newList"/>
将字符串放到一个list 中。
3.6. session-to-field
<session-to-field field="sessionField" session-name="_WEBAPP_NAME_" default="sessionNull"/>
Session-to-field 将session 中参数取出来赋值到当前环境的某变量中。
:field:变量名称.
:session-name:session中变量的名称.
: default:如果sesssion 中此变量对应的值为null的话,则使用此默认值。
注:此命令只有在event 调用simple method 时方有效。即(MethodContext. methodType== MethodContext.EVENT)时方可使用。
目前所知符合条件的只有一种情况,即在controller.xml中,如下例。
<request-map uri="testServiceDelegator">
<event type="simple"
invoke="TestServiceOnSimple" path="component://webtools/script/org/ofbiz/common/CommonServices .xml"/>
<response name="success" type="view" value="testServiceTest"/>
<response name="error" type="view" value="testServiceTest"/>
</request-map>
在event 中调用,且type为simple .
3.7. field-to-session
<field-to-session field="newUserLogin" session-name="userLogin"/>
Field-to-session 将simple 环境中的参数放入session 中。属性不重复了.
使用限制和session-to-field一样。
3.8. field-to-list
<clear-field field="newList"/>
<field-to-list list="newList" field="newUserLogin"/>
Field-to-list ,将simple 环境中的一个参数变量放到一个list 类型的参数变量中。
3.9. field-to-request
<clear-field field="newList"/>
<field-to-list list="newList" field="newUserLogin"/>
<field-to-request field="newList" request-name="userLoginList"/>
field-to-request ,把参数变量放到request 中,使用规则和限制同field-to-session 相同,不重复。
3.10. request-to-field
将参数从request 中取出赋职到simple 运行环境中。规则和限制同field-to-request。
3.11. request-parameters-to-list
<request-parameters-to-list request-name="checkBoxName" list-name="parametersList"/>
request-parameters-to-list 获取request 中的参数数组,并将参数放到simple method 中的list 中。request-parameters参数一般来源于checkBox .使用限制同 Session-to-field。
3.12. list-to-list
待确定。
3.13. map-to-map
待确定。
3.14. loop
Loop待确定。
3.15. first-from-list
<first-from-list entry="oldExampleStatus" list="oldExampleStatusList"/>
<if-not-empty field="oldExampleStatus">
<set field="oldExampleStatus.statusEndDate" from-field="nowTimestamp"/>
<store-value value-field="oldExampleStatus"/>
</if-not-empty>
first-from-list 从list 参数中得到第一个元素,并赋值到变量参数${entry}中。
3.16. webapp-property-to-field
<webapp-property-to-field resource="WebtoolsUiLabels" property="doNotHavePermission" field="fildFromProperties"/>
Webapp-property-to-field 从国际化资源文件WebtoolsUiLabel.xml中获取property 为” doNotHavePermission” 的字符串并赋值到${field}中。
3.17. iterate
<clear-field field="newParamList"/>
<set field="newParamList[]" value="a"/>
<set field="newParamList[]" value="b"/>
<set field="newParamList[]" value="c"/>
<iterate entry="newParam" list="newParamList" >
<log level="info" message="${newParam}"></log>
</iterate>
Iterate 遍历List参数newParamList。
3.18. iterate-map
<clear-field field="newParamMap"/>
<set field="newParamMap.param1" value="param1"/>
<set field="newParamMap.param2" value="param2"/>
<set field="newParamMap.param3" value="param3"/>
<iterate-map key="newKey" value="newValue" map="newParamMap">
<log level="info" message="${newValue}"></log>
<log level="info" message="${newParamMap.${newKey}}"></log>
</iterate-map>
Iterate-map 对map参数进行遍历,这里有两种方法获取map中元素,一: 通过直接读取${value},二:也可以通过${key}读取map .
3.19. while
<set field="tmp" value="1"/>
<while>
<condition>
<if-compare operator="equals" value="2" field="tmp">
</if-compare>
</condition>
<then>
<log level="info" message="test"></log>
</then>
</while>
While 循环,无论condition 条件 是否成立,先执行一次then 中的内容,然后再进行 condition 条件判断,如果不满足,则跳出while 循环。
3.20. refresh-value
refresh-value 待确定。
4. 调用
4.1. script
<script location="component://product/webapp/catalog/WEB-INF/actions/imag emanagement/SetDefaultImage.groovy"/>
Script 调用groovy 脚本 。
:error-list-name:错误信息存放参数名称
4.2. call-bsh
<call-bsh><![CDATA[
taxAuthPartyGeoIds = parameters.get("taxAuthPartyGeoIds");
parameters.put("taxAuthPartyId", taxAuthPartyGeoIds.substring(0, taxAuthPartyGeoIds.indexOf("::")));
parameters.put("taxAuthGeoId", taxAuthPartyGeoIds.substring(taxAuthPartyGeoIds.indexOf("::") + 2));
]]>
</call-bsh>
使用CDATA 部件 直接调用bsh脚本。也可以直接调用bsh 文件。
<call-bsh error-list-name="error_list" resource="component://webtools/webapp/webtools/WEB-INF/actions/ca che/findUtilCache.bsh">
</call-bsh>
4.3. call-class-method
<call-class-method class-name="org.ofbiz.base.util.UtilDateTime" method-name="getInterval" ret-field="originalProductionRunEstimatedTime">
<field field="productionRunHeader.estimatedStartDate" type="Timestamp"/>
<field field="productionRunHeader.estimatedCompletionDate" type="Timestamp"/>
</call-class-method>
<set field="taskTimeDifference" value="${originalProductionRunEstimatedTime - newProductionRunEstimatedTime}" type="Double"/>
public static double getInterval(Date from, Date thru) {
return thru != null ? thru.getTime() - from.getTime() : 0;
}
call-class-method 调用class类中的方法 .
: class-name:class类所在路径。
:method-name:class类中方法名称。
:ret-field:返回值名称,如果ret-map-name 没有设置的话,直接从当前环境中获取此参数就可以了,如上例。
: ret-map-name:如果设置此值,那么需要先从simple methodContext中获取此map 对象,然后再从map 中获取ret-field.
: field:当前调用的方法所需要的参数。
4.4. call-map-processor
<call-map-processor xml-resource="component://accounting/script/org/ofbiz/accounting/ payment/PaymentMapProcs.xml"
processor-name="createCreditCard" in-map-name="parameters" out-map-name="context"/>
call-map-processor调用map 处理器。
map-processor 一种对map中元素进行过滤或者转化的处理器,类似于加工车间,入料口投入原料,出料口获得成品。一般多用于service 的参数进行处理,因为一般情况下service 对输入参数有限制,所以有时候需要对输入参数map 进行转化一下以匹配service 参数义。
:xml-resource:map-processor 路径。
:processor-name:map-processor名称。
:in-map-name:输入map名称,相当于入料口原料,可能包含多余的参数。
:out-map-name:输入map 名称,相当于出料口,获得到的map 可以直接用于service 的输入参数。
4.5. set-service-fields
<set-service-fields to-map="categoryFindContext" service-name="getAllCategories" map="parameters"/>
<call-service service-name="getAllCategories" in-map-name="categoryFindContext">
<result-to-field result-name="categories" field="categories"/>
</call-service>
set-service-fields 功能同call-map-processor,都是对map中元素进行过滤处理。不同的是 call-map-processor 的处理规则是我们手动定义的map-processor规则,set-service-fields规则是使用service 定义的输入参数。
:service-name:service 名称。规定程序按照此service参数定义进行过滤。
:map:转换器入口,投入map 的名称。
:to-map:转换器出口,输出map的名称。
4.6. call-service
<call-service service-name="getAllCategories" in-map-name="categoryFindContext">
<result-to-field result-name="categories" field="categoriesField"/>
<result-to-request result-name="categories" request-name="categoriesField"/>
<result-to-session result-name="categories" session-name="categoriesField"/>
<result-to-result result-name="categories" service-result-name="categoriesResult"/>
</call-service>
call-service
经过call-map-processor 或 set-service-fields 参数处理之后,处理之后的输出结果, 我们可以直接拿来用做调用service 的输入参数。如上例:
:service-name:service 名称
:in-map-name:调用service 时用到的输入参数,map 类型,如果这里调用的是一个simple service的话 这里的in-map-name 就相当于 被调用simple service 中的parameters ,如果这里调用的是一个java service 的话这里的in-map-name 就相当于java service 输入参数中的context ,都是从其中获取参数。
:result-to-field:假设在service A 中调用 service B ,那么个配置是将B service 中的return 参数 赋值到 service A 的参数。result-name 一定要是service B 中定义过的输出参数。
:result-to-request:request-to-request 和 request-to-session 分别是将被调用service 的返回参数赋值到request 或者 session 中, 使用此命令有限制,请参考field-to-request。
:result-to-result: 将service B 的输出参数 赋值到service A 的输出参数中
result-name 一定要是 service B 中定义过的输出参数, service-result-name一定要是service A中定义过的输出参数。
4.7. call-service-asynch
call-service-asynch同call-service 类似,不同的是call-service是能够步调用,call-service-asynch 是异步调用,异步调用使用的ofbiz job 调度实现。
4.8. call-object-method
<set field="newString" value="123:456" type="String"/>
<call-object-method method-name="indexOf" obj-field="newString" ret-field="retObject">
<string value=":"></string>
</call-object-method>
<log level="info" message="${retObject}">
call-object-method 调用参数对象的方法。
:obj-field:参数对象名称。
:method-name:参数对象的方法名称。
:ret-field:返回值。
:string:输入参数。<string value=":"></string> 。field 同样是做为输入参数。
4.9. call-simple-method
<call-simple-method method-name="getGlArithmeticSettingsInline" xml-resource="component://accounting/script/org/ofbiz/accounting/ ledger/GeneralLedgerServices.xml"/>
call-simple-method 直接调用simple method ,不是以service 的形式调用。如果被调用simple-method 与当前service 在同一个xml文件中xml-resource 可以不用写。
5. 其他
5.1. now-date-to-env
<now-date-to-env field="nowDate"/>
将当前日期(不带时间)赋值给变量参数now.格式为yyyy-MM-dd
5.2. now-timestamp
<now-timestamp field="nowTime"/>
将当前日期时间赋值给变量参数nowTime,格式为yyyy-MM-dd HH:mm:ss.sss
5.3. to-string
将参数转化成string 格式。待确定。
5.4. log
输出日志。前面已经用到很多了 ,不重复了 。
5.5. Order-map-list
<clear-field field="newParamMap"/>
<set field="newParamMap.param1" value="param1"/>
<set field="newParamMap.param2" value="param2"/>
<set field="newParamMap.param3" value="param3"/>
<clear-field field="newParamMap1"/>
<set field="newParamMap1.param1" value="param4"/>
<set field="newParamMap1.param2" value="param5"/>
<set field="newParamMap1.param3" value="param6"/>
<clear-field field="newParamMap2"/>
<set field="newParamMap2.param1" value="param7"/>
<set field="newParamMap2.param2" value="param8"/>
<set field="newParamMap2.param3" value="param9"/>
<set field="newList[]" from-field="newParamMap"/>
<set field="newList[]" from-field="newParamMap1"/>
<set field="newList[]" from-field="newParamMap2"/>
<order-map-list list="newList" >
<order-by field-name="-param1"/>
</order-map-list>
<log level="info" message="${newList}"></log>
order-map-list 以一个list 中map的key为标准对这个list 中各个map 进行排序。
5.6. order-value-list
order-value-list 待定。
5.7. transaction-begin
开启事务。
:began-transaction-name:对当前事务取个别名,如果只有一个事务的话,可以使用默认值。
5.8. transaction-commit
提交事务,如果有多个事务可以根据began-transaction-name进行选择事务提交。
5.9. transaction-rollback
事务回滚。如果有多个事务可以根据began-transaction-name进行选择事务回滚。
ofbiz 之minilang解析的更多相关文章
- OFBiz:解析doRequest()
这里的doRequest()是指RequestHandler中的同名函数: public void doRequest(HttpServletRequest request, HttpServletR ...
- ofbiz 代码日记
写代码一定要尽善尽美.. //修改方法 //条件查询 用于修改 List<GenericValue> stoList = delegator.findByAnd("YcrossS ...
- Apache OFBiz 学习笔记 之 服务引擎 二
加载服务定义文件 ofbiz-component.xml:所有的服务定义文件在每个组件的ofbi-component.xml文件中 加载服务定义 例:framework/common/ofbi ...
- Apache OFBiz 学习笔记 之 服务引擎 一
概述 服务定义为一段独立的逻辑顺序,当多个服务组合一起时可完成不同类型的业务需求 服务有很多类型,WorkFlow.Rules.Java.SOAP.BeanShell等.java类型的 ...
- [OFBiz]开发 三
1. Debug不要在Eclipse中使用Ant来启动ofbiz, 因为在Eclipse中无法kill掉Ant的进程,而ofbiz又没有提供stop的方法.(有一个hook shutdown的方法,但 ...
- OFBiz进阶之HelloWorld(三)CRUD操作
参考文档 https://cwiki.apache.org/confluence/display/OFBIZ/OFBiz+Tutorial+-+A+Beginners+Development+Guid ...
- Apache OFBiz源码解读之MVC模型
节点解析 request-map 你可以将其理解为controller的配置,如果你了解或使用过struts的配置或springmvc的annotation,就会发现这个定义跟它们是很相似的: [ht ...
- 何時需要重启 OFBiz
你在做如下更改時需要重新启動OFBiz服務器: - Java文件(記得要重新編譯) - 配置/.properties文件 - entitymodel或entitygroup XML定義文件 - 服務或 ...
- Apache OFBIZ高速上手(三)--文件夹&&配置文件介绍
1.OFBiz简单介绍,什么是OFBiz OFBiz is an Apache Software Foundation top level project. A ...
随机推荐
- 【BZOJ 2322】[BeiJing2011]梦想封印 利用"环基"+线性基特征值
很容易想到离线加边并且把环和链拆开搞(就是对于每个终点求出起点到他的路径(其实就是dfs树),然后bzoj2115),而且维护也很简单,然而我们发现不同的终点可能得到相同的值,这就是我们遇到的最大的问 ...
- PHP检测json格式数据
首先要记住json_encode返回的是字符串, 而json_decode返回的是对象 判断数据不是JSON格式: 复制代码代码如下: function is_not_json($str){ ...
- JAVA 枚举单例模式
1.枚举单例模式的实现 public enum Singleton { INSTANCE { @Override protected void read() { System.out.println ...
- java 面向对象编程(OOP)
java是一个支持并发.基于类和面向对象的计算机编程语言.下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改: 代码复用: 增加代码的可靠性和灵活性: 增加代码的可理解性. 封装 封装 ...
- [设计篇]01.RESTFUL URI 简单入门设计
1. HTTP Methods HTTP 常用方法: GET: 获取某个资源. POST: 创建一个新的资源. PUT: 替换某个已有的资源. PATCH: 修改某个已有的资源.-->这个自己没 ...
- MSSQL,MySQL 语法区别
1 mysql支持enum,和set类型,sql server不支持 2 mysql不支持nchar,nvarchar,ntext类型 3 mysql的递增语句是AUTO_INCREMENT,而mss ...
- MySQL和Postgresql的区别
一.PostgreSQL相对于MySQL的优势 1.在SQL的标准实现上要比MySQL完善,而且功能实现比较严谨:2.存储过程的功能支持要比MySQL好,具备本地缓存执行计划的能力:3.对表连接支持较 ...
- 【bzoj1593-预定旅馆】线段树维护连续区间
题解: 这题非常经典啊似乎..经典模型要记住啊.. 对于每个节点维护该区间里的最大的连续区间,然后我们就可以logn递归找最前面的一段. 那就维护mx(无限制),lmx(必须从左边开始),rmx(必须 ...
- bzoj 4773: 负环——倍增
Description 在忘记考虑负环之后,黎瑟的算法又出错了.对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得 环上的边权和为负数.保证图中不包含重边和自环. Input 第1 ...
- [Unity]插件Node Editor介绍 实现类似状态机画布的扩展
Unity自带的动画状态机有一套对策划非常友好的UI.但是Unity官方没有公开这些控件的api.除了Asset Store里一些已有的方案,我在这里介绍一个在github上的开源项目,封装了底层,但 ...