麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

在Java Web框架中創(chuàng)建VoiceXML頁(yè)面

2019-11-18 16:17:29
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

2006 年 11 月 23 日

    對(duì)于絕大多數(shù) Web 開發(fā)人員來(lái)說(shuō),輸出 Html、XHTML 乃至 xml 是一項(xiàng)微不足道的任務(wù),它只不過(guò)是創(chuàng)建和部署 Web 應(yīng)用程序的常規(guī)流程。從顯示 Internet 頁(yè)面到應(yīng)答電話呼叫看似一個(gè)巨大的飛躍,但實(shí)際并非如此。在這篇文章中,您將看到相同的技術(shù)如何幫助您動(dòng)態(tài)創(chuàng)建 Web 頁(yè)面以便接聽(虛擬的)電話并應(yīng)答呼叫。

    在過(guò)去五年中,Web 得到了比以往任何時(shí)候都長(zhǎng)足的發(fā)展。一度主要以文本為基礎(chǔ)的軟件程序媒介 “Web 瀏覽器” 現(xiàn)已發(fā)展成為一種可供任何具有連通性的設(shè)備使用的信息源。最早列入可訪問(wèn) Web 頁(yè)面的設(shè)備列表的是移動(dòng)電話,隨后是尋呼機(jī)、手持設(shè)備、個(gè)人電子助理和其他任何可通過(guò)無(wú)線連接連入 Web 的設(shè)備。在最近幾年,電話也加入了這一陣營(yíng),通過(guò)普通電話線路使用 Web 程序的呼聲也越來(lái)越高。

    這種最新型的應(yīng)用程序(用戶通過(guò)電話訪問(wèn)在線服務(wù))的更恰當(dāng)?shù)拿Q是電話應(yīng)用程序(telephone application。顯而易見,由于電話無(wú)法用來(lái) “單擊一個(gè)鏈接”,應(yīng)用程序交互幾乎全部是通過(guò)語(yǔ)音處理的。用戶不是采用單擊鏈接的方式,而是說(shuō)出 “賬戶信息” 或使用鍵盤按預(yù)先錄制好的指令進(jìn)行操作。

    通過(guò)現(xiàn)有(或略加修改的)Web 應(yīng)用程序?yàn)殡娫捥峁┓?wù)的能力是一種強(qiáng)大的想法,也是許多 Web 開發(fā)人員都渴望探索的領(lǐng)域之一。關(guān)于 Web 應(yīng)用程序與電話應(yīng)用程序,要了解的最重要的一件事就是您實(shí)際上可以使用相同的技術(shù)組合來(lái)創(chuàng)建這兩種應(yīng)用程序。HTML、XHTML 和 XML 是 Web 界面之下最常用的三種底層技術(shù),VoiceXML(或簡(jiǎn)稱為 VXML)則是一種密切相關(guān)的技術(shù),它使得電話客戶機(jī)可以利用 Web 交互。javaServer Pages 與 servlet、php 腳本以及 Ruby 應(yīng)用程序均可響應(yīng)電話請(qǐng)求,就像響應(yīng)那些進(jìn)入手持設(shè)備或 Web 瀏覽器的請(qǐng)求一樣輕松。在這篇文章中,我們主要關(guān)注使用 Java 平臺(tái)為簡(jiǎn)單的 VoiceXML 應(yīng)用程序提供服務(wù),但您可將本文介紹的方法同樣地應(yīng)用到 PHP、Perl 或您選擇的任何編程語(yǔ)言。

VoiceXML、CCXML 還是 CallXML?

在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖一)從 Voxeo 開始!

您需要首先建立一個(gè)免費(fèi)的 Voxeo 開發(fā)者賬戶,這樣才能在學(xué)習(xí)本文過(guò)程中配合練習(xí)。盡管 Voxeo 并不是任何 VoiceXML 的服務(wù)所必需的,但它確實(shí)提供了一套出色的工具,更有數(shù)千份 VoiceXML、CallXML 和 CCXML 文檔頁(yè)面。本文同時(shí)介紹 Voxeo 與 VioiceXML 編程,后續(xù) developerWorks 還將為您提供更多有關(guān) Voxeo 的內(nèi)容。

    構(gòu)建語(yǔ)音應(yīng)用程序最常用的標(biāo)準(zhǔn)就是 VoiceXML。絕大多數(shù) VXML 瀏覽器都支持 VoiceXML 2.0,本文通篇將使用這個(gè)版本的 VXML。VXML 符合 W3C 規(guī)范且發(fā)展迅速,目前的版本依然是 v2.1。VXML 3.0 即將推出。

    CCXML 是 Call Control XML 的縮寫,也是電話標(biāo)記方面符合 W3C 規(guī)范的最新一員。CCXML 比大多數(shù) VoiceXML 實(shí)現(xiàn)更為高級(jí),提供了對(duì)回叫、事件偵聽器和多路及多方會(huì)話的支持。但除非您特別需要這些屬性,否則最好的選擇或許是繼續(xù)使用 VoiceXML,VoiceXML 更加穩(wěn)定,應(yīng)用也更廣泛。

    CallXML 是特定于 Voxeo 的一種平臺(tái)。CallXML 學(xué)習(xí)起來(lái)非常輕松,并提供了對(duì)按鍵電話(toUChtone)輸入的支持(請(qǐng)注意,它并不支持語(yǔ)音識(shí)別)。CallXML 的最大缺陷就是特定于廠商。Voxeo 是一個(gè)非常出色的站點(diǎn),具有無(wú)數(shù)資源,但被一家廠商鎖定絕對(duì)不是個(gè)好主意。此時(shí),大多數(shù)開發(fā)人員會(huì)再次發(fā)現(xiàn),VoiceXML 更適合他們的需求。

VoiceXML 101

    在接觸 VoiceXML 世界的 Java 方面之前,您應(yīng)大致理解 VoiceXML 應(yīng)用程序的工作原理。之后,我將為您介紹一個(gè)非常簡(jiǎn)單的 VoiceXML 應(yīng)用程序。示例應(yīng)用程序?qū)⑹鼓軌虿榭?VXML 文件,同時(shí)確保您有權(quán)訪問(wèn)(且可使用)Voxeo 的 call-assignment 服務(wù),這個(gè)服務(wù)對(duì)本文后面的內(nèi)容非常關(guān)鍵。

一個(gè)簡(jiǎn)單的 VXML 頁(yè)面

    VoiceXML 最少要以一個(gè) VXML 文件開始,使用 VoiceXML 風(fēng)格的 XML 版本告訴電話應(yīng)用程序它們應(yīng)該以及能夠作些什么。清單 1 給出了一個(gè)非常簡(jiǎn)單的 VXML 文件。將這個(gè)文件保存到您的本機(jī)上。



清單 1. 一個(gè)非常簡(jiǎn)單的 VXML 文件

				<?xml version="1.0" encoding="UTF-8"?><vxml version="2.1">  <form>    <block>      <PRompt>        Things are working correctly! Congratulations.      </prompt>    </block>  </form></vxml>

    對(duì)于 VoiceXML 來(lái)說(shuō),這非常基礎(chǔ),如果您對(duì)語(yǔ)法的了解還不夠清楚,請(qǐng)查看 參考資料 中列出的其他 VoiceXML 文章。清單 1 中的 VXML 文件只包含一條提示信息,未提供任何交互功能,在處理 Java 代碼的一節(jié)中,您將看到更高級(jí)的用法。但目前,使用這個(gè)簡(jiǎn)單的測(cè)試用例來(lái)確保您的環(huán)境工作正常。

上傳應(yīng)用程序

    接下來(lái),將您的 VXML 文件放在某個(gè)可以訪問(wèn)的位置。如果您有 ISP,只需將 VXML 文件上傳到您的 Web 站點(diǎn),您可能也會(huì)希望在 Web 根目錄下為您的 VoiceXML 文件創(chuàng)建一個(gè)目錄,例如 /voicexml 或 /voice。確保這些目錄和文件可通過(guò) Web 訪問(wèn)(如果您不清楚如何進(jìn)行這些操作,請(qǐng)咨詢您的系統(tǒng)管理員或 ISP)。

    如果您沒(méi)有 ISP,那么可以在 Voxeo 注冊(cè),以便使用該站點(diǎn)的 File Manager。您應(yīng)已建立了一個(gè) Voxeo 賬戶,它附帶 10 MB 的主機(jī)空間,因此這是個(gè)不錯(cuò)的免費(fèi)選擇。(10 MB 可以容納大量 VXML 文件!)

    使 VXML 應(yīng)用程序聯(lián)機(jī)之后,我們還想確定能夠通過(guò)在 Web 瀏覽器中輸入 URL 來(lái)訪問(wèn)它。根據(jù)您所使用的具體瀏覽器不同,可能會(huì)要求您下載 XML 文件,也可能會(huì)在您的瀏覽器中以某種形式呈現(xiàn)它。這只是一個(gè)測(cè)試,確保您的 VXML 可用,因此即使您的計(jì)算機(jī)沒(méi)有開始跟您交談,也不要太過(guò)憂慮。VXML 聯(lián)機(jī)后,也就作好了將其與一個(gè)電話號(hào)碼連接的準(zhǔn)備。

為您的應(yīng)用程序分配一個(gè)電話號(hào)碼

在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖一)最后一次呼吁您使用 Voxeo!

如果您尚未注冊(cè)獲得一個(gè) Voxeo 賬戶,那么現(xiàn)在就去注冊(cè)吧!從這里開始,以下的示例都需要您使用 Voxeo 工具。建立賬戶是免費(fèi)的,沒(méi)有任何責(zé)任,您更會(huì)獲得杰出的工具與支持。現(xiàn)在就去 注冊(cè)獲得一個(gè)開發(fā)者賬戶吧!

    與傳統(tǒng)的 Web 應(yīng)用程序不同,您無(wú)法直接打開 Web 瀏覽器然后瀏覽您的 VXML 文件,至少在您希望獲得語(yǔ)音應(yīng)答時(shí)不能這樣做。為了測(cè)試基于電話的應(yīng)用程序,您顯然需要一臺(tái)電話,這就意味著一個(gè)呼叫號(hào)碼。有許多高成本的方法可以將號(hào)碼映射到 VoiceXML 應(yīng)用程序,但對(duì)于測(cè)試、登臺(tái)(staging)和開發(fā)而言,Voxeo 提供了一種出色的免費(fèi)映射服務(wù)。

    導(dǎo)航到 Voxeo.com,登錄(使用頁(yè)面左上角的字段)。在 Account 菜單中選擇 Application Manager,如 圖 1 所示。


圖 1. 使用 Voxeo Application Manager
在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖二)

QQRead.com 推出數(shù)據(jù)恢復(fù)指南教程 數(shù)據(jù)恢復(fù)指南教程 數(shù)據(jù)恢復(fù)故障解析 常用數(shù)據(jù)恢復(fù)方案 硬盤數(shù)據(jù)恢復(fù)教程 數(shù)據(jù)保護(hù)方法 數(shù)據(jù)恢復(fù)軟件 專業(yè)數(shù)據(jù)恢復(fù)服務(wù)指南

選擇 Add Application,然后選擇 VoiceXML 2.0 作為部署平臺(tái)。

    接下來(lái),提供您的 VXML 文件的 URL,另外還有您的應(yīng)用程序的名稱,您可以按照自己的偏好任選名稱。圖 2 展示了訪問(wèn)我的 VXML 文件的設(shè)置。從 Application Phone Number 下拉菜單中選擇 Staging 選項(xiàng)。這將為應(yīng)用程序分配一個(gè)臨時(shí)登臺(tái)電話號(hào)碼(temporary staging phone number),以使您可以真正地用您自己的電話呼叫這個(gè)號(hào)碼。


圖 2. 將一個(gè) VXML 文件映射到一個(gè)電話號(hào)碼
在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖三)

    單擊 Create Application,Voxeo 將為您的應(yīng)用程序分配一些電話號(hào)碼。圖 3 展示了最終屏幕(略微向下滾動(dòng)了一點(diǎn)),以及 VXML 文件的所有訪問(wèn)點(diǎn)。


圖 3. 成功映射!
在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖四)


    這一功能值得您花時(shí)間去注冊(cè) Voxeo,您現(xiàn)在可以通過(guò)長(zhǎng)途電話號(hào)碼、800 免費(fèi)電話號(hào)碼和 Skype 訪問(wèn)您的 VXML 文件,而這些方法還只是其中的一小部分。這非常好,因?yàn)槟槐厥褂?Voxeo 工具去測(cè)試應(yīng)用程序。更好的是,您可以讓您的老板在無(wú)需具備 Voxeo 站點(diǎn)賬戶的情況下完成測(cè)試!

測(cè)試應(yīng)用程序

    剩下的工作就是呼叫一個(gè) Voxeo 提供的號(hào)碼。撥號(hào)后,您的 VXML 應(yīng)用程序應(yīng)獲取號(hào)碼,并讓您知道(用一種單調(diào)機(jī)械的聲音):“Things are working correctly! Congratulations.”

    好,就是這樣:在大約五分鐘內(nèi),您使您的電話與一個(gè) XML 文件進(jìn)行了交談。現(xiàn)在就可以看看 Java 代碼了,并了解如何動(dòng)態(tài)地生成 VXML。

Java 和 VXML

    這里,大多數(shù) Java 開發(fā)人員都試圖在自己的 Java Servlet 中手工編碼 VXML,添加數(shù)百行的 out.println() 語(yǔ)句、為輸出的內(nèi)容類型而操心,通常也會(huì)給許多應(yīng)用程序增加嚴(yán)重且不必要的復(fù)雜性。動(dòng)手處理那些較為復(fù)雜的編程任務(wù)之前(只要應(yīng)用得當(dāng),它們都是很有用的),請(qǐng)先通過(guò)本節(jié)了解一些關(guān)于 VoiceXML Servlet 編程的最基本的內(nèi)容。

 

創(chuàng)建一個(gè) VXML 文件的原型

    首先要開發(fā) VXML 文件。不要打開一個(gè) IDE 并開始編寫 Java 代碼,而是啟動(dòng)一個(gè)文本編輯器,忍住立即添加 packageimport 語(yǔ)句的渴望。構(gòu)建一個(gè)簡(jiǎn)單的 VXML 文件,就像本文前面給出的示例那樣。

    例如,清單 2 是又一個(gè)非常基礎(chǔ)的 VXML 文件。它是一個(gè)語(yǔ)音識(shí)別 VXML 文件,接入一個(gè)恰當(dāng)?shù)脑O(shè)備并提供某些關(guān)于呼叫選擇的注釋。


清單 2. 另外一個(gè)基本的 VXML 文件

				<?xml version="1.0" encoding="UTF-8"?><vxml version="2.1">  <form id="MainMenu">    <field name="instrument">      <prompt>What is your  favorite musical instrument?</prompt>      <!-- Insert an inline grammar -->      <grammar type="text/gsl">        [guitar mandolin dobro (violin fiddle) banjo]      </grammar>      <!-- Handle the case when they give no answer -->      <noinput>        Did you say something? I didn't hear you.        <reprompt />      </noinput>      <!-- Handle the case when no match is found -->      <nomatch>        I suppose that's OK, but it's not on my top five.         Want to try again?        <reprompt />      </nomatch>    </field>    <!-- Handle the various options. -->    <filled namelist="instrument">      <if cond="instrument == 'guitar'">        <prompt>That's right! Hang up and go practice.</prompt>      <elseif cond="instrument == 'mandolin'" />        <prompt>Nice... and only four strings to keep in tune.</prompt>      <elseif cond="instrument == 'dobro'" />        <prompt>Boy, that's no fun to learn, is it?</prompt>      <elseif cond="instrument == 'violin'" />        <prompt>We call that a fiddle, Mr. Fancy Pants.</prompt>      <elseif cond="instrument == 'fiddle'" />        <prompt>Does playing classical music on a         fiddle make it a violin?</prompt>      <elseif cond="instrument == 'banjo'" />        <prompt>Wow, I hope you live alone.</prompt>      </if>    </filled>  </form></vxml>


    編寫這個(gè) VXML、保存它、將它上傳到 ISP,然后為它分配一個(gè)號(hào)碼。只有在您完成所有這些步驟后 —— 確保您的 VXML 正常工作,才是準(zhǔn)備好了,可以開始 考慮編寫 Java 代碼。

    如果您直接跳到 Java,那么很可能會(huì)導(dǎo)致輸出中出錯(cuò),代碼中也會(huì)出錯(cuò)。結(jié)果是要在一個(gè) Web 框架內(nèi)嘗試同步調(diào)試一個(gè) VXML 文件(XML)和一個(gè) Servlet(Java),這種調(diào)試極其艱難。不要添加所有這些變量(沒(méi)有雙關(guān)的意思),務(wù)必從一個(gè)可正常工作的 VXML 文件入手。然后 準(zhǔn)備運(yùn)行 Java 代碼。

 

讀入文件

    準(zhǔn)備好 VXML 可供使用后,您也就為開始編碼作好了最終的準(zhǔn)備。首先從一個(gè)僅載入 VXML 文件的 Servlet 開始。清單 3 是一個(gè)實(shí)現(xiàn)此功能的 Servlet —— 載入 清單 2 中開發(fā)的 VXML。這段代碼沒(méi)有任何輸出,所以期望值暫時(shí)不要太高。


清單 3. 載入一個(gè) VXML 文件

				package com.ibm.vxml;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import javax.servlet.*;import javax.servlet.http.*;public class VoiceXMLServlet extends HttpServlet {  private static final String VXML_FILENAME =    "simple-voice_recog.xml";  public void doGet(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    String vxmlDir = getServletContext().getInitParameter("vxml-dir");    BufferedInputStream bis = null;    ServletOutputStream out = null;    try {      // Load the VXML file      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);      FileInputStream fis = new FileInputStream(vxml);      bis = new BufferedInputStream(fis);      // Output the VXML file       int readBytes = 0;      while ((readBytes = bis.read()) != -1) {        // output the VXML      }    } finally {      if (out != null) out.close();      if (bis != null) bis.close();    }  }}

    這段代碼非常直觀。它載入一個(gè) XML 文件 —— 通過(guò) servlet 的配置上下文中的目錄和一個(gè)常量文件名指定,然后遍歷文件內(nèi)容。您要將文件的路徑硬編碼到 servlet 中,但至少將目錄名存儲(chǔ)到 Web.xml 文件中是一個(gè)非常不錯(cuò)的主意,此文件位于 servlet 上下文的 WEB-INF/ 目錄下。清單 4 展示了 Web.xml 中的上下文參數(shù)。


清單 4. servlet 的上下文參數(shù)

				  <context-param>    <param-name>vxml-dir</param-name>    <param-value>/path-to-your-voicexml-dir/voicexml</param-value>  </context-param>

    若編譯 servlet 并嘗試在 Web 瀏覽器中載入它,您只會(huì)看到一個(gè)空白的屏幕,同樣,您應(yīng)確保至少會(huì)看到這樣的空白屏幕。如果得到錯(cuò)誤,就需要予以更正。例如,常常會(huì)出現(xiàn)文件訪問(wèn)問(wèn)題或 VXML 文件路徑錄入錯(cuò)誤。一旦得到了空白屏幕,也就準(zhǔn)備好實(shí)際輸出 VXML 文件了。

從 servlet 中輸出 VXML

首先,您需要訪問(wèn)一個(gè)輸出對(duì)象,這樣才能向?yàn)g覽器發(fā)送內(nèi)容。這非常簡(jiǎn)單:

      // Load the VXML file      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);      FileInputStream fis = new FileInputStream(vxml);      bis = new BufferedInputStream(fis);      // Let the browser know that XML is coming      out = res.getOutputStream();			

從文件提取內(nèi)容也非常簡(jiǎn)單,只要使用一行代碼即可:

      // Output the VXML file       int readBytes = 0;      while ((readBytes = bis.read()) != -1) {        // output the VXML        out.write(readBytes);      }


    雖然上述代碼看似已經(jīng)足夠,但您依然需要告知瀏覽器您正在向它發(fā)送 XML。切記,瀏覽器用于 HTML,某些瀏覽器可能無(wú)法順利接收 XML。您可設(shè)置內(nèi)容類型,也可設(shè)置內(nèi)容的長(zhǎng)度,只要再次使用 HttpServletResponse 對(duì)象即可:

      // Let the browser know that XML is coming      out = res.getOutputStream();      res.setContentType("text/xml");      res.setContentLength((int)vxml.length());			

清單 5 展示了添加到前文介紹的 清單 3 給出的 servlet 中的所有代碼。


清單 5. 完整且準(zhǔn)備好載入 VXML 文件的 VoiceXMLServlet

				package com.ibm.vxml;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import javax.servlet.*;import javax.servlet.http.*;public class VoiceXMLServlet extends HttpServlet {  private static final String VXML_FILENAME =    "simple-voice_recog.xml";  public void doGet(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    String vxmlDir = getServletContext().getInitParameter("vxml-dir");    BufferedInputStream bis = null;    ServletOutputStream out = null;    try {      // Load the VXML file      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);      FileInputStream fis = new FileInputStream(vxml);      bis = new BufferedInputStream(fis);      // Let the browser know that XML is coming      out = res.getOutputStream();      res.setContentType("text/xml");      res.setContentLength((int)vxml.length());      // Output the VXML file       int readBytes = 0;      while ((readBytes = bis.read()) != -1) {        // output the VXML        out.write(readBytes);      }    } finally {      if (out != null) out.close();      if (bis != null) bis.close();    }  }}

測(cè)試 servlet 載入的 VoiceXML

    完成上述更改后編譯您的 servlet,若需要請(qǐng)重啟 servlet 引擎。瀏覽 servlet,您應(yīng)看到如 圖 4 所示的輸出結(jié)果。成功!


圖 4. VoiceXML servlet 輸出 VXML
在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖五)

    若您未得到類似輸出,確定您的文件是否位于您希望的位置,并確保沒(méi)有任何權(quán)限問(wèn)題。您還要檢查 servlet 引擎的日志或請(qǐng)求系統(tǒng)管理員的幫助。

    現(xiàn)在就準(zhǔn)備好將電話號(hào)碼映射到您的 servlet 了。重新回到 Voxeo.com 的 Application Mnager,添加一個(gè)新應(yīng)用程序(可能會(huì)看到之前您使用過(guò)的應(yīng)用程序)。確保選中 VoiceXML 2.0,然后輸入新應(yīng)用程序的名稱和 servlet 的 URL。Voxeo 將創(chuàng)建應(yīng)用程序并為其分配一個(gè)電話號(hào)碼。

    撥入這個(gè)新號(hào)碼,您應(yīng)聽到 清單 2 中的 VXML 給出的提示。祝賀您!您已經(jīng)編寫好了一個(gè)輸出 VXML 的 Java servlet 的代碼,還在其中掛接了一個(gè)電話號(hào)碼。

 

部分可選的附加項(xiàng)

    您可能希望向 servlet 代碼中添加一些小附加項(xiàng)。它們都不是必需的,但都會(huì)給現(xiàn)有的版本增加一些健壯性和文檔。

    首先,您可能想允許用戶通過(guò) POST 請(qǐng)求訪問(wèn) VXML。這可能在用戶單擊表單上的一個(gè)按鈕時(shí)發(fā)生,該表單將對(duì) VoiceXMLServlet 作出一個(gè) POST 請(qǐng)求。在 servlet 中處理這一操作非常簡(jiǎn)單,只要編寫一個(gè)委托已有 doGet() 方法的 doPost() 即可,如下所示:

  public void doPost(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    doGet(req, res);  }


    另外一個(gè)簡(jiǎn)單的附加項(xiàng)用于允許瀏覽器切實(shí)獲知您正在輸出一個(gè) VXML 文件的內(nèi)容。為此,設(shè)置 servlet 中的 Content-disposition 響應(yīng)頭,如下:

      // Let the browser know that XML is coming      out = res.getOutputStream();      res.setContentType("text/xml");      res.setContentLength((int)vxml.length());      res.addHeader("Content-Disposition",        "attachment; filename=" + vxml);			

    現(xiàn)在讀取您的響應(yīng)的瀏覽器(或其他代碼)就可以發(fā)現(xiàn)所服務(wù)的 VXML 文件了。但務(wù)必不要包含完整的文件路徑,這會(huì)造成安全隱患!

動(dòng)態(tài) VoiceXML

    有了輸出 VXML 文件的 servlet 之后,將其轉(zhuǎn)換成動(dòng)態(tài)輸出 VXML 的 servlet(使用代碼作為模型或模板)輕而易舉。換句話說(shuō),您可以超越簡(jiǎn)單地載入靜態(tài)的 VXML 文件,開始通過(guò)編程創(chuàng)建 VXML。

    當(dāng)您開始考慮動(dòng)態(tài) VoiceXML 時(shí),Java 平臺(tái)就顯示出了自己的優(yōu)勢(shì)。它提供了輕松輸出 XML 的能力,還有與數(shù)據(jù)庫(kù)、目錄服務(wù)器、身份驗(yàn)證存儲(chǔ)和會(huì)話的交互。此外,它還能夠證實(shí),構(gòu)建動(dòng)態(tài) VXML 將消除基于語(yǔ)音的系統(tǒng)的部分刻板性。

    在這一節(jié)中,我將逐步為您介紹創(chuàng)建一個(gè)輸出動(dòng)態(tài) VXML 的 Java servlet 的步驟。

通過(guò) out.println() 輸出 VXML

    您已經(jīng)了解了如何訪問(wèn) ServletOutputStream,然后在輸出流中插入字節(jié)。但如果從源(例如一個(gè)靜態(tài) VXML 文件)傳輸?shù)捷敵隽鞯牟粌H僅是字節(jié),那么直接處理字節(jié)的方式幾乎無(wú)法管理控制。

    如果您希望自行創(chuàng)建 VXML,最好使用 PrintWriter。利用這個(gè)類,您可發(fā)出整個(gè)字符串,使之對(duì)于創(chuàng)建和輸出動(dòng)態(tài)內(nèi)容更為有用。這只需要對(duì)代碼略加修改,如下所示:

  public void doGet(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    String vxmlDir = getServletContext().getInitParameter("vxml-dir");    BufferedInputStream bis = null;    ServletOutputStream out = null;    try {      // Load the VXML file      File vxml = new File(vxmlDir + "/" + VXML_FILENAME);      FileInputStream fis = new FileInputStream(vxml);      bis = new BufferedInputStream(fis);      // Let the browser know that XML is coming      PrintWriter out = res.getOutputStream();      res.setContentType("text/xml");      res.setContentLength((int)vxml.length());      // Output content using PrintWriter    } finally {      if (out != null) out.close();      if (bis != null) bis.close();    }  }

    另外,不要忘記導(dǎo)入 java.io.PrintWriter 類:它不會(huì)自動(dòng)成為對(duì)您的 servlet 的代碼基可用。

    使用 PrintWriter,您現(xiàn)在可以輸出基于字符串的內(nèi)容了。例如,清單 6 輸出與 清單 1 相同的 VXML,但是通過(guò) servlet 輸出,并未從靜態(tài)文件載入 VXML 內(nèi)容。


清單 6. 動(dòng)態(tài)輸出 VXML

				package com.ibm.vxml;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.*;import javax.servlet.http.*;public class DynamicVoiceXMLServlet extends HttpServlet {  public void doGet(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    BufferedInputStream bis = null;    PrintWriter out = null;    try {      // Let the browser know that XML is coming      out = res.getWriter();      res.setContentType("text/xml");      // Output VXML      out.println("<?xml version=/"1.0/" encoding=/"UTF-8/"?>");      out.println("<vxml version=/"2.1/">");      out.println(" <form><block><prompt>");      out.println("  Things are working correctly! Congratulations.");      out.println(" </prompt></block></form>");      out.println("</vxml>");    } finally {      if (out != null) out.close();      if (bis != null) bis.close();    }  }  public void doPost(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    doGet(req, res);  }}



    現(xiàn)在您可編譯這個(gè) servlet、向 Voxeo 注冊(cè)它,并通過(guò)電話訪問(wèn)它,與處理 清單 1 的方法相同。現(xiàn)在我們來(lái)看一些示例,從而展示像 Java 這樣的語(yǔ)言的動(dòng)態(tài)編程能力。

添加時(shí)間提醒

    基于 servlet 的 VXML 輸出的一項(xiàng)最簡(jiǎn)單的用途就是添加時(shí)間提醒。利用 Java 代碼獲取當(dāng)前日期和時(shí)間非常輕松,因此這是個(gè)不錯(cuò)的起點(diǎn)。

    使用 Calendar 類可輕松獲得一天中的具體時(shí)間(實(shí)際上,可以獲得與當(dāng)前日期相關(guān)的任何內(nèi)容)。清單 7 給出了獲得 Calendar 類新實(shí)例的代碼,從而得到一天中的具體時(shí)間(以 24 小時(shí)的格式返回),然后根據(jù)這個(gè)時(shí)間組合出一條簡(jiǎn)單的歡迎詞。


清單 7. 動(dòng)態(tài)輸出 VXML

				package com.ibm.vxml;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.PrintWriter;import java.util.Calendar;import javax.servlet.*;import javax.servlet.http.*;public class DynamicVoiceXMLServlet extends HttpServlet {  public void doGet(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    BufferedInputStream bis = null;    PrintWriter out = null;    try {      // Let the browser know that XML is coming      out = res.getWriter();      res.setContentType("text/xml");      // Output VXML      out.println("<?xml version=/"1.0/" encoding=/"UTF-8/"?>");      out.println("<vxml version=/"2.1/">");      out.println(" <form><block><prompt>");      // Output a greeting based on the time of day      Calendar cal = Calendar.getInstance();      int hour = cal.get(Calendar.HOUR_OF_DAY);      if (hour < 6) {        out.println("You're up early. Good morning.");      } else if (hour < 12) {        out.println("Good morning. How's your day so far?");      } else if (hour < 18) {        out.println("Half the day is done... good afternoon!");      } else{        out.println("Hope you are enjoying your evening.");      }      out.println(" </prompt></block></form>");      out.println("</vxml>");    } finally {      if (out != null) out.close();      if (bis != null) bis.close();    }  }  public void doPost(HttpServletRequest req, HttpServletResponse res)    throws ServletException, IOException {    doGet(req, res);  }}

 

呼叫者和 VXML 生成者之間的差異

    清單 7 也展示了 Voice XML 與動(dòng)態(tài)生成的 VXML 的另外一項(xiàng)特性:呼叫者可能并非 VXML 本身。例如,假設(shè)有一名居住在新西蘭的用戶呼叫 清單 7 所示的應(yīng)用程序。若當(dāng)時(shí)新西蘭時(shí)間是 10:00 PM,但輸出 VXML 的服務(wù)器位于科羅拉多州的丹佛,兩者之間問(wèn)候的消息可能非常古怪,例如 “您起得真早,早上好!” 這完全不恰當(dāng),情況還有可能更糟:如果您已為每周的特定日子添加好了問(wèn)候語(yǔ),那么實(shí)際上總會(huì)出現(xiàn)匹配錯(cuò)誤。

    根本問(wèn)題源于 VXML 和 Java 是在特定服務(wù)器所在的位置和時(shí)區(qū)運(yùn)行的,但可為世界各地的呼叫者所用。如果您的 servlet 未考慮到這方面的問(wèn)題,就會(huì)令一些呼叫者倍感困惑。您有以下幾種選擇:

  • 忽略差異,寄希望于呼叫者了解您的服務(wù)器并非在他們所在的時(shí)區(qū)運(yùn)行代碼。
  • 明確聲明日期和時(shí)間對(duì)應(yīng)于服務(wù)器所在位置。例如,下午問(wèn)候語(yǔ)可以是 “本地現(xiàn)在是下午。祝您愉快”。
  • 編寫代碼詢問(wèn)時(shí)區(qū)或與 GMT 的時(shí)差,然后根據(jù)這一信息提供問(wèn)候語(yǔ)。

    遺憾的是,這些選擇中沒(méi)有任何一種富于吸引力。第一種選擇的所作所為正如所說(shuō)明的那樣:基本忽略呼叫者。不言而喻,忽略呼叫者絕非 贏得和維持業(yè)務(wù)關(guān)系的正確方法。第二種想法 —— 給出本地時(shí)間并明確說(shuō)明這是本地時(shí)間 —— 也沒(méi)有太大的幫助,因?yàn)檫@種方法依然傾向于忽略呼叫者,只是在此過(guò)程中考慮得略微周全一些。


    最后一種選擇乍看上去似乎很有吸引力,可以很容易地編寫出 VXML,允許用戶提供一個(gè)與 GMT 的時(shí)差值,然后根據(jù)該信息應(yīng)答。但呼叫者傾向于盡可能迅速地獲得信息,應(yīng)答提示越多,惹惱呼叫者的風(fēng)險(xiǎn)就越大,他們可能會(huì)不滿地掛斷電話。因此,除非您提供的以日期或時(shí)間為基礎(chǔ)的服務(wù),否則要求呼叫者指明時(shí)區(qū)就是浪費(fèi)資源。甚至可能更糟的是,很多呼叫者并不知道自己所在地與 GMT 的時(shí)差,因此您要面臨提供時(shí)區(qū)、時(shí)區(qū)縮寫、夏令時(shí)……那將是一個(gè)冗長(zhǎng)煩瑣的列表。

為什么要自尋煩惱?

    那么我們?yōu)槭裁匆榻B這種基于日期的 VXML 生成呢?很大程度上是因?yàn)樗故玖诉@些問(wèn)題!您需要密切關(guān)注您的聽眾,盡力只提供那些與他們有關(guān)的信息,而不是與您的服務(wù)器或您所在地有關(guān)的信息。

    對(duì)于基于日期的處理,您要學(xué)習(xí)的課程就是:或許應(yīng)該采用一種更好的最終選擇來(lái)應(yīng)對(duì)呼叫者,除非絕對(duì)必要,否則應(yīng)完全避免采用基于日期或時(shí)間的事務(wù)。如果您預(yù)計(jì)到將有來(lái)自其他時(shí)區(qū)的呼叫者,那么提供與時(shí)間相關(guān)的功能就是自找麻煩。這一原則同樣適用于任何隨州、國(guó)家或陸地標(biāo)線的不同可能發(fā)生變化的數(shù)據(jù)。

    最后,有很多時(shí)候使用 servlet 輸出 VXML 并非良策。如果您只是要從一個(gè)靜態(tài)文件中提取 VXML,使用 servlet 帶來(lái)的好處極為有限(可能只有一點(diǎn)靈活性而已),但要添加代碼、編譯、調(diào)試、一個(gè) servlet 引擎和其他許許多多的東西,從而使語(yǔ)音應(yīng)用程序的復(fù)雜性大為增加。在這些簡(jiǎn)單的情況下,應(yīng)繼續(xù)使用靜態(tài) VXML 文件。

一些有趣的想法

    致此,您已看到,有時(shí) servlet 生成的 VXML 并無(wú) 意義。在結(jié)束本文之前,考慮以下幾種情況,在這些時(shí)候使用 Java 這樣的語(yǔ)言是絕佳 的電話應(yīng)用程序解決方案。此處未提供完整的示例,以后的文章中將予以介紹。

從一個(gè)數(shù)據(jù)庫(kù)中載入 VXML

    最顯而易見的與 VoiceXML 相關(guān)的 Java 應(yīng)用程序就是:使用數(shù)據(jù)庫(kù)提供動(dòng)態(tài) VXML 輸出。這或許也是大部分讀者在選擇閱讀本文時(shí)希望了解的內(nèi)容(但這篇文章中沒(méi)有核心示例,因此您可能未學(xué)到足夠多的知識(shí))。無(wú)論如何,JDBC 都能使您輕松連接數(shù)據(jù)庫(kù),然后利用 SQL 查詢的結(jié)果填充 VXML。

     例如,您要開發(fā)一個(gè)表,包含 VXM 的全部語(yǔ)法信息,然后將這些語(yǔ)法載入您所輸出的每個(gè) VXML 文件中。您不必為每一個(gè) VXML 文件編碼語(yǔ)法,而是可以在類似的文件間共享語(yǔ)法。更好的是,您可在所有 servlet 或一個(gè)特定 servlet 的實(shí)例中預(yù)載入這些語(yǔ)法。從而得益于將語(yǔ)法存儲(chǔ)在數(shù)據(jù)庫(kù)中,無(wú)需浪費(fèi)成本為每個(gè)請(qǐng)求載入語(yǔ)法。

根據(jù)用戶憑證載入 VXML

    另外一項(xiàng)出色的 Java 功能 —— 特別是在與 servlet、jsp 和基于 Web 的編程相關(guān)時(shí) —— 就是在會(huì)話中存儲(chǔ)用戶憑證的能力。這為您帶來(lái)穩(wěn)定的身份驗(yàn)證和授權(quán),以及高度定制的內(nèi)容。

    例如,考慮一個(gè)語(yǔ)音應(yīng)用程序,從詢問(wèn)用戶 ID 號(hào)和 PIN 開始(與當(dāng)今的大多數(shù)銀行或金融應(yīng)用程序類似)。您可根據(jù)數(shù)據(jù)庫(kù)(依靠 Java 平臺(tái)的強(qiáng)大力量)對(duì)這些憑證進(jìn)行驗(yàn)證,然后將呼叫者的 ID 存儲(chǔ)到一個(gè)會(huì)話變量中。此后,每個(gè)處理這名呼叫者的請(qǐng)求的 Java servlet 或 JSP 都可根據(jù)這些憑證了解為用戶提供哪些選擇。

    盡管許多 VoiceXML 替代產(chǎn)品都提供了類似的功能性,但很少有產(chǎn)品以與其基于 Web 的應(yīng)用程序版本之間共享代碼為自豪。換言之,Java 平臺(tái)允許您在 VoiceXML 應(yīng)用程序及其基于 Web 的版本間共享的不僅僅是數(shù)據(jù)庫(kù),還包括代碼組件。生成 VXML 的 servlet 可使用相同的身份驗(yàn)證和授權(quán)工具類作為生成 HTML 和 XHTML 的 servlet,應(yīng)答電話呼叫的 JSP 可與處理 HTTP 請(qǐng)求的 JSP 共享緩存數(shù)據(jù)庫(kù)連接。因而,您將得到一個(gè)能夠處理多種類型客戶機(jī)的應(yīng)用基礎(chǔ)設(shè)施,而不必為每種類型的客戶機(jī)創(chuàng)建一個(gè)完整的應(yīng)用程序。

結(jié)束語(yǔ)

    本文蜻蜓點(diǎn)水地介紹了可用 VXML 和 Java 平臺(tái)實(shí)現(xiàn)的功能。介紹了開發(fā) VXML 的過(guò)程,然后為您展示了如何將 Java 技術(shù)整合到這一過(guò)程之中。介紹過(guò)程中給出了很多線索,告訴您利用 Java 代碼來(lái)開發(fā)豐富、動(dòng)態(tài)的 VoiceXML 應(yīng)用程序的所有有趣的方式。

    我還說(shuō)明了 VoiceXML 開發(fā)人員在語(yǔ)音應(yīng)用程序誤用 Java 技術(shù)的幾種常見形式。處理日期和時(shí)間時(shí)耍小聰明、試圖提供地方性的服務(wù)或是忘卻服務(wù)器當(dāng)?shù)貢r(shí)間和呼叫者當(dāng)?shù)貢r(shí)間之間的差異無(wú)疑會(huì)令用戶灰心離去。應(yīng)將 Java 視為 VoiceXML 的一種工具,不要濫用 DateCalendar 類。

    在后續(xù)的文章中,我將繼續(xù)探討這些主題和更多內(nèi)容,以本文給出的原則為基礎(chǔ)進(jìn)行擴(kuò)展。如果您希望了解構(gòu)建豐富的語(yǔ)音應(yīng)用程序、開發(fā)與數(shù)據(jù)庫(kù)交互的電話應(yīng)用程序、跟蹤用戶、提供個(gè)性化內(nèi)容的更多內(nèi)容,請(qǐng)繼續(xù)關(guān)注本系列文章。另外,訪問(wèn) Voxeo.com,獲得一兩個(gè) servlet,來(lái)提供您自己的 VXML。請(qǐng)繼續(xù)關(guān)注下期文章,了解更多內(nèi)容。

 

QQread.com 推出各大專業(yè)服務(wù)器評(píng)測(cè) linux服務(wù)器的安全性能 SUN服務(wù)器 HP服務(wù)器 DELL服務(wù)器 IBM服務(wù)器 聯(lián)想服務(wù)器 浪潮服務(wù)器 曙光服務(wù)器 同方服務(wù)器 華碩服務(wù)器 寶德服務(wù)器


參考資料

學(xué)習(xí)

  • 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文

  • X+V is a markup language, not a Roman math eXPression(Les Wilson,developerWorks,2003 年 8 月):通過(guò)考察 X+V(XHTML 加 Voice)探索您的選擇 —— 這是一種用于開發(fā)多模應(yīng)用程序的 Web 標(biāo)記語(yǔ)言。

  • Multimodal interaction and the mobile Web, Part 1: Multimodal auto-fill(Gerald McCobb,developerWorks,2005 年 11 月):邁向多模交互開發(fā)的第一步。

  • Speech-enable Web apps using RDC with Voice Toolkit(Girish Dhanakshiru,developerWorks,2005 年 3 月):WebSphere 開發(fā)人員可使用 Voice Toolkit 和 Rational Application Developer(RAD)向任何現(xiàn)有 Web 應(yīng)用程序添加語(yǔ)音。

  • Start developing CCXML applications(Susan Jackson 和 Hannah Parker,developerWorks,2004 年 6 月):Call Control XML(CCXML)語(yǔ)言的簡(jiǎn)介性教程。

  • 選擇一種平臺(tái):Voxeo 解釋了 CallXML、CCXML 和 VoiceXML 之間的差別。

  • W3C's Voice Browser Activity 主頁(yè):包括規(guī)范、FAQ、工具和有用文章的鏈接。

  • VoiceXML 2.1:閱讀 W3C 候選推薦標(biāo)準(zhǔn)。

  • CCXML Version 1.0 規(guī)范:呼叫控制技術(shù)的特性和最新開發(fā)成果。

  • Java and XML, Second edition(Brett McLaughlin;O'Reilly Media, Inc., 2001):包括關(guān)于 XHTML、在 Web 上提供 XML 以及為多種設(shè)備提供內(nèi)容的相關(guān)資料。

  • XML in a Nutshell, Third edition(Elliotte Rusty Harold, W. Scott Means;O'Reilly Media, Inc.,2004):一份出色的 XML 資源大全,還有專門介紹 Web 上的 XML 的章節(jié)。

  • Web 開發(fā)專區(qū):查找關(guān)于各種基于 Web 的解決方案的文章和教程。

  • developerWorks XML 專區(qū):獲得數(shù)百份關(guān)于 XML 的文章和教程。

  • developerWorks Wireless 技術(shù)專區(qū):獲得關(guān)于各種無(wú)線解決方案的內(nèi)容。

  • developerWorks Java 技術(shù)專區(qū):查看大量與 Java 相關(guān)的文章和教程。


獲得產(chǎn)品和技術(shù)

  • Voxeo.com:VoiceXML 信息的絕妙資源。

  • Voxeo Community Tools:尋找與 VoiceXML 相關(guān)的插件和工具的起點(diǎn)。

  • IBM 試用軟件:可在 developerWorks 免費(fèi)下載。


討論

  • 通過(guò)參與 developerWorks blogs 加入 developerWorks 社區(qū)。



 

關(guān)于作者

在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖一)

在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖六)

在Java Web框架中創(chuàng)建VoiceXML頁(yè)面(圖一)

Brett McLaughlin 從 Log 時(shí)代就開始使用計(jì)算機(jī)了。(還記得那個(gè)小三角嗎?)近年來(lái),他已經(jīng)成為 Java 和 XML 社區(qū)中最受歡迎的作者和程序員之一了。他曾經(jīng)在 Nextel Communications 實(shí)現(xiàn)過(guò)復(fù)雜的企業(yè)系統(tǒng),在 Lutris Technologies 編寫過(guò)應(yīng)用服務(wù)器,最近在 O'Reilly Media, Inc. 繼續(xù)撰寫和編輯這方面的圖書。Brett 最新的著作 Head Rush Ajax,為 Ajax 帶來(lái)了獲獎(jiǎng)的創(chuàng)新 Head First 方法。他的近作 Java 1.5 Tiger: A Developer's Notebook 是關(guān)于這一 Java 技術(shù)最新版本的第一部專著。經(jīng)典作品 Java and XML 仍然是在 Java 語(yǔ)言中使用 XML 技術(shù)的權(quán)威著作之一。

(出處:http://www.companysz.com)



發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 亚洲国产精品久久久久久久久久 | 一级毛片播放 | 欧美精品日日鲁夜夜添 | 免费在线观看一级片 | 国产精品国产成人国产三级 | 中文字幕在线播放不卡 | 欧美日韩亚洲成人 | 少妇一级淫片免费放播放 | 久久网站免费 | 久久国产91 | 羞羞视频免费视频欧美 | 国产乱xxxx | 国产精品69页 | 男女羞羞视频在线观看免费 | av大全在线播放 | 精品国产一区二区三区四区阿崩 | 成人啪啪18免费网站 | 妇子乱av一区二区三区 | 国产99久久精品一区二区300 | 在线中文字幕不卡 | 一级免费大片 | 欧美性色生活片免费播放 | 免费a级黄色片 | 少妇一级淫片免费放4p | 欧美视频国产精品 | 国产成人精品免费视频大全最热 | 成人做爽爽爽爽免费国产软件 | 叶子楣成人爽a毛片免费啪啪 | 成人污在线 | 午夜网站视频 | 欧美人与牲禽动交精品一区 | 91久久精品一区二区 | 羞羞视频在线免费 | 日日草夜夜| av中文字幕免费在线观看 | 99精品国产小情侣高潮露脸在线 | 国产一区影院 | 双性帝王调教跪撅打屁股 | 久久久www成人免费精品 | 久久成人激情视频 | 精品一区二区三区免费看 |