房屋贷款案例介绍
IT技术本质上都是为业务服务的,只有真正理解了业务,才能真正理解IT。下面将详细介绍房屋贷款业务的来龙去脉。
1.案例的由来
目前我国的房价正在以飞快的速度上涨,这与“炒房者”一人拥有多套房子不无关系,其实大部分“炒房者”大都是用银行贷款的钱在“炒房”,这与我国目前的银行贷款政策不无关系。目前我国的银行房屋贷款政策对购买一套房和多套房的首付和贷款利率是一样的,这样银行政策是将“炒房者”和“真正的购房者”置于同等的地位,为“炒房者”提供了机会,使他们能够“以小搏大”,以少量的首付贷款得到房子,然后倒手得到巨大的差价。
银行应该根据“购房者”目前的拥有的房屋数量提供不同的首付比例和贷款利率。房屋数量为0的客户应该得到最小的首付比例和最低的贷款利率;然后根据客户的房屋数量依次相应提高首付比例和贷款利率,这样应该能够起到平抑房价的作用。下面的实例假定银行政策已经这么执行了。
2.业务现状
目前有5个独立的Web Service,它们相互之间互不知道,也不能互相调用。
3.业务需求
在完全不影响上面的5个Web Service正常运行的情况下,包括不修改上面5个Web Service的任何代码的情况下,将上面的5个Web Service集成起来。这个新的系统只需要输入用户姓名,这个系统会首先自动查出客户的房屋数量,然后自动转到相应的银行进行房屋贷款服务,客户最后可以得到对应于他的目前已有房屋数量的贷款首付和贷款利率。
4.实现流程
图1显示了用BPEL实现的业务流程,具体过程如下。
(1)BPEL将首先以客户姓名name作为输入变量,调用HouseLoanAgency的Web Service,得到客户的目前拥有的房屋数量。
(2)如果客户房屋数量为0,BPEL将调用Bank0的服务;如果客户房屋数量为1,BPEL将调用Bank1的服务;如果客户房屋数量为2,BPEL将调用Bank2的服务;如果客户房屋数量大于2,BPEL将调用Bank3的服务。
(3)BPEL将从Bank返回的首付比率和贷款利率返回给服务请求者。

图1 通过BPEL实现房屋贷款业务
定义BPEL流程的接口WSDL
定义BPEL流程的接口WSDL主要有两个目的:
(1)让客户端知道如何使用相应的组织数据来调用这个BPEL服务。例如下面的接口portType 名称为“HouseLoanBroker”;其下的输入input为“tns:getLoanQuoteRequest”,其中“tns”为命名空间“urn:sample:soa:houseloanbroker”;getLoanQuoteRequest下面含有元素“name”;总的结构如下:
HouseLoanBroker(portType)
|――tns:getLoanQuoteRequest (input)
|――name (String)
这样客户端可以创建响应的SOAP请求消息:
|
<getLoanQuoteRequest xmlns='urn:sample:soa:houseloanbroker'> |
(2)BPEL引擎可以根据请求消息创建相应的BPEL实例,执行BPEL流程。例如:
BPEL在收到上面的服务请求后,根据命名空间“urn:sample:soa:houseloanbroker”和请求消息“getLoanQuoteRequest”,就知道创建和执行该BPEL流程houseloanbroker。
例程1显示了BPEL流程的接口WSDL文件。
例程1 houseloanbroker.wsdl
|
<?xml version="1.0" encoding="UTF-8"?> <definitions targetNamespace="urn:sample:soa:houseloanbroker" xmlns:tns="urn:sample:soa:houseloanbroker" xmlns:typens="urn:sample:soa:houseloanbroker:types" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"> <import namespace="urn:sample:soa:houseloanagency" location="houseloanagency.wsdl" /> <import namespace="urn:sample:soa:bank" location="bank.wsdl" /> <!-- type defs --> <types> <xsd:schema targetNamespace="urn:sample:soa:houseloanbroker:types" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="getLoanQuoteRequest"> <xsd:sequence> <xsd:element name="name" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getLoanQuoteResponse"> <xsd:sequence> <xsd:element name="rate" type="xsd:double" /> <xsd:element name="firstpaidratio" type="xsd:double" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="unknownNAMEFault"> <xsd:sequence> <xsd:element name="name" type="xsd:string" /> </xsd:sequence> </xsd:complexType>
</xsd:schema> </types> <message name="getLoanQuoteRequest"> <part name="payload" type="typens:getLoanQuoteRequest" /> </message> <message name="getLoanQuoteResponse"> <part name="payload" type="typens:getLoanQuoteResponse" /> </message> <message name="unknownNAMEFault"> <part name="payload" type="typens:unknownNAMEFault" /> </message> <portType name="HouseLoanBroker"> <operation name="getLoanQuote"> <input message="tns:getLoanQuoteRequest" /> <output message="tns:getLoanQuoteResponse" /> <fault name="UnknownNAME" message="tns:unknownNAMEFault" /> </operation> </portType> <plnk:partnerLinkType name="HouseLoanBrokerPL"> <plnk:role name="HouseLoanBrokerService" portType="tns:HouseLoanBroker" /> </plnk:partnerLinkType> <binding name="HouseLoanBroker" type="tns:HouseLoanBroker"> <operation name="request"></operation> </binding> <service name="HouseLoanBrokerService"> <port name="houseloanbroker" binding="tns:HouseLoanBroker" /> </service> </definitions> |
外部服务合作伙伴的WSDL
下面是BPEL需要调用的外部服务houseloanagency的WSDL文件,这个外部服务接收顾客姓名,输出顾客已有的房屋数量。通过这个WSDL,BPEL可以知道所要调用的外部服务的接口、接口操作、输入消息和输出消息、异常,这都是BPEL流程在调用外部服务时需要知道的,对于houseloanagency.wsdl,这些参数如下。
接口:HouseLoanAgency;
接口操作:getHouseNumber;
输入消息为下面的树状结构:
getHouseNumberRequest
|――name (String)
l 输出消息为下面的树状结构:
getHouseNumberResponse
|――housenumber (int)
l 异常:unknownNAMEFault。
此外,BPEL需要引入该WSDL,并定义该服务为合作伙伴,所以还需要在此加入合作伙伴的定义。
<plnk:partnerLinkType name="HouseLoanAgencyPL">
<plnk:role name="HouseLoanAgencyService" portType="tns:HouseLoanAgency" />
</plnk:partnerLinkType>
上面portType="tns:HouseLoanAgency"指该合作伙伴所对应的WSDL的接口。BPEL的一个合作伙伴,对应于WSDL的一个接口。如果WSDL有多个接口,则需要定义多个合作伙伴。
例程2显示了houseloanagency.wsdl的内容。
例程2 houseloanagency.wsdl
|
<?xml version="1.0" encoding="UTF-8"?> <definitions targetNamespace="urn:sample:soa:houseloanagency" xmlns:tns="urn:sample:soa:houseloanagency" xmlns:typens="urn:sample:soa:houseloanagency:types" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"> <types> <xsd:schema targetNamespace="urn:sample:soa:houseloanagency:types" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="getHouseNumberRequest"> <xsd:sequence> <xsd:element name="name" type="xsd:string" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getHouseNumberResponse"> <xsd:sequence> <xsd:element name="housenumber" type="xsd:int" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="unknownNAMEFault"> <xsd:sequence> <xsd:element name="name" type="xsd:string" /> </xsd:sequence> </xsd:complexType> </xsd:schema> </types> <message name="getHouseNumberRequest"> <part name="payload" type="typens:getHouseNumberRequest" /> </message> <message name="getHouseNumberResponse"> <part name="payload" type="typens:getHouseNumberResponse" /> </message> <message name="unknownNAMEFault"> <part name="payload" type="typens:unknownSSNFault" /> </message> <portType name="HouseLoanAgency"> <operation name="getHouseNumber"> <input message="tns:getHouseNumberRequest" /> <output message="tns:getHouseNumberResponse" /> <fault name="UnknownNAME" message="tns:unknownNAMEFault"/> </operation> </portType> <plnk:partnerLinkType name="HouseLoanAgencyPL"> <plnk:role name="HouseLoanAgencyService" portType="tns:HouseLoanAgency" /> </plnk:partnerLinkType> </definitions> |
下面是所要调用的4个Bank的服务,它们的服务接口一样,只是输出结果的首付比例和贷款比例不同,所以采用同一个WSDL文件即可,但是在BPEL中需要定义4个合作伙伴,这4个合作伙伴所指向的服务地址是不同的,Bank的WSDL内容如下。
接口:Bank;
接口操作:getLoanQuote;
输入消息为如下树状结构;
getLoanQuoteRequest
|――housenumber(int)
l 输出消息为如下的树状结构:
getHouseNumberResponse
|――rate (double)
|――firstpaidratio (double)
此外,BPEL需要引入该WSDL,并定义该服务为合作伙伴,所以还需要在此加入合作伙伴定义:
<plnk:partnerLinkType name="BankPL"> <plnk:role name="BankService" portType="tns:Bank" /> </plnk:partnerLinkType>
例程3显示了bank.wsdl的内容。
例程3 bank.wsdl
|
<?xml version="1.0" encoding="UTF-8"?> <definitions targetNamespace="urn:sample:soa:bank" xmlns:tns="urn:sample:soa:bank" xmlns:typens="urn:sample:soa:bank:types" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"> <types> <xsd:schema targetNamespace="urn:sample:soa:bank:types" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="getLoanQuoteRequest"> <xsd:sequence> <xsd:element name="housenumber" type="xsd:int" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getLoanQuoteResponse"> <xsd:sequence> <xsd:element name="rate" type="xsd:double" /> <xsd:element name="firstpaidratio" type="xsd:double" /> </xsd:sequence> </xsd:complexType> </xsd:schema> </types> <message name="getLoanQuoteRequest"> <part name="payload" type="typens:getLoanQuoteRequest" /> </message> <message name="getLoanQuoteResponse"> <part name="payload" type="typens:getLoanQuoteResponse" /> </message> <portType name="Bank"> <operation name="getLoanQuote"> <input message="tns:getLoanQuoteRequest" /> <output message="tns:getLoanQuoteResponse" /> </operation> </portType> <plnk:partnerLinkType name="BankPL"> <plnk:role name="BankService" portType="tns:Bank" /> </plnk:partnerLinkType> </definitions> |