欢迎使用普元产品知识库,本知识库包含普元应用开发平台EOSPlatform,流程平台BPS,企业服务总线ESB,微服务平台Microservice,运维管理平台Devops,数据集成平台DI
欢迎使用普元文档库
在项目实施的过程中,遇到最普遍的问题之一就是,第三方系统调用ESB时自定义参数无法识别的问题。本文主要对ESB的参数进行介绍,以及一些参数识别无效的处理方法。
首先来研究一下这几个参数是干嘛的。
ClientId直面意思是客户端id,它的含义就是指接口调用方的身份标识。它的组成成分包含,应用编码前缀、系统域、应用编码后缀。
例如com.zhaojin.esb.ZJKY.BPM中的com.zhaojin.esb 应用编码前缀,ZJKY是系统域,BPM是应用编码后缀。
OperationCode直面意思是操作码,由应用编码前缀、系统域、应用编码后缀、ESB服务名、ESB操作名组成。它是直指提供方接口的具体实现方法的声明。
例如com.zhaojin.esb.ZJKY.CONTRACT.ContractInfo_Update.Update_info中的 com.zhaojin.esb 应用编码前缀,ZJKY是系统域,BPM是应用编码后缀,ContractInfo_Update是ESB服务名,Update_info 是ESB操作名。一般来说,ESB服务名所指提供方接口名,ESB操作名所指提供方接口中某一方法名。
了解以上,我们来说说如何提供制定两个参数规则。比如当前有两个系统需要接入ESB,一个是BPM,一个是合同管理系统。由BPM系统发请求给合同完成某一流程更新合同的操作。调用发起方是BPM,接收方是合同管理系统。那么按照以上所说的参数作用,ClientId 就是com.zhaojin.esb.ZJKY.BPM,而OperationCode就是com.zhaojin.esb.ZJKY.CONTRACT.ContractInfo_Update.Update_info。这两个参数就是要在BPM系统向ESB发起请求时必填的参数。
ESB中要求参数从http request header中添加,可以直接对其解析。解析后根据ESB-SAM系统的配置规则对其请求发起具体业务服务。
这里以java cfx方式调用为例
//接入ESB地址 String endpoint = "http://127.0.0.1:9090/com.zhaojin.esb.ZJKY.CONTRACT.ContractInfo_Update.Update_info "; WebClient client = WebClient.create(endpoint); //添加ClientId client.header("ClientId", "com.zhaojin.esb.ZJKY.BPM"); //添加OperationCode client.header("OperationCode", "com.zhaojin.esb.ZJKY.CONTRACT.ContractInfo_Update.Update_info"); //调用方式1 //InvokeMethodService invokeMethod = JAXRSClientFactory.fromClient(client, InvokeMethodService.class); //调用方式2 InvokeMethodService invokeMethod = JAXRSClientFactory.fromClient(client, InvokeMethodService.class, true); //params是具体的业务数据 String res = invokeMethod.otherInvoke(params); |
这里有几个重点关注的地方。也是项目中所遇到的一个真实例子。调用方在一开始发起调用的时候所使用的是调用方式1,代码检查都没有问题,但始终在ESB这边接收不到ClientId和OperationCode。后来,在厂商尝试无果的情况下,我们把它的调用代码拿过来逐个排查,发现是由于这个接口函数重载了多个同名方法。通过查询相关的API文档,确定了采用调用方式2的方式,最终将ESB必须的两个参数传了过来。
另外,在非java语言中,Asp发起调用ESB请求的时候,也遇到了一个特别诡异的传参问题。
Set xmlhttp = server.CreateObject("MSXML2.XMLHTTP") xmlhttp.Open "POST",url,False xmlhttp.setRequestHeader "ClientId","com.zhaojin.esb.ZJKY.BPM" xmlhttp.setRequestHeader "OperationCode","com.zhaojin.esb.ZJKY.CONTRACT.ContractInfo_Update.Update_info" ... |
检查代码都没有问题,但是确实就是ESB这边接收不到参数,通过抓包工具发现发起调用的数据包中的两个参数key ClientId和OperationCode变成了clientid和operationcode所致。排查后,发现是MSXML2.XMLHTTP组件传递的过程中自己做了一次转换。后来替换了组件为CreateObject("MSXML2.ServerXMLHTTP")解决了这个问题,当然了这其中还有其他的一些问题。但最终通过替换上述组件完美解决了一系列问题。
这里也给咱们ESB产品提一个建议,在识别参数这里忽略大小写,因为这个header参数是ESB产品自定义的,考虑到第三方接入兼容性的问题,希望这里可以完善一下。
另外我们再说说某些平台的限制,有一些平台无法在request header中加入自定义参数。通过查询ESB文档,其实在soap报文中做了一些处理,可以通过soap header中加入如上两个参数。具体配置,在Transport上添加拦截器
com.primeton.esb.governance.interceptor.parameter.ParameterInterceptor
<soapenv:Header> <ClientId> com.zhaojin.esb.ZJKY.BPM </ClientId> <OperationCode> com.zhaojin.esb.ZJKY.CONTRACT.ContractInfo_Update.Update_info </OperationCode> < /soapenv:Header> |
这里要注意的是,第三方平台在追加soap header中的参数时,可能会遇到ESB无法识别的情况。排查发现有的第三方系统发起调用时在具体参数中增加命名空间,比如<s:ClientId>,这样我们的产品默认的拦截器其实是不能对其进行正确的解析的。有两个解决办法,一是在调用发起方对soap header进行改造,去掉相应的命名空间,另外就是重写拦截器,去适配第三方的报文格式。重写拦截器的方法,更能适应第三方系统各种复杂的header报文格式。建议谨慎使用,避免第三方实施厂家各种重度依赖ESB,从而给自己增加额外的不必要的工作量。