亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

在Java Web框架中創建VoiceXML頁面

2019-11-18 16:17:29
字體:
來源:轉載
供稿:網友

2006 年 11 月 23 日

    對于絕大多數 Web 開發人員來說,輸出 Html、XHTML 乃至 xml 是一項微不足道的任務,它只不過是創建和部署 Web 應用程序的常規流程。從顯示 Internet 頁面到應答電話呼叫看似一個巨大的飛躍,但實際并非如此。在這篇文章中,您將看到相同的技術如何幫助您動態創建 Web 頁面以便接聽(虛擬的)電話并應答呼叫。

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

    這種最新型的應用程序(用戶通過電話訪問在線服務)的更恰當的名稱是電話應用程序(telephone application。顯而易見,由于電話無法用來 “單擊一個鏈接”,應用程序交互幾乎全部是通過語音處理的。用戶不是采用單擊鏈接的方式,而是說出 “賬戶信息” 或使用鍵盤按預先錄制好的指令進行操作。

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

VoiceXML、CCXML 還是 CallXML?

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

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

    構建語音應用程序最常用的標準就是 VoiceXML。絕大多數 VXML 瀏覽器都支持 VoiceXML 2.0,本文通篇將使用這個版本的 VXML。VXML 符合 W3C 規范且發展迅速,目前的版本依然是 v2.1。VXML 3.0 即將推出。

    CCXML 是 Call Control XML 的縮寫,也是電話標記方面符合 W3C 規范的最新一員。CCXML 比大多數 VoiceXML 實現更為高級,提供了對回叫、事件偵聽器和多路及多方會話的支持。但除非您特別需要這些屬性,否則最好的選擇或許是繼續使用 VoiceXML,VoiceXML 更加穩定,應用也更廣泛。

    CallXML 是特定于 Voxeo 的一種平臺。CallXML 學習起來非常輕松,并提供了對按鍵電話(toUChtone)輸入的支持(請注意,它并不支持語音識別)。CallXML 的最大缺陷就是特定于廠商。Voxeo 是一個非常出色的站點,具有無數資源,但被一家廠商鎖定絕對不是個好主意。此時,大多數開發人員會再次發現,VoiceXML 更適合他們的需求。

VoiceXML 101

    在接觸 VoiceXML 世界的 Java 方面之前,您應大致理解 VoiceXML 應用程序的工作原理。之后,我將為您介紹一個非常簡單的 VoiceXML 應用程序。示例應用程序將使您能夠查看 VXML 文件,同時確保您有權訪問(且可使用)Voxeo 的 call-assignment 服務,這個服務對本文后面的內容非常關鍵。

一個簡單的 VXML 頁面

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



清單 1. 一個非常簡單的 VXML 文件

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

    對于 VoiceXML 來說,這非?;A,如果您對語法的了解還不夠清楚,請查看 參考資料 中列出的其他 VoiceXML 文章。清單 1 中的 VXML 文件只包含一條提示信息,未提供任何交互功能,在處理 Java 代碼的一節中,您將看到更高級的用法。但目前,使用這個簡單的測試用例來確保您的環境工作正常。

上傳應用程序

    接下來,將您的 VXML 文件放在某個可以訪問的位置。如果您有 ISP,只需將 VXML 文件上傳到您的 Web 站點,您可能也會希望在 Web 根目錄下為您的 VoiceXML 文件創建一個目錄,例如 /voicexml 或 /voice。確保這些目錄和文件可通過 Web 訪問(如果您不清楚如何進行這些操作,請咨詢您的系統管理員或 ISP)。

    如果您沒有 ISP,那么可以在 Voxeo 注冊,以便使用該站點的 File Manager。您應已建立了一個 Voxeo 賬戶,它附帶 10 MB 的主機空間,因此這是個不錯的免費選擇。(10 MB 可以容納大量 VXML 文件!)

    使 VXML 應用程序聯機之后,我們還想確定能夠通過在 Web 瀏覽器中輸入 URL 來訪問它。根據您所使用的具體瀏覽器不同,可能會要求您下載 XML 文件,也可能會在您的瀏覽器中以某種形式呈現它。這只是一個測試,確保您的 VXML 可用,因此即使您的計算機沒有開始跟您交談,也不要太過憂慮。VXML 聯機后,也就作好了將其與一個電話號碼連接的準備。

為您的應用程序分配一個電話號碼

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

如果您尚未注冊獲得一個 Voxeo 賬戶,那么現在就去注冊吧!從這里開始,以下的示例都需要您使用 Voxeo 工具。建立賬戶是免費的,沒有任何責任,您更會獲得杰出的工具與支持。現在就去 注冊獲得一個開發者賬戶吧!

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

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


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

QQRead.com 推出數據恢復指南教程 數據恢復指南教程 數據恢復故障解析 常用數據恢復方案 硬盤數據恢復教程 數據保護方法 數據恢復軟件 專業數據恢復服務指南

選擇 Add Application,然后選擇 VoiceXML 2.0 作為部署平臺。

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


圖 2. 將一個 VXML 文件映射到一個電話號碼
在Java Web框架中創建VoiceXML頁面(圖三)

    單擊 Create Application,Voxeo 將為您的應用程序分配一些電話號碼。圖 3 展示了最終屏幕(略微向下滾動了一點),以及 VXML 文件的所有訪問點。


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


    這一功能值得您花時間去注冊 Voxeo,您現在可以通過長途電話號碼、800 免費電話號碼和 Skype 訪問您的 VXML 文件,而這些方法還只是其中的一小部分。這非常好,因為您不必使用 Voxeo 工具去測試應用程序。更好的是,您可以讓您的老板在無需具備 Voxeo 站點賬戶的情況下完成測試!

測試應用程序

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

    好,就是這樣:在大約五分鐘內,您使您的電話與一個 XML 文件進行了交談。現在就可以看看 Java 代碼了,并了解如何動態地生成 VXML。

Java 和 VXML

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

 

創建一個 VXML 文件的原型

    首先要開發 VXML 文件。不要打開一個 IDE 并開始編寫 Java 代碼,而是啟動一個文本編輯器,忍住立即添加 packageimport 語句的渴望。構建一個簡單的 VXML 文件,就像本文前面給出的示例那樣。

    例如,清單 2 是又一個非?;A的 VXML 文件。它是一個語音識別 VXML 文件,接入一個恰當的設備并提供某些關于呼叫選擇的注釋。


清單 2. 另外一個基本的 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>


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

    如果您直接跳到 Java,那么很可能會導致輸出中出錯,代碼中也會出錯。結果是要在一個 Web 框架內嘗試同步調試一個 VXML 文件(XML)和一個 Servlet(Java),這種調試極其艱難。不要添加所有這些變量(沒有雙關的意思),務必從一個可正常工作的 VXML 文件入手。然后 準備運行 Java 代碼。

 

讀入文件

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


清單 3. 載入一個 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();    }  }}

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


清單 4. servlet 的上下文參數

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

    若編譯 servlet 并嘗試在 Web 瀏覽器中載入它,您只會看到一個空白的屏幕,同樣,您應確保至少會看到這樣的空白屏幕。如果得到錯誤,就需要予以更正。例如,常常會出現文件訪問問題或 VXML 文件路徑錄入錯誤。一旦得到了空白屏幕,也就準備好實際輸出 VXML 文件了。

從 servlet 中輸出 VXML

首先,您需要訪問一個輸出對象,這樣才能向瀏覽器發送內容。這非常簡單:

      // 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();			

從文件提取內容也非常簡單,只要使用一行代碼即可:

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


    雖然上述代碼看似已經足夠,但您依然需要告知瀏覽器您正在向它發送 XML。切記,瀏覽器用于 HTML,某些瀏覽器可能無法順利接收 XML。您可設置內容類型,也可設置內容的長度,只要再次使用 HttpServletResponse 對象即可:

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

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


清單 5. 完整且準備好載入 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();    }  }}

測試 servlet 載入的 VoiceXML

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


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

    若您未得到類似輸出,確定您的文件是否位于您希望的位置,并確保沒有任何權限問題。您還要檢查 servlet 引擎的日志或請求系統管理員的幫助。

    現在就準備好將電話號碼映射到您的 servlet 了。重新回到 Voxeo.com 的 Application Mnager,添加一個新應用程序(可能會看到之前您使用過的應用程序)。確保選中 VoiceXML 2.0,然后輸入新應用程序的名稱和 servlet 的 URL。Voxeo 將創建應用程序并為其分配一個電話號碼。

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

 

部分可選的附加項

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

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

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


    另外一個簡單的附加項用于允許瀏覽器切實獲知您正在輸出一個 VXML 文件的內容。為此,設置 servlet 中的 Content-disposition 響應頭,如下:

      // 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);			

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

動態 VoiceXML

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

    當您開始考慮動態 VoiceXML 時,Java 平臺就顯示出了自己的優勢。它提供了輕松輸出 XML 的能力,還有與數據庫、目錄服務器、身份驗證存儲和會話的交互。此外,它還能夠證實,構建動態 VXML 將消除基于語音的系統的部分刻板性。

    在這一節中,我將逐步為您介紹創建一個輸出動態 VXML 的 Java servlet 的步驟。

通過 out.println() 輸出 VXML

    您已經了解了如何訪問 ServletOutputStream,然后在輸出流中插入字節。但如果從源(例如一個靜態 VXML 文件)傳輸到輸出流的不僅僅是字節,那么直接處理字節的方式幾乎無法管理控制。

    如果您希望自行創建 VXML,最好使用 PrintWriter。利用這個類,您可發出整個字符串,使之對于創建和輸出動態內容更為有用。這只需要對代碼略加修改,如下所示:

  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();    }  }

    另外,不要忘記導入 java.io.PrintWriter 類:它不會自動成為對您的 servlet 的代碼基可用。

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


清單 6. 動態輸出 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);  }}



    現在您可編譯這個 servlet、向 Voxeo 注冊它,并通過電話訪問它,與處理 清單 1 的方法相同?,F在我們來看一些示例,從而展示像 Java 這樣的語言的動態編程能力。

添加時間提醒

    基于 servlet 的 VXML 輸出的一項最簡單的用途就是添加時間提醒。利用 Java 代碼獲取當前日期和時間非常輕松,因此這是個不錯的起點。

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


清單 7. 動態輸出 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 與動態生成的 VXML 的另外一項特性:呼叫者可能并非 VXML 本身。例如,假設有一名居住在新西蘭的用戶呼叫 清單 7 所示的應用程序。若當時新西蘭時間是 10:00 PM,但輸出 VXML 的服務器位于科羅拉多州的丹佛,兩者之間問候的消息可能非常古怪,例如 “您起得真早,早上好!” 這完全不恰當,情況還有可能更糟:如果您已為每周的特定日子添加好了問候語,那么實際上總會出現匹配錯誤。

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

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

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


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

為什么要自尋煩惱?

    那么我們為什么要介紹這種基于日期的 VXML 生成呢?很大程度上是因為它正展示了這些問題!您需要密切關注您的聽眾,盡力只提供那些與他們有關的信息,而不是與您的服務器或您所在地有關的信息。

    對于基于日期的處理,您要學習的課程就是:或許應該采用一種更好的最終選擇來應對呼叫者,除非絕對必要,否則應完全避免采用基于日期或時間的事務。如果您預計到將有來自其他時區的呼叫者,那么提供與時間相關的功能就是自找麻煩。這一原則同樣適用于任何隨州、國家或陸地標線的不同可能發生變化的數據。

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

一些有趣的想法

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

從一個數據庫中載入 VXML

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

     例如,您要開發一個表,包含 VXM 的全部語法信息,然后將這些語法載入您所輸出的每個 VXML 文件中。您不必為每一個 VXML 文件編碼語法,而是可以在類似的文件間共享語法。更好的是,您可在所有 servlet 或一個特定 servlet 的實例中預載入這些語法。從而得益于將語法存儲在數據庫中,無需浪費成本為每個請求載入語法。

根據用戶憑證載入 VXML

    另外一項出色的 Java 功能 —— 特別是在與 servlet、jsp 和基于 Web 的編程相關時 —— 就是在會話中存儲用戶憑證的能力。這為您帶來穩定的身份驗證和授權,以及高度定制的內容。

    例如,考慮一個語音應用程序,從詢問用戶 ID 號和 PIN 開始(與當今的大多數銀行或金融應用程序類似)。您可根據數據庫(依靠 Java 平臺的強大力量)對這些憑證進行驗證,然后將呼叫者的 ID 存儲到一個會話變量中。此后,每個處理這名呼叫者的請求的 Java servlet 或 JSP 都可根據這些憑證了解為用戶提供哪些選擇。

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

結束語

    本文蜻蜓點水地介紹了可用 VXML 和 Java 平臺實現的功能。介紹了開發 VXML 的過程,然后為您展示了如何將 Java 技術整合到這一過程之中。介紹過程中給出了很多線索,告訴您利用 Java 代碼來開發豐富、動態的 VoiceXML 應用程序的所有有趣的方式。

    我還說明了 VoiceXML 開發人員在語音應用程序誤用 Java 技術的幾種常見形式。處理日期和時間時耍小聰明、試圖提供地方性的服務或是忘卻服務器當地時間和呼叫者當地時間之間的差異無疑會令用戶灰心離去。應將 Java 視為 VoiceXML 的一種工具,不要濫用 DateCalendar 類。

    在后續的文章中,我將繼續探討這些主題和更多內容,以本文給出的原則為基礎進行擴展。如果您希望了解構建豐富的語音應用程序、開發與數據庫交互的電話應用程序、跟蹤用戶、提供個性化內容的更多內容,請繼續關注本系列文章。另外,訪問 Voxeo.com,獲得一兩個 servlet,來提供您自己的 VXML。請繼續關注下期文章,了解更多內容。

 

QQread.com 推出各大專業服務器評測 linux服務器的安全性能 SUN服務器 HP服務器 DELL服務器 IBM服務器 聯想服務器 浪潮服務器 曙光服務器 同方服務器 華碩服務器 寶德服務器


參考資料

學習

  • 您可以參閱本文在 developerWorks 全球站點上的 英文原文 。

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

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

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

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

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

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

  • VoiceXML 2.1:閱讀 W3C 候選推薦標準。

  • CCXML Version 1.0 規范:呼叫控制技術的特性和最新開發成果。

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

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

  • Web 開發專區:查找關于各種基于 Web 的解決方案的文章和教程。

  • developerWorks XML 專區:獲得數百份關于 XML 的文章和教程。

  • developerWorks Wireless 技術專區:獲得關于各種無線解決方案的內容。

  • developerWorks Java 技術專區:查看大量與 Java 相關的文章和教程。


獲得產品和技術

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

  • Voxeo Community Tools:尋找與 VoiceXML 相關的插件和工具的起點。

  • IBM 試用軟件:可在 developerWorks 免費下載。


討論

  • 通過參與 developerWorks blogs 加入 developerWorks 社區。



 

關于作者

在Java Web框架中創建VoiceXML頁面(圖一)

在Java Web框架中創建VoiceXML頁面(圖六)

在Java Web框架中創建VoiceXML頁面(圖一)

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

(出處:http://www.49028c.com)



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情区在线播放| 午夜精品一区二区三区在线| 一区二区三欧美| 亚洲欧美国产视频| 97视频在线观看免费高清完整版在线观看| 日韩美女视频免费在线观看| 久久久久久com| 成人福利在线视频| 国产一区二区三区在线播放免费观看| 亚洲天天在线日亚洲洲精| 欧美极品少妇xxxxⅹ喷水| 久久伊人精品一区二区三区| 亚洲天堂av综合网| 亚洲的天堂在线中文字幕| 色综合久久久久久中文网| 精品国产91乱高清在线观看| 亚洲欧美精品在线| 欧美在线免费视频| 亚洲国产福利在线| 日韩精品福利网站| 国产精品麻豆va在线播放| 日本精品久久久久久久| 欧美福利在线观看| 日韩在线视频免费观看| 亚洲国产精品va在线观看黑人| 亚洲天堂男人天堂女人天堂| 国产做受69高潮| 亚洲欧洲日产国码av系列天堂| 精品一区二区三区电影| 国产在线视频一区| 国产亚洲人成网站在线观看| 北条麻妃99精品青青久久| 欧美激情网站在线观看| 亚洲自拍av在线| 亚洲激情视频在线观看| 亚洲一区二区黄| 欧美三级免费观看| 57pao成人国产永久免费| 亚洲免费一在线| 69国产精品成人在线播放| 国产精品免费小视频| 日韩精品极品在线观看播放免费视频| 欧美国产日韩一区| 国产一区二区三区日韩欧美| 亚洲国产日韩欧美在线动漫| 亚洲精品成人av| 亚洲欧美在线一区二区| 久久这里只有精品99| 成人欧美一区二区三区黑人孕妇| 欧美激情视频一区二区三区不卡| 精品亚洲一区二区三区四区五区| 精品丝袜一区二区三区| www国产精品com| 主播福利视频一区| 91中文精品字幕在线视频| 亚洲精品一区中文| 亚洲黄页网在线观看| 亚洲色图13p| 国模叶桐国产精品一区| 欧美丰满少妇xxxx| 日韩精品高清在线| 51精品国产黑色丝袜高跟鞋| 亚洲免费影视第一页| 亚洲aⅴ男人的天堂在线观看| 国产精品69久久| 亚洲欧美日韩久久久久久| 欧美极品在线视频| 日韩中文第一页| 久久久亚洲精选| 日韩中文字幕亚洲| 久久国产精品免费视频| 欧美性一区二区三区| 午夜精品免费视频| 精品成人69xx.xyz| 亚洲国产91色在线| 精品久久久久久亚洲国产300| 久久久亚洲网站| 国产香蕉一区二区三区在线视频| 奇米四色中文综合久久| 51ⅴ精品国产91久久久久久| 青青青国产精品一区二区| 亚洲精品国产电影| 国产成人亚洲综合青青| 日韩**中文字幕毛片| 久久久久久久久久久成人| 亚洲xxxxx性| 久久精品成人动漫| 揄拍成人国产精品视频| 色视频www在线播放国产成人| 国产一区二区视频在线观看| 97精品一区二区三区| 久久久国产精彩视频美女艺术照福利| 国产不卡av在线| 91免费视频国产| 亚洲一区二区三区毛片| 91国在线精品国内播放| 欧美日在线观看| 亚洲国产成人爱av在线播放| 午夜精品美女自拍福到在线| 欧美影院成年免费版| 国产午夜精品理论片a级探花| 91伊人影院在线播放| 久久亚洲欧美日韩精品专区| 精品国产一区二区三区久久久狼| 亚洲日本成人网| 久久国产精品99国产精| 91老司机在线| 中文字幕精品国产| 亚洲性av网站| 国产视频自拍一区| 精品国产成人av| 亚洲精品日韩av| 日韩亚洲在线观看| 亚洲国产成人爱av在线播放| 欧美另类高清videos| 国产精品27p| 国产精品福利久久久| 亚洲第一色在线| 北条麻妃一区二区三区中文字幕| 欧美日韩国产成人高清视频| 亚洲国产天堂久久国产91| 日韩av片永久免费网站| 亚洲福利小视频| 亚洲自拍偷拍色片视频| 国产精品自在线| 精品国产一区二区三区在线观看| 97精品免费视频| 久久久女人电视剧免费播放下载| 国产精品国语对白| 亚洲视频在线观看| 久久91超碰青草是什么| 亚洲性夜色噜噜噜7777| 在线日韩日本国产亚洲| 91色精品视频在线| 国产剧情日韩欧美| 国产97在线观看| 成人黄色午夜影院| 久久99热这里只有精品国产| 国产免费一区二区三区香蕉精| 日韩av男人的天堂| 精品毛片网大全| 热99久久精品| 热门国产精品亚洲第一区在线| 欧美肥臀大乳一区二区免费视频| 91欧美日韩一区| 日韩中文理论片| 亚洲国产精品va在看黑人| 国产精品永久免费在线| 一区二区成人精品| 国产一区二区三区视频| 日韩免费中文字幕| 亚洲欧美综合精品久久成人| 麻豆国产va免费精品高清在线| 中文字幕日韩在线视频| 久久精品一偷一偷国产| 国产在线观看不卡| 亚洲毛片在线看| 欧美尤物巨大精品爽| 欧美性xxxxx极品| 国产亚洲精品久久久优势| 久久久久99精品久久久久| 亚洲人成网站777色婷婷| 久久久www成人免费精品张筱雨| 国产乱肥老妇国产一区二|