熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

再談通過 Java 執行 POST 操作

2013-11-15 11:39:23  來源: JSP教程 

  我的上一篇關於 從 applet 中執行 POST 操作的技巧在讀者中引出了許多問題其中最突出的問題是如何顯示由 Web 服務器上的 POST CGIbin 處理程序返回的 HTML 文檔?在這篇技巧中我們將探索這一問題的解決方法並深入研究幾個很棒的服務器端的 Java 問題
  注意本技巧假定您知道讀者提出的有關通過 Java 執行 POST 操作的一些基本問題如果您還不熟悉這些概念請參考Java 技巧
  
  那麼我們如何顯示來自 applet 的 POST 的結果呢?這一問題有四個答案按照難易程度遞增的順序排列依次為
  
  無法顯示
  別執行 POST 操作
  使用 bean
  作弊
  正如在Java 技巧 中討論的那樣浏覽器目前所用的安全性管理器不允許在浏覽器中顯示由 applet 生成的 HTML浏覽器僅允許我們將它指向 URLURL 將代表我們將它顯示出來這種情況難以令人滿意!
  
  我們通過 難以置信! 不使用 POST 就可以避開顯示 POST 結果的這種限制我們可以將一些信息編碼在 URL 中然後再將編碼後的 URL 提供給 showDocument() 方法這些信息可作為 GET 請求的參數傳遞給 Web 服務器不幸的是這存在一些缺陷只能傳輸數量有限的數據 此外在這個過程中 URL 被更改這樣做相當笨拙稍後我們會看到采用這種編碼方式的一個示例
  
  最近Sun 的 JavaSoft 分公司發布了 HTML renderer bean(還有幾個別的商用軟件)這樣將這個 bean 作為 applet 的一部分並用它來顯示網頁就成為可能有什麼缺點?大小兼容性和成本這個 bean 當然不小它需要支持 bean 的浏覽器而且不是免費的當然我們完全可以花時間來編寫自己的翻譯組件但那是一種愚蠢的做法
  
  這個問題的一種有趣而有建設性的解決方案就是作弊在這個特例中我們讓服務器端的代碼(例如 CGIbin 腳本)與我們的 applet 共同作弊基本思想很簡單將 POST 與隨後的 GET 結合起來使用這個過程如下所示
  
  applet 仍然通過 POST 操作將信息發送給服務器
  服務器利用 POST 信息生成 HTML
  服務器將 HTML 保存到 Web 服務器上的文件中
  服務器向 applet 返回一個魔力鍵
  applet 將這個鍵編碼在 URL 中並返回給服務器
  applet 通過在 showDocument() 調用中使用生成的 URL 來通知浏覽器顯示網頁
  服務器接收 GET 請求並提取魔力鍵參數
  服務器檢索與此魔力鍵相關的文件
  服務器將文件中的 HTML 內容返回給浏覽器
  浏覽器將 HTML 內容顯示出來
  這種返回處理無疑比其他解決方案更復雜但現在這種處理適用於客戶機和服務器的廣泛組合方式這種處理的缺點在於完成一個完整的事務必須執行多個 HTTP 請求我們必須在多個請求的之間維護狀態信息以便能跟蹤正在進行的事務(回憶一下HTTP 是一種無狀態的請求/響應協議)穩健地處理這些必要的狀態信息可能相當具有挑戰性Tcl 腳本語言及 Sprite 分布式操作系統之父 John Ousterhout 曾經說過在分布式計算中狀態是第二麻煩的問題它是最麻煩的問題
  
  服務器部分最復雜所以讓我們先來看一下 applet:) 這個 applet 與以前的Java 技巧 中所用的 Happy applet 僅有幾點區別到服務器的 POST 操作是相同的但我們必須修改讀取服務器響應的的部分input = new DataInputStream (urlConngetInputStream ());
  
  String str = null;
  String firstLine = null;
  while (null != ((str = inputreadLine())))
  {
  if (null == firstLine)
  firstLine = str;
  
  Systemoutprintln (str);
  textAreaappendText (str + \n);
  }
  
  inputclose ();
  經過許可服務器返回魔力鍵作為第一行魔力鍵是一段狀態信息此信息用來唯一標識 applet 所涉及的與此服務器有關的事務 如果在處理 POST 請求的過程中遇到任何問題服務器通過以下方式將這一情況通知 applet返回 nil 字符串並緊接著返回這一問題的文本描述applet 現在所要做的唯一操作就是構建 URL並調用 showDocument() 來顯示 HTMLif (null != firstLine)
  {
  url = new URL (// +
  ((getCodeBase())getHost())toString() +
  /poster? + firstLine);
  (getAppletContext())showDocument (url _blank);
  }
  一定要注意URL 參數必須是 URL 編碼的在上面的代碼段中因為來自服務器的魔力鍵已被安全編碼所以我們只需添加問號將基准 URL 與所傳遞的參數分隔開
  
  現在我們已討論了 applet 部分下面該研究服務器了在以前有關 POST 的一篇 Java 技巧中服務器端的代碼是用 Perl 編寫的傳統 CGIbin 腳本Perl 是一種不錯的解決方案但是您難道不想用 Java 編寫服務器端的代碼嗎?我們可以用 Java 編寫 CGIbin 腳本(請參閱參考資源部分)但還有更好的解決辦法那就是作為 Web 服務器本身一部分的 Java這種服務器端的 Java 稱為 servlet本文所提供的解決方案將是一個 servlet是按照 Java Servlet API 編寫的 盡管通過 CGIbin 腳本(用 PerlTclJava 或其他語言編寫)也能實現同樣的解決方案
  
  請注意對 servlet 編程和管理的介紹不屬於本文的討論范圍我們僅討論與 POST 解決方案有直接關系的主要問題
  
  PosterServlet 代碼包含大量的注釋以便指導您閱讀代碼代碼包含大量的錯誤處理和額外檢查用來處理過多的可能出現的問題拒絕服務攻擊等但是多數時候您可以忽略這些代碼(稍後我會更深入地討論安全性問題)這個 servlet 是針對 Java x API 編寫的(而 applet 代碼是針對 Java 編寫的)
  
  doPost() 方法處理 POST 請求 doPost() 負責前三種服務器職責它根據通過 POST 發送來信息生成 HTML 文檔然後將文檔保存到一個臨時的磁盤文件中並將魔力鍵返回給 applet魔力鍵用來標識 HTML 文檔並適合直接嵌入隨後的 GET 請求中
  
  下面是代碼的核心部分(要查看完整的代碼請參閱實際的源文件)實現說明魔力鍵實際上是為此事務生成的 HTML 文檔的文件名 文件名是使用 javautilRandom 類生成的一個 Long 值 protected void doPost (HttpServletRequest request
  HttpServletResponse response)
  throws ServletException IOException
  {
  responsesetContentType (text/plain);
  
  // 構建輸出文件名
  String fileName = (new Long (randomizernextLong()))toString();
  File file = null;
  try
  {
  file = new File (posterTempDir + Fileseparator +
  fileName + posterTempExt);
  }
  catch (Exception e)
  {
  sendPostFailure (response
  Unable to build output file path!);
  return;
  }
  
  // 打開輸出文件
  PrintWriter output = null;
  try
  {
  output = new PrintWriter
  ( new BufferedWriter
  ( new FileWriter (file)));
  }
  catch (IOException e)
  {
  sendPostFailure (response Unable to open output file!);
  return;
  }
  
  outputprintln (< html>);
  outputprint (< head>< title>Poster Servlet Generated Output);
  outputprintln (< /title>< /head>);
  outputprintln (< body>);
  
  
  // 現在循環檢查請求標頭並將它們寫入文件中
  String headerName = null;
  Enumeration headers = requestgetHeaderNames();
  if (headershasMoreElements())
  {
  outputprintln (< h>CGI headers:< /h>< hr>);
  outputprintln (< ul>);
  while (headershasMoreElements())
  {
  headerName = (String) headersnextElement();
  outputprint (< li>< b>);
  outputprint (headerName);
  outputprint ( = );
  outputprint (requestgetHeader (headerName));
  outputprintln (< /b>< /li>< br>);
  }
  outputprintln (< /ul>< hr>< br>);
  }
  
  // 處理 POST 內容
  if ( < requestgetContentLength())
  {
  String line = null;
  
  // 將所有輸入字節轉換為字符
  BufferedReader in = new BufferedReader
  ( new InputStreamReader (requestgetInputStream()));
  
  outputprintln (< h>POST contents:< h>< hr>);
  outputprintln (< p>< pre>);
  
  
  // 讀取輸入的每一行並將其寫入輸出文件中
  HttpUtils httpUtils = new HttpUtils();
  try
  {
  while (null != (line = inreadLine()))
  {
  try
  {
  Hashtable data = (line);
  String keyName = null;
  Enumeration keys = datakeys();
  
  while (keyshasMoreElements())
  {
  String[] values = null;
  
  keyName = (String) keysnextElement();
  outputprint (keyName);
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19385.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.