内容


构建 Amazon 店面

Comments

介绍

我应该学习本教程吗?

本教程适合于想使用 SOAP 来通过 Amazon Web 服务(Amazon Web Services,AWS)访问 Amazon 产品数据库的开发者。它为您展示如何使用 IBM WebSphere SDK for Web Services(WSDK)来从 Amazon Web 服务描述语言(Web Services Description Language,WSDL)文件创建 Java 类,演示这些类的使用,然后分析使用 WSDK 来把这些类变成 Web 应用程序和 Amazon 店面的过程。

开发者至少应在整体上对 Web 服务有一个基本的理解并熟悉 Java 编程语言。对 HTML 和 servlet 的理解有助于学习有关创建 Web 应用程序的最后一部分,但不必理解 Web 服务客户机本身。

本教程有哪些内容?

Amazon.com 创建的 AWS 把数据公开在巨大的 Amazon 产品数据库供任何感兴趣的人访问它。AWS 使开发者能够创建自动查询 Amazon 数据库的信息(例如标题、定价、产品描述、用户评价甚至相似的产品)的动态 Web 站点、创建 Web 店面或其他应用程序。

有两种风格的 AWS:SOAP 和 XML/HTTP。如果选择的是 SOAP,那么,请求被编码成 SOAP 消息并被发送到 Amazon 服务器,然后 Amazon 服务器通过 SOAP 消息返回被请求的信息。接着,应用程序可以抽取信息并恰当地对待它(或者处理它,或者仅仅在 Web 页面或其他界面上显示它)。如果选择的是 XML/HTTP,那么,特定构造的 URL 通过 XML 文件来返回信息,然后开发者可以使用 XSL 转换(XSL Transformations,XSLT)来转换该 XML 文件以形成所需的 Web 页面。本教程演示使用 SOAP 的 AWS 访问。

本教程讨论如何使用 WSDK 中提供的工具来创建访问 Amazon 数据库的基于 Web 的店面。它包括以下主题:

  • 安装 WSDK。
  • 使用 wsdl2java 来从 Amazon WSDL 文件创建类。
  • 创建访问 Web 服务的应用程序。
  • 进行搜索、浏览类别和访问 Listmania 列表。
  • 把信息添加到 Amazon 购物车、愿望列表和礼物注册中心。
  • 使 WSDK 与 Web 应用程序服务器(例如 WebSphere 或 Tomcat)集成。
  • 通过使用 servlet 利用 Web 服务客户机来创建店面。

工具

在开始学习本教程前请您确保安装并测试以下工具:

您可以下载本教程中示例的源代码:storefront.zip

Amazon Web 服务是什么?

Amazon 数据库和店面

自从 Amazon.com 在几年前建立以来,它不仅试图拥有最多的在线销售的图书,还试图拥有许多其他产品系列(例如电子产品、玩具和音乐)。然而,Amazon 的战略不只是销售产品,还要通过特色(例如产品评价和提供基本销售跟踪信息)为消费者提供更多价值。例如,消费者可以通过查看购买当前产品的客户购买的其他产品来找到与当前产品相似的产品(或至少很可能迎合他们的品味)。

所有这一切对消费者是有用的,但是,对于试图销售产品的人来说也是有用的。在过去的几年里,这不仅包括 Amazon.com 自身,还包括 Amazon 伙伴 ― 把用户从自己的 Web 站点介绍到 Amazon 的个人和小公司,然后接收任何销售的一部分。多数伙伴仅仅是创建把对某个物品的引用链接回 Amazon 站点的页面,但是有些伙伴创建包括多个产品类的整个店面。

然而,创建这样的店面是日常工作;此外,伙伴甚至不能列出价格,因为它们变得太快。但是,Amazon Web 服务在此基础上作了很大的改进。

Amazon Web 服务

AWS 项目原先被称为“伙伴的 XML”,但是任何人可以访问数据以用于几乎任何目的。AWS 使开发者能够创建动态调用 Amazon 数据库并实时接收响应的应用程序或 Web 站点,这样,信息总是最新的。

AWS 的最常见的用途是创建店面,但是也可以用于许多其他用途,例如为用户提供动态搜索关于某个主题的资源而不离开当前的站点的功能,或提供某个艺术家的 CD 的链接或某个制造商的产品的链接。新的用途正在不断地出现,例如使用 Amazon 的电影列表的“Six Degrees of Kevin Bacon”游戏。

AWS 使任何请求“开发者令牌(developer's token)”(类似于许可证密钥)的人免费地使用这些信息。您可以决定如何使用这些信息。

访问选项

当 Amazon 开发者在创建 AWS 时,他们在访问信息时有两个不同的选择:XML/HTTP 和 SOAP。他们发现开发者无法就哪个更有用这个问题达成一致意见,所以他们决定提供两种选择,而这仅作为解决争执的方式。

在使用 XML/HTTP 时,开发者检索类似于

http://xml.amazon.com/onca/xml?v=1.0&t=webservices-20&dev-t=00000000000000
&KeywordSearch=food&mode=books&type=lite&page=1&f=xml

的 URL 的内容,然后解析文件以抽取信息或使用 XSLT 来创建实际的 Web 页面。

在使用 SOAP 时,开发者把与下面消息类似的 SOAP 消息发送给 AWS,然后接收有产生的数据的 SOAP 响应。

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope  
       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
      <namesp1:KeywordSearchRequest 
               xmlns:namesp1="urn:PI/DevCentral/SoapService">
         <KeywordSearchRequest xsi:type="m:KeywordRequest">
             <keyword >food</keyword>
             <page >1</page>
             <mode >books</mode>
             <tag >webservices-20</tag>
             <type >lite</type>
             <dev-tag >00000000000000</dev-tag>
             <format >xml</format>
             <version >1.0</version>
         </KeywordSearchRequest>
      </namesp1:KeywordSearchRequest>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这些消息很适合 XML 数据绑定,在这种绑定中,XML 由对象来表示并可由程序来处理。在某些方面,这要比仅仅使用 XSLT 样式表更复杂,但更有助于程序分析和数据使用。

本教程分析使用数据的 SOAP 方法。

使用时的注意事项

在申请开发者令牌或下载 AWS 工具箱时(对于本教程来说是不必要的),Amazon 将给您完整的许可证协议,该协议说明了您可以把在 AMS 的调用中检索到的数据用于哪些目的,不可以用于哪些目的。这里的讨论是为了使您对我在写本教程时已有的限制有一个大致的了解且不应取代对许可证协议的仔细审阅。

总的来说,该许可证协议明确指出某些活动是不允许的。开发者除了知道 Amazon 所坚持的“数据不应被用来贬低 Amazon.com 或与它竞争”(这一点相当明显),还应把以下限制放在心上:

  • 您可以把数据存入高速缓存,但只能保存 24 小时,而且您不能把它存储在共享的数据库中。
  • 您必须至少每小时刷新一次价格。
  • 一个开发者每秒只能对 AWS 调用一次。
  • 请求和响应不能超过 20K。

如果您对您的应用程序是否以可接受的方式使用数据存有疑问,请通过 webservices@amazon.com 与 Amazon Web 服务联系。

安装

下载和安装 WSDK

WSDK 包括几个创建和使用 Web 服务的工具,其中的工具可用于搜索和发布到 UDDI 目录、组合 Web 服务并把它部署到简单的内置应用程序服务器和使用组成现有的 Web 服务的 Java 类来创建 WSDL 文件。它甚至还包括本地的 UDDI 注册中心以用于测试、搜索和发布应用程序。本教程把重点放在 wsdl2java 工具上,该工具能自动地根据服务的 WSDL 文件为某个 Web 服务客户机创建类。

为了准备使用 WSDK,请执行以下步骤:

  1. 下载 WSDK(请参阅工具中的链接)。
  2. 在 Windows 上,您只需执行该文件,然后重新引导机器。在 Linux 上,解压缩该文件,然后以 root 用户的身份登录并运行包含的脚本 installln32.sh
  3. 通过运行 WSDK bin 目录中的 wsdkconfig.bat(或 wsdkconfig.sh)脚本来配置应用程序。请接受缺省值。
  4. 启动包含的应用程序服务器的方法是通过使用 cd 命令进入 bin 目录然后输入 appserver start。(在 Linux 系统上,请以 root 的身份来启动服务器。)
  5. 为了确认服务器正确地运行,请执行(主要的 WSDK 目录中)位于 StartHere.htm 的开始页面所链接的一个演示。

额外的库

为了使用 AWS,当前版本的 WSDK 需要额外的库。为了完成安装,请执行以下步骤:

  1. 请备份以下文件(假设 %WSDK_HOME% 是 WSDK 的安装目录):
    %WSDK_HOME%\lib\wsdl4j.jar
    %WSDK_HOME%\axis\lib\axis.jar
    %WSDK_HOME%\axis\lib\jaxrpc.jar
  2. 下载 wsdk_additional.zip 文件并解压它。
  3. 把新的 wsdl4j.jar 文件复制到 %WSDK_HOME%/lib
  4. 把新的 axis.jarjaxrpc.jarsaaj.jar 文件复制到 %WSDK_HOME%\axis\lib
  5. 在文本编辑器中打开 %WSDK_HOME%\bin\wsdkenv.bat 并找到标记为“rem Axis begin”的部分。把下面一行添加到该部分:
set WSDK_CP=%WSDK_CP%;%WSDK_HOME%\axis\lib\saaj.jar

WSDK 的安装已完成,下一步是满足 Amazon 的要求。

获取开发者令牌和伙伴标识

为了执行查询,您至少需要获得开发者令牌。请访问 http://www.amazon.com/webservices,然后单击 Apply for a free developer's token

同样,任何人可以使用 AWS,但是如果您准备向 Amazon 发送任何流量,那么您应该申请自己的伙伴标识。如果您想获取有关信息和申请的链接,请访问 http://www.amazon.com/exec/obidos/subst/associates/join/associates.html。即使您对付给伙伴的佣金不感兴趣,拥有伙伴标识使您能够通过伙伴中心(Associates Central)为您的 Web 服务获取跟踪信息。

获取 WSDL 文件

Amazon 确实提供开发者工具箱,但是实际上您无需使用它来构建本教程中的应用程序。相反,请从 http://soap.amazon.com/schemas/AmazonWebServices.wsdl 下载 WSDL 文件。该文件包含有关服务的位置和它所期待的消息类型的信息。wsdl2java 工具将读取这些信息并使用它来创建表示请求和响应的 Java 类。

设置环境

在生成或使用任何类以前,您必须设置某些环境变量。请打开命令提示符并输入:

cd %WSDK_HOME%\bin
wsdkenv

(对于 Linux,别忘了使斜杠反向。)

该脚本为使用 WSDK 设置了所有必需的环境变量(有一个变量除外),但那个变量是很关键的 CLASSPATH。为了设置 CLASSPATH 变量以使它包含 WSDK 库,请输入(用于 Windows 系统):

set CLASSPATH=%WSDK_CP%;%CLASSPATH%

或(用于 Linux 系统):

set CLASSPATH=%WSDK_CP%;%CLASSPATH% 
export CLASSPATH

您可能还会发现把 WSDK 的 bin 目录添加到系统的路径是有用的。

在设置了环境变量后,系统就可以生成新的类。

生成类

环境变量被设置后,现在可以实际生成表示 AWS 客户机的类。

请您进入保存 WSDL 文件的目录并输入:

wsdl2java -p com.tutorials.amazon.aws AmazonWebServices.wsdl

-p 命令开关提供软件包的名称,所有生成的类将属于这个软件包。如果您不为这个命令开关提供值,那么那些类将成为 PI 软件包的一部分。

wsdl2java 生成完毕后,请编译那些类以确认 wsdl2java 正确地创建了所有的东西。请进入(*.java 文件所在的)soap 目录并输入:

javac *.java

如果任何类编译失败,请确保所有的环境变量被正确地设置。然而,如果所有的类被正确地编译,那么您可以开始进行搜索。

进行搜索

创建服务对象

当 WSDK 为 Web 服务客户机创建对象时,它创建表示服务本身的类并创建表示服务处理的请求和响应的类。使用这些类的第一步是通过使用定位器类来实例化服务本身。

请考虑访问 Web 服务的类的开头:

import  com.tutorials.amazon.aws.*;
        
public class AmazonSearch 
{ 
  public static void main( String [] args) throws Exception
  { 
     AmazonSearchServiceLocator AmazonServiceLocator=                                           new AmazonSearchServiceLocator();      AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();
        
  } 
}

首先,导入生成的类以使应用程序可以使用它们。然后,在 main() 方法中实例化 AmazonSearchServiceLocator 的对象 AmazonServiceLocator。该类包含有关服务的实际 URI 的信息。在这里,URI 是 http://soap.amazon.com/onca/soap,这与 WSDL 文件中指定的相同:

...
<service name="AmazonSearchService">
<port name="AmazonSearchPort" binding="typens:AmazonSearchBinding">
  <soap:address location="http://soap.amazon.com/onca/soap" /> 
  </port>
  </service>
...

接着,定位器实例化端口对象 AmazonSearchPort ,我们将在进行搜索中看到,该对象可以实际发送请求。然而,在发送请求前,您需要被发送的搜索请求。

创建关键字搜索请求

实际的搜索请求被表示成对象,如下所示:

import  com.tutorials.amazon.aws.*;

public class AmazonSearch
{
  public static void main( String [] args) throws Exception
  {
    java.io.PrintStream out= System.err;
    AmazonSearchServiceLocator AmazonServiceLocator= 
                                           new AmazonSearchServiceLocator();
    AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();

    KeywordRequest theRequest = new KeywordRequest();
    theRequest.setKeyword("xml");
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("00000000000000");
    theRequest.setPage("1");
    theRequest.setMode("books");
    theRequest.setType("heavy");
    theRequest.setVersion("1.0");
  }
}

这个示例显示的是使用方法来设置各种属性的 KeywordRequest。该请求在多数搜索中使用这些属性:

  • keyword:仅用于 KeywordRequest。请记住在发送 SOAP 请求时,keyword 只能是一个单词或由逗号分隔的几个单词。
  • tag:这是您的 Amazon 伙伴标识。如果您没有该标识,您可以使用一般标识 webservices-20
  • devtag:这是由 14 个数字组成的开发者令牌。
  • page:AWS 每次仅返回 10 个结果,所以如果您想要更多的结果,您必须通过指定页面编号来访问多个页面。
  • mode :Amazon 有许多不同的产品系列供选择,例如图书、音乐和电子产品等,详情请见产品方式
  • type :AWS 能返回两种类型的文档,一种是(包括许多额外材料(例如客户评价和类似产品)的)“重量级”文档,另一种是(只包括基本信息的)“轻量级”文档。如果您想获得更多信息,请参阅重量级与轻量级
  • version:在我写本教程时,所有的请求是 AWS 版本 1.0 的一部分。

有了请求后,您就可以把它发送给服务了。

进行搜索

进行搜索是很简单的事,您只需通过把 KeywordRequest 对象用作参数来执行关键字搜索:

import  com.tutorials.amazon.aws.*;
        
public class AmazonSearch 
{ 
  public static void main( String [] args) throws Exception
  { 
    java.io.PrintStream out= System.err;
    AmazonSearchServiceLocator AmazonServiceLocator= 
                                           new AmazonSearchServiceLocator();
    AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();
        
    KeywordRequest theRequest = new KeywordRequest();
    theRequest.setKeyword("xml"); 
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("000000000000000");
    theRequest.setPage("1");
    theRequest.setMode("books");
    theRequest.setType("heavy");
    theRequest.setVersion("1.0");
    theRequest.setFormat("book");
    ProductInfo result = searchSite.keywordSearchRequest(theRequest);      Details[] allDetails = result.getDetails();      int numResults = allDetails.length;      System.out.println("The search returned "+numResults+" products.");  
   } 
}

keywordSearchRequest() 方法取得请求对象(theRequest)并把它发送给服务。然后,服务本身返回响应,WSDK 将响应转换成 ProductInfo 对象。ProductInfo 对象包括一系列产品,每个产品可通过 Details 对象来访问。同样,getDetails() 方法返回由 Details 对象组成的数组。

运行该应用程序后应产生如下输出:

The search returned 10 products.

请注意,这个特定搜索的结果肯定远远不止 10 个产品,但是对于每次请求该数组最多只能显示 10 个搜索返回的结果。不幸的是,在我写本教程时,如果不取得多个页面的话,您无法确定总共有多少个结果。

Details 对象包括有关某个产品的信息。

简单产品的详细信息

有关每个产品的信息是该产品的 Details 对象的一部分。有些信息(例如产品的名称或列出的价格)被表示成简单的 String,您可以容易地使用类似 getListPrice() 的方法来检索它。其他信息(例如作者或客户评价)可能有多个条目,所以作为数组被返回。这个示例可显示查询返回的图书的基本信息:

... 
        
    Details[] allDetails = result.getDetails();
    int numResults = allDetails.length;
    System.out.println("The search returned "+numResults+" products.");
        
 for (int i = 0; i < numResults; i++) {  
                    
System.out.println("--------------------");  
Details thisDetails = allDetails[i];  
String title = thisDetails.getProductName();  
String asin = thisDetails.getAsin();  
String price = thisDetails.getListPrice();  
String amazonPrice = thisDetails.getOurPrice();  
System.out.println(title + " (" + asin +"): ");  
System.out.println("List price: "+price);  
System.out.println("Amazon's price: "+amazonPrice);  
                    
String[] allAuthors = thisDetails.getAuthors();  
for (int j = 0; j < allAuthors.length; j++) {  
   System.out.print (allAuthors[j] + " ");  
}  
System.out.println();  
    } 
        
  } 
}

执行该应用程序可显示有关每个产品的基本信息:

The search returned 10 products. 
-------------------- 
Web Design in a Nutshell (0596001967): 
List price: $29.95 
Amazon's price: $20.97 
Jennifer Niederst  
-------------------- 
The Guru's Guide to SQL Server Stored Procedures, XML, and HTML (With CD-ROM) 
(0201700468): 
List price: $49.99 
Amazon's price: $34.99 
Ken Henderson 
-------------------- 
Learning XML (0596000464): 
List price: $34.95 
Amazon's price: $24.47 
Erik T. Ray 
-------------------- 
Essential XML Quick Reference: A Programmer's Reference to XML, XPath, 
XSLT, XML Schema, SOAP, and More (0201740958): 
List price: $24.99 
Amazon's price: $17.49 
Aaron Skonnard and Martin Gudgin 
-------------------- 
Java & XML, 2nd Edition: Solutions to Real-World Problems (0596001975):
List price: $44.95 
Amazon's price: $31.47 
Brett McLaughlin 
-------------------- 
XSLT Programmer's Reference 2nd Edition (1861005067): 
List price: $34.99 
Amazon's price: $24.49 
Michael H. Kay 
...

为了防止 AWS 生成太长的文档,Amazon 把返回的每个产品的信息量限制在 10 个作者、(对于电影)10 个演员、(对于音乐)10 个艺术家、5 个类似产品和 3 个客户评价。

在有些情况下,数据本身可能是另一个对象,例如客户评价。

复杂数据

某些数据(例如客户评价)作为另一个对象(而不是 String)被返回。如下所示,访问这些信息是很简单的事,您只需重复用于检索更简单的产品数据的过程。

... 
        String[] allAuthors = thisDetails.getAuthors();
        for (int j = 0; j < allAuthors.length; j++) {
           System.out.print (allAuthors[j] + " ");
        } 
        System.out.println();
        
        Reviews overallReview = thisDetails.getReviews();          String avgReview = overallReview.getAvgCustomerRating();          CustomerReview[] allReviews = overallReview.getCustomerReviews();          for (int j = 0; j < allReviews.length; j++) {             CustomerReview thisReview = allReviews[j];             String rating = thisReview.getRating();             String summary = thisReview.getSummary();             String comment = thisReview.getComment();             System.out.println("*******");             System.out.println(summary + " ("+rating+")");             System.out.println(comment);          }  
    } 
  } 
}

在这里,Details 对象仅有一个 Reviews 对象,Reviews 对象有一个平均的客户评价的简单的 String 值和一系列 CustomerReview 对象。

选择的是重量级结果还是轻量级结果将决定被返回的数据结构。

重量级与轻量级

Amazon 提供两种不同的结果:重量级和轻量级(被 AWS 引用为“lite”)。重量级结果包括产品的所有可获得的信息(包括客户评价、与它关联的 Listmania! 列表等),轻量级结果只包括基本信息。

每个版本的 XML 模式和文档类型定义(Document Type Definitions,DTD)揭示了这两个版本之间的区别。您可以从以下位置下载它们:

轻量级 DTD:http://xml.amazon.com/schemas/dev-lite.dtd

重量级 DTD:http://xml.amazon.com/schemas/dev-heavy.dtd

轻量级 XML 模式:http://xml.amazon.com/schemas/dev-lite.xsd

重量级 XML 模式:http://xml.amazon.com/schemas/dev-heavy.xsd

区分这两个版本是很重要的,因为如果您请求轻量级文档然后试图检索不是该文档的一部分的数据,那么您将得到 NullPointerException

其他类型的搜索

产品方式

搜索结果只能来自一个产品系列(由 mode 参数来决定)。对于各个部门,mode 参数取以下值:

  • 婴儿用品:baby
  • 图书:books
  • 古典音乐:classical
  • DVD:dvd
  • 电子产品:electronics
  • 户外活动:garden
  • 厨房和家用器皿:kitchen
  • 杂志:magazines
  • 流行音乐:music
  • 计算机:pc-hardware
  • 照相机和照片:photo
  • 软件:software
  • 玩具和游戏:toys
  • 工具和五金:universal
  • 视频:vhs
  • 计算机和电子游戏:videogames

例如,有关太空的电子游戏的关键字搜索的创建可能与下面的代码相似:

    KeywordRequest theRequest = new KeywordRequest();
    theRequest.setKeyword("space");
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("00000000000000");
    theRequest.setPage("1");
    theRequest.setMode("videogames"); 
    theRequest.setType("heavy");
    theRequest.setVersion("1.0");

浏览类别

AWS 的一个常见用法是列出某个类别的产品以使用户能够单击某个产品的链接。发送这种类型的请求几乎与关键字搜索相同,这是因为一个简单的原因:AWS 执行的每个搜索返回一个 ProductInfo 对象,所以返回的数据类型不会改变。浏览类别与搜索关键字的唯一区别是前者涉及 BrowseNodeRequest 对象而不是 KeywordSearchRequest 对象:

import  com.tutorials.amazon.aws.*;

public class AmazonBrowse
{
  public static void main( String [] args) throws Exception
  {

    AmazonSearchServiceLocator AmazonServiceLocator= new AmazonSearchServiceLocator();
    AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();

    BrowseNodeRequest theRequest = new BrowseNodeRequest();
    theRequest.setBrowse_Node("25");
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("00000000000000");
    theRequest.setPage("1");
    theRequest.setMode("books");
    theRequest.setType("lite");
    theRequest.setVersion("1.0");
    ProductInfo result = searchSite.browseNodeSearchRequest(theRequest);

    Details[] allDetails = result.getDetails();
    int numResults = allDetails.length;

    for (int i = 0; i < numResults; i++) {

        Details thisDetails = allDetails[i];
        String title = thisDetails.getProductName();
        String asin = thisDetails.getAsin();
        System.out.println(title + " (" + asin +")");
    }
  }
}

该服务很聪明,它搞清了您想要什么并返回合适的数据。第 25 个类别是科幻小说和幻想作品,所以运行应用程序后产生的结果如下:

Morgawr (The Voyage of the Jerle Shannara, Book 3) (0345435729)
The Hobbit and The Lord of the Rings Boxed Set (0345340426)
Shadow Puppets (0765300176)
Crossroads of Twilight (The Wheel of Time, Book 10) (0312864590)
Harry Potter Paperback Boxed Set (Books 1-4) (0439434866)
The Hobbit and The Lord of the Rings (Boxed Set) (0618002251)
1984 (0451524934)
The Silmarillion (0345325818)
The Lord of the Rings (Leatherette Collector's Edition) (0395193958)
Brave New World (0060929871)

在取得 ASIN 编号后,您可以显示仅包括该产品的页面。

产品编号搜索,第 1 部分

在典型的“浏览”情形中,或者说当一个伙伴在试图出售某个产品时,能够取得某一个产品的信息而不是一组产品的信息是有用的。为了做到这一点,AWS 提供三种方式:用于图书的 ISBN 代码、用于音乐的 UPC 代码和所有产品(包括图书和音乐)的 ASIN 代码。ASIN 代码是 Amazon 的编号系统,对于图书来说,ASIN 代码与 ISBN 编号匹配。

同样,因为所有的搜索都返回一个 ProductInfo 对象,所以,即使(这里出现的就是这种情况)它是由一个对象组成的数组,它们都包括相同的 Details 对象。通过 ASIN 来请求产品信息的代码可能与下面的代码相似:

import  com.tutorials.amazon.aws.*;

public class AmazonASIN
{
  public static void main( String [] args) throws Exception
  {

    AmazonSearchServiceLocator AmazonServiceLocator= new AmazonSearchServiceLocator();
    AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();

    AsinRequest theRequest = new AsinRequest();
    theRequest.setAsin("0451524934");
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("00000000000000");
    theRequest.setType("heavy");
    theRequest.setVersion("1.0");
    ProductInfo result = searchSite.asinSearchRequest(theRequest);

    Details[] allDetails = result.getDetails();
    int numResults = allDetails.length;

    for (int i = 0; i < numResults; i++) {

        Details thisDetails = allDetails[i];
        String title = thisDetails.getProductName();
        String asin = thisDetails.getAsin();

        System.out.println(title + " (" + asin +")");
        String[] allAuthors = thisDetails.getAuthors();
        for (int j = 0; j < allAuthors.length; j++) {
           System.out.print (allAuthors[j] + " ");
        }
        System.out.println();

        String largeImage = thisDetails.getImageUrlLarge();
        String listPrice= thisDetails.getListPrice();
        String ourPrice = thisDetails.getOurPrice();
        String usedPrice = thisDetails.getUsedPrice();
        String refurbishedPrice= thisDetails.getRefurbishedPrice();
        String collectiblePrice= thisDetails.getCollectiblePrice();
        String thirdPartyNewPrice = thisDetails.getThirdPartyNewPrice();

        System.out.println("Image URL:" +largeImage);
        System.out.println("ListPrice: " +listPrice);
        System.out.println("OurPrice: " +ourPrice );
        System.out.println("UsedPrice: " +usedPrice );
        System.out.println("RefurbishedPrice: " +refurbishedPrice);
        System.out.println("CollectiblePrice: " +collectiblePrice);
        System.out.println("ThirdPartyNewPrice: " +thirdPartyNewPrice );

        System.out.println("\nThis product listed in:");
        BrowseNode[] otherCategories = thisDetails.getBrowseList();
        for (int j = 0; j < otherCategories.length; j++) {
            BrowseNode thisCategory = otherCategories[j];
            String catName = thisCategory.getBrowseName();
            String catId = thisCategory.getBrowseId();
            System.out.println(catName+" ("+catId+")");
        }

        System.out.println("\nOther users bought:");
        String[] otherUsersBought = thisDetails.getSimilarProducts();
        for (int j=0; j< otherUsersBought.length; j++){
            System.out.println(otherUsersBought[j]);
        }
        System.out.println();

        Reviews overallReview = thisDetails.getReviews();
        String avgReview = overallReview.getAvgCustomerRating();
        CustomerReview[] allReviews = overallReview.getCustomerReviews();
        for (int j = 0; j < allReviews.length; j++) {
           CustomerReview thisReview = allReviews[j];
           String rating = thisReview.getRating();
           String summary = thisReview.getSummary();
           String comment = thisReview.getComment();
           System.out.println("*******");
           System.out.println(summary + " ("+rating+")");
           System.out.println(comment);
        }


    }
  }
}

请注意,因为 ASIN 搜索仅仅返回某一个产品,所以它不再需要 pagemode 信息。另外,请注意,类别和相似产品的数据所包括的信息(browseIdasin)可被您在需要的情况下用来链接到更多信息。

产品编号搜索,第 2 部分

前面一页的应用程序被执行后将返回如下所示的结果:

1984 (0451524934)
George Orwell Erich Fromm
Image URL:http://images.amazon.com/images/P/0451524934.01.LZZZZZZZ.jpg
ListPrice: $6.95
OurPrice: $6.95
UsedPrice: $0.99
RefurbishedPrice: null
CollectiblePrice: $5.99
ThirdPartyNewPrice: $4.98
       
This product listed in:
Literature: Classics (null)
Literature - Classics / Criticism (null)
Fiction (null)
Classics (null)
Science Fiction - General (null)
       
Other users bought:
0060929871
0399501487
0440180295
0316769487
0451526341
       
*******
a must read (5)
This is a powerful book and a must read for everybody. While some may say this b
ook was written to criticize the corrupted Soviet empire, that is not true. Anim
al Farm was written for that purpose. This book was instead written to warn the
free world of totalitarianism, something that could easily happen anywhere in th
e world, even in democracies like the US, or England, the setting of the book. 
*******
Oh (Big) Where art thou? (4)
In today's technologically oriented world, people still seem shocked when movies
come out that portray governmental security that seemingly invades on the public
...

您还可以搜索某些产品属性。

强力搜索

AWS 还允许“强力搜索”,通过这种搜索,用户可以根据产品类型按作者、艺术家、导演、演员或制造商来搜索产品。同样,与所有的搜索相似,这些搜索返回 ProductInfo 对象,所以,您可以选择仅仅列出名称或标题,也可以选择包括所有的相关信息。例如,以下代码仅仅列出 Amazon.com 的数据库中第 1 至第 10 部由 Steven Spielberg 指导的 DVD:

import com.tutorials.amazon.aws.*;

public class AmazonDirector
{
  public static void main( String [] args) throws Exception
  {

    AmazonSearchServiceLocator AmazonServiceLocator= new AmazonSearchServiceLocator();
    AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();

    DirectorRequest theRequest = new DirectorRequest();
    theRequest.setPage("1");
    theRequest.setMode("dvd");
    theRequest.setDirector("Steven Spielberg");
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("00000000000000");
    theRequest.setType("lite");
    theRequest.setVersion("1.0");

    ProductInfo result = searchSite.directorSearchRequest(theRequest);

    Details[] allDetails = result.getDetails();
    int numResults = allDetails.length;

    for (int i = 0; i < numResults; i++) {

        Details thisDetails = allDetails[i];
        String title = thisDetails.getProductName();
        String asin = thisDetails.getAsin();

        System.out.println(title + " (" + asin +")");
    }
  }
}

执行该应用程序后显示的结果如下:

E.T. - The Extra-Terrestrial (Widescreen Collector's Edition) (B00003CX9Q)
Saving Private Ryan - DTS (B00001ZWUT)
Saving Private Ryan (B00001ZWUS)
Close Encounters of the Third Kind (The Collector's Edition) (B00003CX9G)
Hook (0767836324)
The Color Purple (0790729717)
Empire of the Sun (B00003CX9U)
E.T. - The Extra-Terrestrial (Full-Frame) (B0000696ID)
A.I. Artificial Intelligence (Widescreen Special Edition) (B00003CXXP)
Jurassic Park - Widescreen Collector's Edition (B00003CXAT)

通过使用 ASIN,您能够容易地链接到这些产品的信息页面。您还可以链接到用户提供的产品列表中的信息。

Listmania! 列表

Amazon 创建的一个方便用户的特色是用户创建他们喜爱的产品列表的能力。该站点在相关的搜索和产品旁显示这些列表。您可以通过使用列表的标识编号来访问列表中的产品,您可以通过手工输入或从类似图书的产品信息中取得列表的标识编号。例如:

import  com.tutorials.amazon.aws.*;

public class AmazonListMania
{
  public static void main( String [] args) throws Exception
  {

    AmazonSearchServiceLocator AmazonServiceLocator= new AmazonSearchServiceLocator();
    AmazonSearchPort searchSite= AmazonServiceLocator.getAmazonSearchPort();

    ListManiaRequest theRequest = new ListManiaRequest();
    theRequest.setLm_Id("1RWQU4AVIV54L");
    theRequest.setPage("1");
    theRequest.setMode("books");
    theRequest.setTag("webservices-20");
    theRequest.setDevtag("00000000000000");
    theRequest.setType("lite");
    theRequest.setVersion("1.0");
    ProductInfo result = searchSite.listManiaSearchRequest(theRequest);

    Details[] allDetails = result.getDetails();
    int numResults = allDetails.length;

    for (int i = 0; i < numResults; i++) {

        Details thisDetails = allDetails[i];
        String title = thisDetails.getProductName();
        String asin = thisDetails.getAsin();

        System.out.println(title + " (" + asin +")");
    }
  }
}

这里的格式与前一页中的导演搜索相同。仅仅结果有所不同:

Ella Enchanted (Trophy Newbery) (0064407055)
Northanger Abbey (Penguin Classics) (0140434135)
The Princess Diaries (0380814021)
Harry Potter and the Chamber of Secrets (Book 2) (0439064864)

现在,您应该很清楚如何找到信息,所以,下面将开始讲述如何把所有这些搜索变成基于 Web 的店面。

使 WSDK 与应用程序服务器集成

把 WSDK 支持添加到 Web 应用程序服务器

从一开始 J2EE 就被设计成模块化的体系结构从而不需很多努力就可以使应用程序之间相互插入。Amazon 店面通过“插入”Web 服务客户机功能来利用这种能力以使 servlet 或 JSP 能够使用它。

上述做法取得成功的部分原因是因为 Web 应用程序的标准结构。虽然有些位置可被定制,但是,只要类似 .jar 文件的资源被放在正确的地方,服务器就能知道在哪里可找到它们。您无需编辑文件或环境变量。

相反,把库文件和类添加到正确的目录以使服务器能够自动地找到它们。

创建 Web 应用程序

典型的 Web 应用程序被放在服务器的 webapps 目录中,它的结构与下面的清单相似(在讨论中未被用到的目录被省略)。

webapps/storefront
webapps/storefront/WEB-INF
webapps/storefront/WEB-INF/classes
webapps/storefront/WEB-INF/lib

在此,该应用程序被称为 storefront,任何静态文件被放在 storefront 目录中。例如,文件:

webapps/storefront/index.html

可通过以下 URL 被访问:

http://myhostname/storefront/index.html

类似地,任何 .jsp 文件也被放在该目录。

在另一方面,servlet 和被应用程序引用的任何其他个别的类都属于 classes 目录。换句话说,名为 HomePage.class 的已被编译的 servlet 类的位置是:

webapps/storefront/WEB-INF/classes/HomePage.class

因此可通过以下 URL 来访问它:

http://myhostname/storefront/servlet/HomePage

任何库文件(例如类所依赖的 .jar 文件)应放入 lib 目录。这样做的好处是每个应用程序能够有自己的一组库从而排除了潜在的冲突。

实际创建应用程序取决于您的服务器环境。如果您使用的是 WebSphere Application Server,请使用管理客户机来创建名为 storefront 的简单应用程序。现在,请不要担心 WSDK 文件。如果您使用的是类似 Tomcat 的 servlet 引擎,请创建在上面的 webapps 目录中列出的目录。

添加所需的库

现在已经有了目录,请把必要的文件复制到这些目录中以使 Web 服务器能够找到它们。这些文件来自两个不同的位置,这两个位置都假设 %WSDK_HOME% 表示您安装 WSDK 所在的目录。请把以下文件复制到 storefront/WEB-INF/lib 目录:

  • %WSDK_HOME%/axis/lib 中的所有文件
  • %WSDK_HOME%/lib/wsdl4j.jar
  • %WSDK_HOME%/lib/xercesImpl.jar
  • %WSDK_HOME%/lib/xml-apis.jar
  • %WSDK_HOME%/lib/xmlParserAPIs.jar

下一步,服务器需要知道在哪里能够找到 AWS 的支持类。因为它们是个别的类文件而不是 .jar 文件,所以应将它们归入 classes 目录。请把被编译的、被生成的类文件复制到 classes 目录并确保目录结构不变。这意味着您需要创建目录:

storefront/WEB-INF/classes/com/tutorials/amazon/aws

并把编译好的类放在该目录。

测试安装

请在 storefront/WEB-INF/classes 目录中创建名为 TestPage.java 的 servlet。它的内容如下:

import javax.servlet.http.HttpServlet;
import com.tutorials.amazon.aws.*;

public class TestPage extends HttpServlet {

	public void doPost(
		javax.servlet.http.HttpServletRequest request,
		javax.servlet.http.HttpServletResponse response)
		throws javax.servlet.ServletException, java.io.IOException {
	}

	public void doGet(
		javax.servlet.http.HttpServletRequest request,
		javax.servlet.http.HttpServletResponse response)
		throws javax.servlet.ServletException, java.io.IOException {
			
         String title="not retrieved";
         String asin = request.getParameter("asin");

         try {
            AmazonSearchServiceLocator AmazonServiceLocator = 
                                         new AmazonSearchServiceLocator();
            AmazonSearchPort searchSite = 
                                AmazonServiceLocator.getAmazonSearchPort();

            AsinRequest theRequest = new AsinRequest();
            theRequest.setAsin(asin);
            theRequest.setTag("webservices-20");
            theRequest.setDevtag("00000000000000");
            theRequest.setType("heavy");
            theRequest.setVersion("1.0");
            ProductInfo result = searchSite.asinSearchRequest(theRequest);

            Details[] allDetails = result.getDetails();
            int numResults = allDetails.length;

            for (int i = 0; i < numResults; i++) {

               Details thisDetails = allDetails[i];
               title = thisDetails.getProductName();
            }
          } catch (Exception e){
            title = e.getMessage();
          }

          response.getWriter().print("ASIN number "+asin+" refers to title: ");
          response.getWriter().print("<b><i>"+title+"</i></b>");
	}

}

编译这个 servlet。如果 javac 找不到 javax.servlet.http.HttpServlet 软件包,请在您的 Web 服务器的安装目录中找到 servlet.jar 文件并把它添加到您的类路径(classpath)。

请打开浏览器并访问:

http://{your-hostname}/storefront/servlet/TestPage?asin=0451524934

这个 servlet 应该和 AWS 联系以检索书名(在此,1984)并把它显示在页面上:

图 1

图 1

Web 应用程序

列出类别

这部分演示如何使用 AWS 客户机来创建基于 Web 的店面。请记住两点。第一,因为这是技术讨论,所以我不为 GUI 设计和可用性而担心;您应使它看起来更漂亮。第二,因为这里的技术讨论是关于 Web 服务的而不是关于 Web 应用程序的可伸缩性的,所以我不为性能问题而担心;您应分析类似对象作用域的问题。

首先,我将创建列出几个类别(这些类别是从一个标识列表中取得的)的页面。每个类别链接到这个类别中的图书的列表。因为 Amazon 的结果是基于产品搜索,目前没有办法来动态地生成类别的列表,所以这是一个被称为 home.html 的静态页面。

<html>
<head><title>Vanguard Science Fiction Report Amazon Storefront</title></head>
<body>
    <h1>Our Amazon Store</h1>

    We carry books from the following categories:

   <ul>
        <li><a href="servlet/bookList?browseId=16272">Hard Science Fiction</a></li>
        <li><a href="servlet/bookList?browseId=16190">Fantasy</a></li>
        <li><a href="servlet/bookList?browseId=12038">Writing SF&F</a></li>
    </ul>

    <p><a href="http://www.vanguardreport.com">Home</a></p>

</body>
</html>

请把这个文件保存到 storefront 目录(因为它是静态文件)并把您的浏览器指向:

http://{your-hostname}/storefront/index.html

主索引页面的图片

主索引页面的图片

当用户单击类别链接的时候,浏览器将调用在下一页中创建的 bookList servlet。

列出产品

创建实际访问 AWS 的 servlet 是简单的事情,您只需把先前出现在本教程中的代码复制到 servlet 类(或可被 servlet 类访问的类)中。bookList servlet 取得 browseId 和页面编号,然后列出该页面的所有结果(包括每本书的缩略图)。

import javax.servlet.http.HttpServlet;
import com.tutorials.amazon.aws.*;

public class bookList extends HttpServlet {

   public void doPost(
      javax.servlet.http.HttpServletRequest request,
      javax.servlet.http.HttpServletResponse response)
      throws javax.servlet.ServletException, java.io.IOException {
   }

   public void doGet(
      javax.servlet.http.HttpServletRequest request,
      javax.servlet.http.HttpServletResponse response)
      throws javax.servlet.ServletException, java.io.IOException {

      response.getWriter().print("
      <html><head><title>Catalog</title></head>");
      response.getWriter().print("<body>");
      response.getWriter().print("<table>");

      String browseId = request.getParameter("browseId");      
      String pagenumString = request.getParameter("pagenum");
      int pagenum = new Integer(pagenumString).intValue();

      if (pagenum > 1) {
         response.getWriter().print("<a href=\"bookList?browseId="
                      +browseId+"&pagenum="+(pagenum-1)+"\">Previous 10</a>");
      } 
      int numResults = 0;
			
      try {

         AmazonSearchServiceLocator AmazonServiceLocator = 
                                      new AmazonSearchServiceLocator();
         AmazonSearchPort searchSite = 
                             AmazonServiceLocator.getAmazonSearchPort();

         BrowseNodeRequest theRequest = new BrowseNodeRequest();
         theRequest.setBrowse_Node(browseId);
         theRequest.setTag("thevanguardsc-20");
         theRequest.setDevtag("00000000000000");
         theRequest.setPage(pagenumString);
         theRequest.setMode("books");
         theRequest.setType("lite");
         theRequest.setVersion("1.0");
         ProductInfo result = searchSite.browseNodeSearchRequest(theRequest);

         Details[] allDetails = result.getDetails();
         numResults = allDetails.length;

         for (int i = 0; i < numResults; i++) {

             Details thisDetails = allDetails[i];
             String title = thisDetails.getProductName();
             String asin = thisDetails.getAsin();
             String thumbnail = thisDetails.getImageUrlSmall();
             String[] authors = thisDetails.getAuthors();

             String bookInfo = "<tr><td><img src=\""+thumbnail+"\" /></td>";
             bookInfo = bookInfo + "<td><b><a href=\"bookInfo?asin="+asin+"\">";
             bookInfo = bookInfo + title + "</a></b>";
             try {
                bookInfo = bookInfo + ", by " + authors[0];
                for (int j = 0; j < authors.length; j++) {
                    bookInfo = bookInfo + ", " + authors[j];
                }
             } catch (NullPointerException e){
                //This book has no authors
             }
             bookInfo = bookInfo + "</td></tr>";
             response.getWriter().println(bookInfo);
         }     
     } catch (Exception e){
       response.getWriter().print("["+e.getMessage()+"]");
        e.printStackTrace();
     }

     response.getWriter().print("</table>");

     if (numResults == 10) {
         response.getWriter().print("<a href=\"bookList?browseId="
                      +browseId+"&pagenum="+(pagenum+1)+"\">Next 10</a>");
     }

     response.getWriter().print("</body></html>");

  }

}

关于列出产品的更多的详细信息

一般来说,该 servlet 与先前构建的应用程序基本相同,区别仅在于数据被输出到 HTML 标记之间的页面而不是被输出到屏幕。然而,以下几点仍令人感兴趣。

第一,因为一个请求最多返回 10 个产品,所以有必要添加上一个页面和下一个页面的链接并相应地递增或递减页面编号。

第二,您无法知道是否真的下一个页面,所以在百分之十的时间里,当用户单击“下 10 个”链接时,该方法将产生错误。为了十分之一的可能,您可以通过“试验性”地获取下一个页面或编写措辞谨慎的错误页面来解决这个问题。

第三,尽管该页面只检索图书,但是并不能保证所有关于图书的字段都被植入。例如,下面的图像中有一本书的旁边没有作者。请查阅 DTD(见于重量级与轻量级中的列表)以确定您使用的信息是否是必需的并相应地作好准备。

目录页面的图片

目录页面的图片

请把该文件保存到 storefront/classes 目录,编译该文件,然后单击在列出类别页中创建的索引页面中的一个链接以查看它的运行结果。

产品页面

当用户单击一个产品时,他们被带到(由 bookInfo servlet 创建的)有产品信息的页面:

import javax.servlet.http.HttpServlet;
import com.tutorials.amazon.aws.*;

public class bookInfo extends HttpServlet {

   public void doPost(
      javax.servlet.http.HttpServletRequest request,
      javax.servlet.http.HttpServletResponse response)
      throws javax.servlet.ServletException, java.io.IOException {
   }

   public void doGet(
      javax.servlet.http.HttpServletRequest request,
      javax.servlet.http.HttpServletResponse response)
      throws javax.servlet.ServletException, java.io.IOException {

      response.getWriter().print("<html><head><title>Catalog</title></head>");
      response.getWriter().print("<body>");

      String asin = request.getParameter("asin");      
			
      try {

         AmazonSearchServiceLocator AmazonServiceLocator = 
                                      new AmazonSearchServiceLocator();
         AmazonSearchPort searchSite = 
                             AmazonServiceLocator.getAmazonSearchPort();

         AsinRequest theRequest = new AsinRequest();
         theRequest.setAsin(asin);
         theRequest.setTag("thevanguardsc-20");
         theRequest.setDevtag("00000000000000");
         theRequest.setType("heavy");
         theRequest.setVersion("1.0");
         ProductInfo result = searchSite.asinSearchRequest(theRequest);

         Details[] allDetails = result.getDetails();
         int numResults = allDetails.length;

         if (numResults == 1) {

             Details thisDetails = allDetails[0];
             String title = thisDetails.getProductName();

             String cover = thisDetails.getImageUrlLarge();
             String[] authors = thisDetails.getAuthors();
             String price = thisDetails.getOurPrice();
             String publisher = thisDetails.getManufacturer();
             String release = thisDetails.getReleaseDate();
             Reviews reviews = thisDetails.getReviews();
            
             String bookInfo;

             bookInfo = "<table>";
             bookInfo = bookInfo + "<tr><td><img src=\""+cover+"\" /></td>";
             bookInfo = bookInfo + "<td><h2>";
             bookInfo = bookInfo + title + "</a></h2>";
             bookInfo = bookInfo + "<p>";
             try {
                bookInfo = bookInfo + "by " + authors[0];
                for (int j = 1; j < authors.length; j++) {
                    bookInfo = bookInfo + ", " + authors[j];
                }
             } catch (NullPointerException e){
                //This book has no authors
             }
             bookInfo = bookInfo + "</p>";
             bookInfo = bookInfo + "<p>" + publisher + " ("+release+")</p>";
             bookInfo = bookInfo + "<p>Amazon price: "+price+"</p>";

             try {
                bookInfo = bookInfo + "Average review: " + 
                                            reviews.getAvgCustomerRating();

                bookInfo = bookInfo + "</td></tr>";
                bookInfo = bookInfo + "<tr><td colspan=\"2\">";

                bookInfo = bookInfo + "<h3>Customer Reviews</h3>";
                CustomerReview[] custReviews = reviews.getCustomerReviews();
                for (int i = 1; i < custReviews.length; i++) {
                    CustomerReview thisReview = custReviews[i];
                    String summary = thisReview.getSummary();
                    String rating = thisReview.getRating();
                    String comment = thisReview.getComment();
                    bookInfo = bookInfo + "<p><b>"+summary+"</b> ";
                    bookInfo = bookInfo + "("+rating+" out of 5)</b>";
                    bookInfo = bookInfo + "<br />" + comment +"</p>";
                }
             } catch (NullPointerException e) {
                 //No reviews for this item
             }
             bookInfo = bookInfo + "</td></tr>";
             bookInfo = bookInfo + "</table>";

             response.getWriter().println(bookInfo);
         } else {
             response.getWriter().println("No such ASIN.");
         }    
     } catch (Exception e){
       response.getWriter().print("["+e.getMessage()+"]");
        e.printStackTrace();
     }

     response.getWriter().print("</body></html>");

  }

}

在这个 servlet 中绝对没有什么新东西。它使用了您现在已熟悉的模式:

  1. 创建请求。
  2. 发送请求。
  3. 从 ProductInfo 中的 Details 抽取信息。
  4. 显示信息并解释可能缺少的信息。

任何可用的特色(例如强力搜索或 Listmania! 列表)的工作方式完全相同。

然而,这个店面少了一件必要的东西:实际购买东西的能力。

购物车、愿望列表和注册中心

使用购物车、愿望列表和注册中心

到目前为止,本教程把重点放在从 Amazon.com 数据库获取信息而不是把信息添加到该数据库。这部分讲述在 Amazon 下订单和把产品添加到愿望列表和注册中心。

首先,请控制一下您的期望:虽然您能够把产品添加到用户的购物车、愿望列表或婚礼注册中心,但是您不能读取这些对象中的东西。抱歉。然而,当您的用户已作出所有的决定并且实际上已准备检出时,在最后可能的时刻把他们送到 Amazon.com 是可能的。(Amazon.com 负责处理检出。您不收取任何钱。)

既然我们已讲了那么多,那些对象是什么?

Amazon 购物车的含义与它的名称相符:用户计划从 Amazon.com 购买的一组产品。当用户准备检出时,Amazon.com 使他(她)能够检查数量、除去产品等。

Amazon 愿望列表是用户确实想买但还没买的产品列表。朋友、家人、感激的用户和其他人就可以在他们想为您买礼物时查看该列表。它就象一个不必结婚的婚礼注册中心。

Amazon 还经营婚礼注册中心,夫妇们可在该中心列出他们想要的礼物,朋友们可以了解为他们买什么。此外,Amazon 为有婴儿的客户运行注册中心,但是您无法通过 AWS 来使用婴儿注册中心。

添加到购物车

把产品添加到用户的购物车、愿望列表或注册中心的最常见的方法是把按钮添加到页面中。该按钮是包含许多与 SOAP 请求的一部分相同的信息的表单的一部分。例如,创建把 ASIN 编号 0345404475 添加到用户的购物车的按钮的 HTML 是:

<form method="POST" 
action="http://www.amazon.com/o/dt/assoc/handle-buy-box=0345404475"> 
<input type="hidden" name="asin.0345404475" value="3" /> 
<input type="hidden" name="tag-value" value="webservices-20" /> 
<input type="hidden" name="tag_value" value="webservices-20" /> 
<input type="submit" name="submit.add-to-cart" value="Buy from Amazon.com" /> 
</form>

请注意该表单必须把伙伴的标识既列为 tag-value 也列为 tag_value。此外,请注意 asin 表单字段中的数字表示数量;该表单把 Do Androids Dream of Electric Sheep 的三个拷贝添加到用户的购物车。

当用户单击该按钮时,他(她)将被带到 Amazon.com 以完成定单。

您也可以把按钮直接添加到 servlet。

把按钮添加到页面

为了添加在 servlet 生成的页面中买东西的能力,您只需输出正确的 HTML:

...
             bookInfo = bookInfo + "<p>" + publisher + " ("+release+")</p>";
             bookInfo = bookInfo + "<p>Amazon price: "+price+"</p>";

             bookInfo = bookInfo + "<form method=\"POST\" "
                     + "action
                     =\"http://www.amazon.com/o/dt/assoc/handle-buy-box="
                                          + asin+"\">";
             bookInfo = bookInfo + "<input type=\"hidden\" "
                     + "name=\"asin."+asin+"\" value=\"1\">"; 
             bookInfo = bookInfo + "<input type=\"hidden\" "
                     + "name=\"tag-value\" value=\"thevanguardsc-20\">";
             bookInfo = bookInfo + "<input type=\"hidden\" "
                     + "name=\"tag_value\" value=\"thevanguardsc-20\">";
             bookInfo = bookInfo + "<input type=\"submit\" "
                     + "name=\"submit.add-to-cart\" "
                     + "value=\"Buy from Amazon.com\">"; 
             bookInfo = bookInfo + "</form>";

             try {
                bookInfo = bookInfo + "Average review: " + 
                                            reviews.getAvgCustomerRating();
...

您可以使用相同的方法把产品添加到用户的愿望列表或注册中心。

愿望列表和注册中心

把产品添加到愿望列表或注册中心与把它添加到购物车一样简单。您只需更改提交按钮的名称和值以指明新的目的地。

对于愿望列表,表单应该是:

<form method="POST" 
action="http://www.amazon.com/o/dt/assoc/handle-buy-box=0345404475"> 
<input type="hidden" name="asin.0345404475" value="3" /> 
<input type="hidden" name="tag-value" value="webservices-20" /> 
<input type="hidden" name="tag_value" value="webservices-20" /> 
<input type="submit" name="submit.add-to-registry.wishlist" 
                                       value="Add to Amazon.com Wishlist">
</form>

对于婚礼注册中心,请使用:

<form method="POST" 
action="http://www.amazon.com/o/dt/assoc/handle-buy-box=0345404475"> 
<input type="hidden" name="asin.0345404475" value="3" /> 
<input type="hidden" name="tag-value" value="webservices-20" /> 
<input type="hidden" name="tag_value" value="webservices-20" /> 
<input type="submit" name="submit.add-to-registry.wedding" 
                                value="Add to Amazon.com Wedding Registry">
</form>

总结

使用 SOAP 和 WSDK 来构建 Amazon 店面的总结

通过 Amazon Web 服务项目,Amazon.com 使任何想用它的数据库的人都可以使用它,使用的方式是通过返回 XML 文档的 HTTP 请求或通过 SOAP 接口。本教程讨论了 SOAP 接口并包括以下主题:

  • 安装和配置 WSDK。
  • 使用 WSDK 和 AWS WSDL 文件来生成 Java 客户机。
  • 创建各种类型的请求对象。
  • 执行请求。
  • 从结果中检索产品信息。
  • 使 Web 客户机与 Web 应用程序服务器集成。
  • 创建使用该客户机的 Web 店面。
  • 把产品添加到用户的购物车、愿望列表和婚礼注册中心。

反馈

请让我们知道本教程对您是否有所帮助以及改进它的方法。我还想知道您想看到的其他教程主题。谢谢!


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services
ArticleID=84953
ArticleTitle=构建 Amazon 店面
publish-date=01242003