搭建一个在线广告营销系统,离不开第三方的支持。而使用第三方提供的API,是一个非常不错的解决方案。
Google提供的Adwords API是一个跨语言的,支持基本所有的主流编程语言。
本文分为四个部分,首先讲解Adwords API是如何做到跨语言的;然后分别讲解Java版本的Client是如何工作的,以及作为开发人员,如何改进和扩展这个API;最后讲解我们在实际的应用中,都遇到了哪些问题。
WebService与AXIS
WebService
使用WebService,是Adwords API能够实现跨语言的原因。简单来说,我们可以这样理解WebService:
客户端(Client)与服务端(Server)之间使用SOAP协议进行通信,这和我们熟悉的HTTP通信非常类似,Client发送一个SOAP请求到Server,Server接受到请求后,开始计算,然后将计算的结果返回给Client。
这是一个SOAP请求:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns="https://adwords.google.com/api/adwords/v8">
<soap:Header>
<email>loginemail@youraccount.com</email>
<password>secretpassword</password>
<useragent>Your User Agent description</useragent>
<developerToken>_developer_token_here_</developertoken>
<applicationToken>_application_token_here_</applicationtoken>
</soap:Header>
<soap:Body>
<estimateKeywordList>
<keywordRequests>
<type>Broad</type>
<text>flowers</text>
<maxCpc>50000</maxCpc>
</keywordRequests>
</estimateKeywordList>
</soap:Body>
</soap:Envelope>
这是一个SOAP应答:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<responseTime
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns="https://adwords.google.com/api/adwords/v8">
10636
</responseTime>
<operations
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns="https://adwords.google.com/api/adwords/v8">
1
</operations>
<units
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns="https://adwords.google.com/api/adwords/v8">
1
</units>
<requestId
soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"
soapenv:mustUnderstand="0"
xmlns="https://adwords.google.com/api/adwords/v8">
eb21e6667abb131c117b58086f75abbd
</requestId>
</soapenv:Header>
<soapenv:Body>
<estimateKeywordListResponse
xmlns="https://adwords.google.com/api/adwords/v8">
<estimateKeywordListReturn>
<avgPosition>2.9376502</avgPosition>
<cpc>50000</cpc>
<ctr>0.01992803</ctr>
<id>-1</id>
<impressions>62823</impressions>
<notShownPerDay>139255</notShownPerDay>
</estimateKeywordListReturn>
</estimateKeywordListResponse>
</soapenv:Body>
</soapenv:Envelope>
上面这2个SOAP的示例,就是我们的应用程序利用Adwords API与Google Adwords实际的数据交互情况。
那么,当API非常复杂的时候将会出现什么问题?我们不可能记住所有的方法参数、类定义等等。这个时候,我们需要一个标准的定义文件,用来描述某一个WebService可以提供哪些方法,复杂的数据结果是如何定义的,这个文件就是WSDL(Web Services Definition Language)。我们可以看看一个简单的WSDL定义:
<element name="getName">
<complexType>
<sequence>
<element name="adgroupID" type="xsd:int" />
</sequence>
</complexType>
</element>
<element name="getNameResponse">
<complexType>
<sequence>
<element name="getNameReturn" type="xsd:string" />
</sequence>
</complexType>
</element>
<wsdl:message name="getNameRequest">
<wsdl:part element="impl:getName" name="parameters" />
</wsdl:message>
<wsdl:message name="getNameResponse">
<wsdl:part element="impl:getNameResponse" name="parameters" />
</wsdl:message>
这个WSDL文件定义了这个WebService支持的操作。Adwords API为每一个Service提供了一个WSDL的定义文件,如:https://adwords.google.com/api/adwords/v13/AdService?wsdl
AXIS
如果我们直接在浏览器里面访问https://adwords.google.com/api/adwords/v13/AdService 我们会发现浏览器中出现了这样的字样:
v13/AdService
Hi there, this is an AXIS service!
Perhaps there will be a form for invoking the service here...
这个提示暗示我们:Adwords API的Server端是使用AXIS开发的。
AXIS是Apache下面的一个用于开发WebService应用的框架,具体的使用可以参考它的User Guide。
在使用AXIS开发WebService应用中,有一点非常值得我们注意的:使用WSDL驱动WebService开发,大体流程是这样的:
- 编写WSDL文件。
- 使用WSDL2Java,自动生成WSDL中定义的数据代码。
- 编写每一个方法的实现。
- 部署服务器。
注意使用WSDL2Java工具根据WSDL文件自动生成的代码,这些代码就是Client与Server之间的协议实现,在两边都会有使用。
Google Adwords API内部构成
Java版本的Adwords API主要有两种类型的发型版本:
- adwords-api-X.X.X-loner.tar.gz
- adwords-api-X.X.X.tar.gz
其中带-loner标识的版本只包含Google发布的代码,而不带-loner标识的版本不仅包含了Google发布的代码,同时包含了Adwords API依赖的所有第三方库,其中当然包括AXIS。
我们打开adwords-api-6.3.0-loner可以看到4个主要的包:
- com.google.api.adwords.lib
- com.google.api.adwords.v13
- com.google.api.adwords.v200906
- com.google.api.adwords.v200909
其中的2,3,4包都是根据Adwords的WSDL自动生成的代码,用于和Adwords的数据交互,我们开发人员无需关心。
- 在com.google.api.adwords.lib中,主要包含以下功能:
- AdWordsServiceLogger:定义了SOAP交互的日志功能。
- AdWordsUser,AdWordsVersion,AuthToken,AdWordsService,AdWordsServiceFactory:定义了调用指定WebService对象的实现。
- ServiceAccountant,ServiceAccountantRecord,ServiceAccountantManager:定义了记录SOAP日志的策略以及统计Adwords API的使用情况(使用了多少Quota,Response Time)。
- AdWordsHttpSender:定义了与Adwords交互的策略,这个类是我们对Adwords API进行改进与扩展的关键。
其中还有一个非常重要的AXIS的Client端配置信息,硬编码在代码中的:
<?xml version='1.0'?>
<deployment name='defaultClientConfig' xmlns='http://xml.apache.org/axis/wsdd/'
xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'>
<globalConfiguration>
<parameter name='disablePrettyXML' value='true' />
</globalConfiguration>
<!-- Define the Google Adwords communication strategy -->
<transport name='http' pivot='java:com.google.api.adwords.lib.AdWordsHttpSender' />
<transport name='local' pivot='java:org.apache.axis.transport.local.LocalSender' />
<transport name='java' pivot='java:org.apache.axis.transport.java.JavaSender' />
</deployment>
结合这个配置信息,就非常好理解AdWordsHttpSender的作用了。
AdWordsHttpSender究竟做了哪些事情,这是它的实现代码:
super.invoke(msgContext);
3: ServiceAccountantManager.getInstance().recordMessage(msgContext);
4: }