首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Web 框架中動態生成 VoiceXML:從靜態頁面到語音應用實戰

     編輯:Java 相關知識

VoiceXML (VXML) 讓普通電話也能成為 Web 客戶端,用戶以語音或按鍵與應用互動。本文示範如何在 Java Servlet 容器中由「靜態 VXML 檔案」漸進至「動態生成 VXML」,並解決時區、快取、架構決策等實務陷阱。適用於 PHP、Ruby 等同理可轉。

VoiceXML 快速入門

最小 VXML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1">
  <form>
    <block><prompt>Things are working correctly! Congratulations.</prompt></block>
  </form>
</vxml>
  • Voxeo 提供免費 10 MB 空間與 Application Manager,可將 VXML URL 映射至長途/800/Skype 號碼,極適合開發測試。
  • 標準:VoiceXML 2.0/2.1 (W3C)、CCXML(呼叫控制)、CallXML(Voxeo 專有,不建議綁定廠商)。

Voxeo Application Manager

映射 VXML 到電話號碼

成功取得電話號碼

階段一:Servlet 靜態轉發 VXML

先寫好可運行的 VXML 檔,再用 Servlet 讀取並輸出,避免同時除錯 XML 語法與 Java 邏輯。

public class VoiceXMLServlet extends HttpServlet {
  private static final String VXML_FILENAME = "simple-voice_recog.xml";
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    String vxmlDir = getServletContext().getInitParameter("vxml-dir");
    File vxml = new File(vxmlDir, VXML_FILENAME);
    res.setContentType("text/xml");
    res.setContentLength((int)vxml.length());
    try (FileInputStream fis = new FileInputStream(vxml);
         BufferedInputStream bis = new BufferedInputStream(fis);
         ServletOutputStream out = res.getOutputStream()) {
      byte[] buf = new byte[4096];
      int len;
      while ((len = bis.read(buf)) != -1) out.write(buf, 0, len);
    }
  }
  protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    doGet(req, res);  // 支援 POST
  }
}

web.xml 設定 vxml-dir context-param,部署後瀏覽 Servlet 應見原始 XML,再映射電話號碼測試語音播放。

Servlet 輸出 VXML

階段二:動態生成 VXML — PrintWriter 模式

改用 PrintWriter 直接寫入字串,支援動態內容(如問候語依時間變化)。

public class DynamicVoiceXMLServlet extends HttpServlet {
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    res.setContentType("text/xml");
    PrintWriter out = res.getWriter();
    out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    out.println("<vxml version=\"2.1\">");
    out.println(" <form><block><prompt>");
    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>");
  }
  protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    doGet(req, res);
  }
}

關鍵陷阱:伺服器時區 ≠ 呼叫者時區

伺服器在丹佛 (MDT),用戶從紐西蘭 (NZST) 來電,伺服器傍晚 6 PM 卻對用戶說「Good morning」。解法三選一:

  1. 忽略差異(不推薦,體驗極差)。
  2. 明確宣告「伺服器本地時間」,如「伺服器現在是下午,祝您愉快」。
  3. 語音提示用戶輸入時差或時區(增加互動步驟,易惱人)。

最佳實務:除非業務強相關(如鬧鐘、行程提醒),否則避免在 VXML 中使用伺服器端日期/時間。改用相對時間(「稍後 30 分鐘」)、或由客戶端(電話網關)提供時間資訊。

何時「不該」用 Servlet 生成 VXML?

  • 純靜態內容:直接放靜態 .vxml 檔於 Web 根目錄,效能最好、零維護。
  • 簡單條件分支:VXML 自帶 <if>/<filled> 邏輯即可處理。
  • 需求僅為「多語系」:用 <prompt xml:lang="zh-TW"> 或多檔案切換。

動態 VXML 的高價值場景

1. 資料庫驅動語法庫

將語音辨識 <grammar> 存於 DB,Servlet 依業務類型動態組裝,多應用共享、熱更新、免重編譯。

2. 用戶憑證驅動個性化選單

Session 存放用戶 ID/角色,Servlet 依權限輸出不同 <menu>、<field>,同一套 Java 驗證/授權代碼同時服務 Web 與語音通道。

3. 整合外部服務 (CRM、計費、地圖)

Servlet 呼叫 EJB/Web Service 取得即時資料,內插 VXML 回應,實現「語音版 Mashup」。

架構建議:共享核心、分離表現

  • 核心服務層:Java Bean/EJB/Spring Service,無协议耦合。
  • 表現層:
     • Web:JSP/Struts/JSF → HTML
     • Voice:Servlet/JSP → VoiceXML
     • Mobile:REST/JSON → App
  • 同一個 Service 方法可被 Web Action 與 Voice Servlet 同時調用,真正實現「一次開發、多渠道觸達」。

總結

  1. 先寫可跑的靜態 VXML,用 Voxeo 免費號碼驗證流程。
  2. Servlet 靜態轉發 → 確認無誤 → 改動態生成。
  3. 用 PrintWriter 而非 out.println() 拼接字串,維護性較佳。
  4. 嚴禁濫用伺服器時間;若需時間感知,採用相對時間或客戶端提供。
  5. 靜態內容留給 Web Server,動態邏輯才進 Servlet,避免過度工程。
  6. 核心業務邏輯下沉共享層,VoiceXML 只是另一種 View Renderer。

下一篇將示範:資料庫驅動動態 Grammar、Session 狀態跨語音/網頁同步、VoiceXML 錯誤處理與日誌審計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved