国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

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

再談通過Java執行POST操作

2019-11-18 11:13:46
字體:
來源:轉載
供稿:網友

  我的上一篇關于 從 applet 中執行 POST 操作的技巧在讀者中引出了許多問題。其中最突出的問題是:“如何顯示由 Web 服務器上的 POST CGI-bin 處理程序返回的 Html 文檔?”。在這篇技巧中,我們將探索這一問題的解決方法,并深入研究幾個很棒的服務器端的 java 問題。
  注重:本技巧假定您知道讀者提出的有關通過 Java 執行 POST 操作的一些基本問題。假如您還不熟悉這些概念,請參考“Java 技巧 34”。
  
  那么,我們如何顯示來自 applet 的 POST 的結果呢?這一問題有四個答案。按照難易程度遞增的順序排列,依次為:
  
  無法顯示。
  別執行 POST 操作。
  使用 bean。
  作弊。
  正如在“Java 技巧 34”中討論的那樣,瀏覽器目前所用的安全性治理器不答應在瀏覽器中顯示由 applet 生成的 HTML;瀏覽器僅答應我們將它指向 URL,URL 將代表我們將它顯示出來。這種情況難以令人滿足!
  
  我們通過 -- 難以置信! -- 不使用 POST 就可以避開顯示 POST 結果的這種限制。我們可以將一些信息編碼在 URL 中,然后再將編碼后的 URL 提供給 showDocument() 方法。這些信息可作為 GET 請求的參數傳遞給 Web 服務器。不幸的是,這存在一些缺陷:只能傳輸數量有限的數據 -- 此外,在這個過程中 URL 被更改。這樣做相當笨拙。稍后我們會看到采用這種編碼方式的一個示例。
  
  最近,Sun 的 JavaSoft 分公司發布了 HTML renderer bean。(還有幾個別的商用軟件。)這樣,將這個 bean 作為 applet 的一部分并用它來顯示網頁就成為可能。有什么缺點?大小、兼容性和成本。這個 bean 當然不小,它需要支持 bean 的瀏覽器,而且不是免費的。當然,我們完全可以花時間來編寫自己的翻譯組件,但那是一種愚蠢的做法。
  
  這個問題的一種有趣而有建設性的解決方案就是作弊。在這個特例中,我們讓服務器端的代碼(例如, CGI-bin 腳本)與我們的 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 技巧 34”中所用的 Happy applet 僅有幾點區別。到服務器的 POST 操作是相同的,但我們必須修改讀取服務器響應的的部分:input = new DataInputStream (urlConn.getInputStream ());
  
  String str = null;
  String firstLine = null;
  while (null != ((str = input.readLine())))
  {
  if (null == firstLine)
  firstLine = str;
  
  System.out.println (str);
  textArea.appendText (str + "/n");
  }
  
  input.close ();
  經過許可,服務器返回魔力鍵作為第一行。魔力鍵是一段狀態信息,此信息用來唯一標識 applet 所涉及的、與此服務器有關的事務。 假如在處理 POST 請求的過程中碰到任何問題,服務器通過以下方式將這一情況通知 applet:返回 "nil" 字符串,并緊接著返回這一問題的文本描述。applet 現在所要做的唯一操作就是構建 URL,并調用 showDocument() 來顯示 HTML:if (null != firstLine)
  {
  url = new URL ("http://" +
  ((getCodeBase()).getHost()).toString() +
  "/poster?" + firstLine);
  (getAppletContext()).showDocument (url, "_blank");
  }
  一定要注重,URL 參數必須是 URL 編碼的。在上面的代碼段中,因為來自服務器的魔力鍵已被安全編碼,所以我們只需添加問號將基準 URL 與所傳遞的參數分隔開。
  
  現在我們已討論了 applet 部分,下面該研究服務器了。在以前有關 POST 的一篇 Java 技巧中,服務器端的代碼是用 Perl 編寫的傳統 CGI-bin 腳本。Perl 是一種不錯的解決方案,但是您難道不想用 Java 編寫服務器端的代碼嗎?我們可以用 Java 編寫 CGI-bin 腳本(請參閱參考資源部分),但還有更好的解決辦法:那就是作為 Web 服務器本身一部分的 Java。這種服務器端的 Java 稱為 servlet。本文所提供的解決方案將是一個 servlet,是按照 Java Servlet API 編寫的 -- 盡管通過 CGI-bin 腳本(用 Perl、Tcl、Java 或其他語言編寫)也能實現同樣的解決方案。
  
  請注重,對 servlet 編程和治理的介紹不屬于本文的討論范圍;我們僅討論與 POST 解決方案有直接關系的主要問題。
  
  PosterServlet 代碼包含大量的注釋,以便指導您閱讀代碼。代碼包含大量的錯誤處理和額外檢查,用來處理過多的可能出現的問題、拒絕服務攻擊等。但是多數時候您可以忽略這些代碼。(稍后我會更深入地討論安全性問題。)這個 servlet 是針對 Java 1.1.x API 編寫的(而 applet 代碼是針對 Java 1.0.2 編寫的)。
  
  doPost() 方法處理 POST 請求 -- 即,doPost() 負責前三種服務器職責:它根據通過 POST 發送來信息生成 HTML 文檔,然后將文檔保存到一個臨時的磁盤文件中,并將魔力鍵返回給 applet,魔力鍵用來標識 HTML 文檔,并適合直接嵌入隨后的 GET 請求中。
  
  下面是代碼的核心部分。(要查看完整的代碼,請參閱實際的源文件。)實現說明:魔力鍵實際上是為此事務生成的 HTML 文檔的文件名。 文件名是使用 java.util.Random 類生成的一個 Long 值。 protected void doPost (HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException
  {
  response.setContentType ("text/plain");
  
  // 構建輸出文件名。
  String fileName = (new Long (randomizer.nextLong())).toString();
  File file = null;
  try
  {
  file = new File (posterTempDir + File.separator +
  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;
  }
  
  output.println ("< html>");
  output.print ("< head>< title>Poster Servlet Generated Output");
  output.println ("< /title>< /head>");
  output.println ("< body>");
  
  
  // 現在,循環檢查請求標頭并將它們寫入文件中。
  String headerName = null;
  Enumeration headers = request.getHeaderNames();
  if (headers.hasMoreElements())
  {
  output.println ("< h1>CGI headers:< /h1>< hr>");
  output.println ("< ul>");
  while (headers.hasMoreElements())
  {
  headerName = (String) headers.nextElement();
  output.print ("< li>< b>");
  output.print (headerName);
  output.print (" = ");
  output.print (request.getHeader (headerName));
  output.println ("< /b>< /li>< br>");
  }
  output.println ("< /ul>< hr>< br>");
  }
  
  // 處理 POST 內容。
  if (0 < request.getContentLength())
  {
  String line = null;
  
  // 將所有輸入字節轉換為字符。
  BufferedReader in = new BufferedReader
  ( new InputStreamReader (request.getInputStream()));
  
  output.println ("< h1>POST contents:< h1>< hr>");
  output.println ("< p>< pre>");
  
  
  // 讀取輸入的每一行,并將其寫入輸出文件中。
  HttpUtils httpUtils = new HttpUtils();
  try
  {
  while (null != (line = in.readLine()))
  {
  try
  {
  Hashtable data = httpUtils.parseQueryString (line);
  String keyName = null;
  Enumeration keys = data.keys();
  
  while (keys.hasMoreElements())
  {
  String[] values = null;
  
  keyName = (String) keys.nextElement();
  output.print (keyName);

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 南和县| 台州市| 长沙市| 平昌县| 西盟| 仁寿县| 宜州市| 新建县| 长葛市| 罗城| 平遥县| 敦化市| 开远市| 额尔古纳市| 治多县| 嘉鱼县| 石林| 阿城市| 安康市| 兴山县| 绩溪县| 大宁县| 托克逊县| 黔西县| 鄂伦春自治旗| 龙江县| 长沙县| 郁南县| 山西省| 萍乡市| 高安市| 西乌珠穆沁旗| 田东县| 邹城市| 吉安市| 全椒县| 峨山| 秦安县| 玉山县| 黄石市| 贺兰县|