在好些场景需要执行其他Cache库的M逻辑来实现业务功能。总不能每次有要求就部署发布个webservice,然后创建客户端代理类。这样太麻烦了,机依赖已有的webservice封装一个跨库执行M的通道。来实现跨库报告同步、跨库基础数据同步等等。
1.包装代码如下
/// 到远程数据库执行M返回数据
/// w ##class(LIS.WS.DHCLISServiceBase).RemoteGetData("http://172.26.234.12:57772/imedicallis/csp/LIS.WS.DHCLISService.cls?wsdl=1&CacheUserName=yonghu&CachePassword=mima","LIS.WS.DHCLISServiceBase","RemoteCacheActiveTestMTHD","")
/// Address:webservice地址
/// ClassName:调用类名
/// FuncName:调用方法名
/// P0-P13的参数
/// OutFormat:输出类型,不传输出JSON,否则输出xml
ClassMethod RemoteGetData(Address, ClassName, FuncName, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, OutFormat) As %String
{
s Address=$g(Address)
s ClassName=$g(ClassName)
s FuncName=$g(FuncName)
s P0=$g(P0)
s P1=$g(P1)
s P2=$g(P2)
s P3=$g(P3)
s P4=$g(P4)
s P5=$g(P5)
s P6=$g(P6)
s P7=$g(P7)
s P8=$g(P8)
s P9=$g(P9)
s P10=$g(P11)
s P12=$g(P12)
s P13=$g(P13)
s Sessions=$g(Sessions)
s OutFormat=$g(OutFormat)
s RowCount=$g(RowCount)
s soapObj=##Class(LIS.WS.DHCLISServiceSoap).%New()
s soapObj.SSLConfiguration="hisweb"
s soapObj.Address=Address
s ParaXml="<Parameter>"
s ParaXml=ParaXml_"<P0>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P0>"
s ParaXml=ParaXml_"<P1>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P1>"
s ParaXml=ParaXml_"<P2>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P2>"
s ParaXml=ParaXml_"<P3>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P3>"
s ParaXml=ParaXml_"<P4>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P4>"
s ParaXml=ParaXml_"<P5>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P5>"
s ParaXml=ParaXml_"<P6>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P6>"
s ParaXml=ParaXml_"<P7>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P7>"
s ParaXml=ParaXml_"<P8>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P8>"
s ParaXml=ParaXml_"<P9>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P9>"
s ParaXml=ParaXml_"<P10>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P10>"
s ParaXml=ParaXml_"<P11>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P11>"
s ParaXml=ParaXml_"<P12>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P0)_"</P12>"
s ParaXml=ParaXml_"<P13>"_##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(P13)_"</P0>"
s ParaXml=ParaXml_"</Parameter>"
i '$l(OutFormat) d
.s OutFormat="JSON"
i OutFormat="JSON" d
.s $p(Sessions,"^",7)="JSON"
.s retxml=soapObj.GetData(ClassName,FuncName,ParaXml,Sessions)
.s err=..GetXmlValByPath(retxml,"/Response/Error")
.i $l(err) THROW ##class(%Exception.SystemException).%New("远程调用异常","D",,"调用远程M失败:"_err)
.s retstr=..GetXmlValByPath(retxml)
e d
.s retstr=soapObj.GetData(ClassName,FuncName,ParaXml,Sessions)
q retstr
}
/// 通过xpath得到xml节点值
/// w ##class(LIS.WS.DHCLISServiceBase).GetXmlValByPath("<Response><RemoteCacheActiveTestMTHDResult>1</RemoteCacheActiveTestMTHDResult><RetVal>0</RetVal><Error></Error><Node>RemoteCacheActiveTestMTHD</Node><RowCount>0</RowCount><ResType>1</ResType><RetSession>^^^^^^JSON</RetSession></Response>","")
/// xml:xml串
/// xpath:不传就默认为检验csp返回格式的xpath,否则传入/Response/RemoteCacheActiveTestMTHD格式层级路径
ClassMethod GetXmlValByPath(xml, xpath)
{
s xml=$g(xml)
s xpath=$g(xpath)
set sc = ##class(%XML.TextReader).ParseStream(xml, .reader)
Set repid=$I(^CacheTemp)
s ret=""
k ^TMP($zn,repid,$j)
while (reader.Read()) {
set Type = reader.NodeType
set Path = reader.Path
set Value = reader.Value
i Type="chars" d
.s ^TMP($zn,repid,$j,Path)=Value
}
i '$l(xpath) d
.s nodenamePath="/Response/Node"
.s resNodeName=$g(^TMP($zn,repid,$j,nodenamePath))
.s xpath="/Response/"_resNodeName_"Result"
i $l(xpath) s ret=$g(^TMP($zn,repid,$j,xpath))
k ^TMP($zn,repid,$j)
q ret
}
Soap代理类
Class LIS.WS.DHCLISServiceSoap Extends %SOAP.WebClient [ ProcedureBlock ]
{
/// This is the URL used to access the web service.
Parameter LOCATION = "http://127.0.0.1:57772/imedicallis/csp/LIS.WS.DHCLISService.cls";
/// This is the namespace used by the Service
Parameter NAMESPACE = "http://tempuri.org";
/// Use xsi:type attribute for literal types.
Parameter OUTPUTTYPEATTRIBUTE = 1;
/// Determines handling of Security header.
Parameter SECURITYIN = "ALLOW";
/// This is the name of the Service
Parameter SERVICENAME = "LISService";
/// This is the SOAP version supported by the service.
Parameter SOAPVERSION = 1.1;
/// webservice地址http://127.0.0.1:57772/imedicallis/csp/LIS.WS.DHCLISService.cls?wsdl=1&CacheUserName=yonghu&CachePassword=mima
Property Address As %String;
Method ExcMethod(ClassName As %String, FuncName As %String, P0 As %String, P1 As %String, P2 As %String, P3 As %String, P4 As %String, P5 As %String, P6 As %String, P7 As %String, P8 As %String, P9 As %String, P10 As %String, P11 As %String, P12 As %String, P13 As %String, P14 As %String) As %String [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
Quit ..WebMethod("ExcMethod").Invoke($this,"http://tempuri.org/LIS.WS.DHCLISService.ExcMethod",.ClassName,.FuncName,.P0,.P1,.P2,.P3,.P4,.P5,.P6,.P7,.P8,.P9,.P10,.P11,.P12,.P13,.P14)
}
Method GetData(ClassName As %String, FuncName As %String, Param As %String(MAXLEN=99999999), Session As %String(MAXLEN=1000)) As %String [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
s User=""
s Pwd=""
//判断地址是否包含密码
i ..Address["?" d
.s AddressNew=$REPLACE(..Address,"&","&")
.s PassInfo=$p(AddressNew,"?",2)
.f i=1:1:$l(PassInfo,"&") d
..s OnePStr=$p(PassInfo,"&",i)
..s PCode=$p(OnePStr,"=",1)
..s PVal=$p(OnePStr,"=",2)
..i PCode="CacheUserName" d
...s User=PVal
..i PCode="CachePassword" d
...s Pwd=PVal
//webservice是2016库使用
i $l(User) d ..WSSecurityLogin(User,Pwd)
s $this.Location=$p(AddressNew,"?",1)
Quit ..WebMethod("GetData").Invoke($this,"http://tempuri.org/LIS.WS.DHCLISService.GetData",.ClassName,.FuncName,.Param,.Session)
}
Method GetLabTrakData(ClassName As %String, FuncName As %String, P0 As %String, P1 As %String, P2 As %String, P3 As %String) As %String [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
Quit ..WebMethod("GetLabTrakData").Invoke($this,"http://tempuri.org/LIS.WS.DHCLISService.GetLabTrakData",.ClassName,.FuncName,.P0,.P1,.P2,.P3)
}
Method GetLabTrakQuery(ClassName As %String, FuncName As %String, P0 As %String, P1 As %String, P2 As %String, Output rset As %XML.DataSet) As %String [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
Quit ..WebMethod("GetLabTrakQuery").Invoke($this,"http://tempuri.org/LIS.WS.DHCLISService.GetLabTrakQuery",.ClassName,.FuncName,.P0,.P1,.P2,.rset)
}
Method GetSQLData(SQLText As %String(MAXLEN=100000), Param As %String(MAXLEN=100000), Session As %String(MAXLEN=100000)) As %String [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
Quit ..WebMethod("GetSQLData").Invoke($this,"http://tempuri.org/LIS.WS.DHCLISService.GetSQLData",.SQLText,.Param,.Session)
}
}
这样需要跨库执行M就方便了,不需要特殊配置,测试代码示例:
Class LIS.WS.DHCRemoteCallTest Extends %RegisteredObject
{
/// 测试远程数据库是否能访问,可以访问返回1
/// w ##class(LIS.WS.DHCRemoteCallTest).CallTestMTHD("")
ClassMethod CallTestMTHD(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, Sessions, Output RowCount As %String) As %String
{
//远程webservice地址
s Address="http://192.168.23.234:57772/imedicallis/csp/LIS.WS.DHCLISService.cls?wsdl=1&CacheUserName=yonghu&CachePassword=mima"
//先测试远程执行是否可用
s dbActive=##class(LIS.WS.DHCLISServiceBase).RemoteGetData(Address,"LIS.WS.DHCLISServiceBase","RemoteCacheActiveTestMTHD","")
//数据库可用的话调用业务M
i dbActive="1" d
.//查询检验仪器列表,以JSON格式返回。可以调用任意符合检验M参数的方法和Qry
.s qcMachine=##class(LIS.WS.DHCLISServiceBase).RemoteGetData(Address,"Service.LIS.QC.DHCQCService","GetMachineList","")
.zw qcMachine
.s sp=""
.zw sp
.zw sp
.zw sp
.//查询检验仪器列表,以XML格式返回。可以调用任意符合检验M参数的方法和Qry
.s qcMachine=##class(LIS.WS.DHCLISServiceBase).RemoteGetData(Address,"Service.LIS.QC.DHCQCService","GetMachineList","","","","","","","","","","","","","","","","XML")
.zw qcMachine
q ""
}
}
效果
DHC-LISDATA>w ##class(LIS.WS.DHCRemoteCallTest).CallTestMTHD("")
qcMachine="[{""Code"":""1"",""Name"":""0319Test"",""HospitalCode"":""DHSZHYYZY""},{""Code"":""2"",""Name"":""0508质控测试"",""HospitalCode"":""DHSZHYYZY""},{""C ode"":""4"",""Name"":""tyu测试仪器"",""HospitalCode"":""DHSZHYYZY""},{""Code"":" "6"",""Name"":""0906质控测试"",""HospitalCode"":""DHSZHYYZY""},{""Code"":""7""," "Name"":""微生物仪器1"",""HospitalCode"":""DHSZHYYZY""},{""Code"":""8"",""Name"" :""西门子"",""HospitalCode"":""DHSZHYYZY""},{""Code"":""9"",""Name"":""海尔血球 仪"",""HospitalCode"":""DHSZHYYZY""}]" sp=""
sp=""
sp=""
qcMachine="<Response><GetMachineListResult><s:schema id=""DefaultDataSet"" xmlns="""" attributeFormDefault=""qualified"" elementFormDefault=""qualified"" xmlns:s=""http://www.w3.org/2001/XMLSchema"" xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata""><s:element name=""DefaultDataSet"" msdata:IsDataSet=""true""><s:complexType><s:choice maxOccurs=""unbounded""><s:element name=""GetMachineList""><s:complexType><s:sequence><s:element name=""Code""/><s:element name=""Name""/><s:element name=""HospitalCode""/></s:sequence></s:complexType></s:element></s:choice></s:complexType></s:element></s:schema><GetMachineList><Code>1</Code><Name>0319Test</Name><HospitalCode>DHSZHYYZY</HospitalCode></GetMachineList><GetMachineList><Code>2</Code><Name>0508质控测试</Name><HospitalCode>DHSZHYYZY</HospitalCode ></GetMachineList><GetMachineList><Code>4</Code><Name>tyu测试仪器</Name><Hospita lCode>DHSZHYYZY</HospitalCode></GetMachineList><GetMachineList><Code>6</Code><Name>0906质控测试</Name><HospitalCode>DHSZHYYZY</HospitalCode></GetMachineList><Ge tMachineList><Code>7</Code><Name>微生物仪器1</Name><HospitalCode>DHSZHYYZY</Hosp italCode></GetMachineList><GetMachineList><Code>8</Code><Name>西门子</Name><Hosp italCode>DHSZHYYZY</HospitalCode></GetMachineList><GetMachineList><Code>9</Code><Name>海尔血球仪</Name><HospitalCode>DHSZHYYZY</HospitalCode></GetMachineList></ GetMachineListResult><RetVal>0</RetVal><Error></Error><Node>GetMachineList</Node><RowCount>7</RowCount><ResType>0</ResType><RetSession></RetSession></Response>"
DHC-LISDATA>
多备点基础方法,总有机会用到的。