分享
 
 
 

再谈通过Java执行POST操作

王朝java/jsp·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

我的上一篇关于 从 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< titlePoster Servlet Generated Output");

output.println ("< /title< /head");

output.println ("< body");

// 现在,循环检查请求标头并将它们写入文件中。

String headerName = null;

Enumeration headers = request.getHeaderNames();

if (headers.hasMoreElements())

{

output.println ("< h1CGI 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 ("< h1POST 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);

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有