WSO2 EI:如何在定时任务中遍历JSON数组并动态调用API?
问题描述
我已在property中定义一个JSON数组:
<property name="systemList" type="STRING" value='[ {"systemName":"Vodafone", "tokenEndpoint":"https://vodafone.com/oauth/token", "client_id":"c6VwL5qIGQAhJfmZADoR", "client_secret":"dGfk4xKTGPcZ4MvMxpl5"}, {"systemName":"TalkTalk", "tokenEndpoint":"https://talktalk.com/oauth/token", "client_id":"xyz123", "client_secret":"abc456"}, {"systemName":"NewSystem", "tokenEndpoint":"https://newapi.com/oauth/token", "client_id":"newClientID", "client_secret":"newSecret"} ]'/>
我当前使用<iterate> mediator遍历该数组:
<iterate expression="json-eval($.systemList)" preservePayload="false" attachPath="$"> <target> <sequence> <log category="INFO" level="custom"> <property name="Step" value="Fetching token for a system" /> <property name="Current System" expression="json-eval($.systemName)" /> </log> <property name="TokenEndpoint" scope="default" expression="json- eval($.tokenEndpoint)" /> <property name="Content-Type" scope="transport" type="STRING" value="application/x-www-form-urlencoded" /> <property name="Accept" scope="transport" type="STRING" value="application/json" /> <property name="client_id" scope="default" expression="json-eval($.client_id)" /> <property name="client_secret" scope="default" expression="json-eval($.client_secret)" /> <send> <endpoint> <http method="POST" uri-template="{get-property('TokenEndpoint')}"> <timeout> <responseAction>discard</responseAction> <duration>30000</duration> </timeout> </http> </endpoint> </send> <enrich> <source clone="true" type="body" /> <target property="fetchedToken" type="property" /> </enrich> <property expression="json-eval($.access_token)" name="storedToken" scope="registry" type="STRING" /> <property expression="json-eval($.systemName)" name="systemName" scope="default" type="STRING" /> <property name="registryTokenKey" expression="concat('storedToken_', get-property('systemName'))" scope="default" type="STRING" /> </sequence> </target> </iterate>
请问我是否应该使用其他循环机制来遍历这个JSON数组?
解答
当前Iterate Mediator的适用性
你的场景用Iterate Mediator是完全合适的:
- Iterate默认支持并行处理每个数组元素,对于这种独立的OAuth token请求场景,并行处理能有效提升整体效率,不需要等待前一个请求完成再处理下一个。
- 你配置的
preservePayload="false"和attachPath="$"是正确的,确保每个迭代流程只处理单个系统的JSON对象,不会干扰原消息内容。
什么时候需要更换循环机制
只有当你的需求不匹配Iterate的特性时,才需要考虑其他方案:
- 串行处理需求:如果必须等待前一个系统的token请求完成后,再处理下一个,那么可以改用Loop Mediator。使用Loop需要先获取数组长度,再通过索引逐个访问元素,示例逻辑如下:
<!-- 先获取数组长度 --> <property name="systemCount" expression="json-eval($.systemList.length())" scope="default" type="INTEGER"/> <!-- 循环处理 --> <loop expression="$ctx:systemCount"> <sequence> <property name="currentIndex" expression="$ctx:loopIndex" scope="default" type="INTEGER"/> <!-- 获取当前系统的JSON对象 --> <property name="currentSystem" expression="json-eval($.systemList[{$ctx:currentIndex}])" scope="default" type="STRING"/> <!-- 后续的token请求逻辑... --> </sequence> </loop> - 复杂条件过滤+循环:如果需要先对数组元素做复杂过滤(比如只处理特定名称的系统),可以在Iterate的expression里直接加过滤条件,不需要更换机制,例如:
<iterate expression="json-eval($.systemList[?(@.systemName != 'NewSystem')])" preservePayload="false" attachPath="$"> <!-- 目标序列逻辑 --> </iterate>
当前代码的小优化点
- 修正
TokenEndpoint属性里的表达式空格问题:把json- eval($.tokenEndpoint)改为json-eval($.tokenEndpoint),避免解析错误。 - 存储registry token时,可以直接从
fetchedToken属性取值,逻辑更清晰:<property expression="json-eval($ctx:fetchedToken.access_token)" name="storedToken" scope="registry" type="STRING" />
总结
如果你的需求是并行处理多个系统的token请求,当前的Iterate Mediator完全满足需求,不需要更换;如果有串行处理、特殊过滤逻辑等其他需求,再考虑Loop Mediator或其他组合方案。
内容的提问来源于stack exchange,提问作者Roy
相关产品推荐
相关产品推荐

