﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-FreeZone-随笔分类-JavaScript资料集</title><link>http://www.blogjava.net/sunbaoyu/category/4318.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 03 Mar 2007 04:41:25 GMT</lastBuildDate><pubDate>Sat, 03 Mar 2007 04:41:25 GMT</pubDate><ttl>60</ttl><item><title>Ajax: 构建动态的 Java 应用程序</title><link>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17436.html</link><dc:creator>bluesky</dc:creator><author>bluesky</author><pubDate>Sun, 30 Oct 2005 07:36:00 GMT</pubDate><guid>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17436.html</guid><wfw:comment>http://www.blogjava.net/sunbaoyu/comments/17436.html</wfw:comment><comments>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sunbaoyu/comments/commentRss/17436.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sunbaoyu/services/trackbacks/17436.html</trackback:ping><description><![CDATA[<blockquote>在 Web 应用程序开发中，页面重载循环是最大的一个使用障碍，对于 Java™
开发人员来说也是一个严峻的挑战。在这个系列中，作者 Philip McCarthy 介绍了一种创建动态应用程序体验的开创性方式。Ajax（异步
JavaScript 和 XML）是一种编程技术，它允许为基于 Java 的 Web 应用程序把 Java 技术、XML 和
JavaScript 组合起来，从而打破页面重载的范式。</blockquote>
<p>Ajax（即异步 JavaScript 和
XML）是一种 Web 应用程序开发的手段，它采用客户端脚本与 Web
服务器交换数据。所以，不必采用会中断交互的完整页面刷新，就可以动态地更新 Web 页面。使用 Ajax，可以创建更加丰富、更加动态的 Web
应用程序用户界面，其即时性与可用性甚至能够接近本机桌面应用程序。</p>
<p>Ajax 不是一项技术，而更像是一个 <i>模式</i> ——
一种识别和描述有用的设计技术的方式。Ajax 是新颖的，因为许多开发人员才刚刚开始知道它，但是所有实现 Ajax
应用程序的组件都已经存在若干年了。它目前受到重视是因为在 2004 和 2005 年出现了一些基于 Ajax 技术的非常棒的动态 Web
UI，最著名的就是 Google 的 GMail 和 Maps 应用程序，以及照片共享站点
Flickr。这些用户界面具有足够的开创性，有些开发人员称之为“Web 2.0”，因此对 Ajax 应用程序的兴趣飞速上升。</p>
<p>在这个
系列中，将提供使用 Ajax 开发应用程序需要的全部工具 。在第一篇文章中，将解释 Ajax 背后的概念，演示为基于 Java 的 Web
应用程序创建 Ajax 界面的基本步骤。我将使用代码示例演示让 Ajax 应用程序如此动态的服务器端 Java 代码和客户端
JavaScript。最后，将指出 Ajax 方式的一些不足，以及在创建 Ajax 应用程序时应当考虑的一些更广的可用性和访问性问题。</p>
<p><a name="IDA1CAKB"><span class="atitle">更好的购物车</span></a></p>
<p>可
以用 Ajax 增强传统的 Web
应用程序，通过消除页面装入从而简化交互。为了演示这一点，采用一个简单的购物车示例，在向里面添加项目时，它会动态更新。这项技术如果整合到在线商
店，那么用户可以持续地浏览和向购物车中添加项目，而不必在每次点击之后都等候完整的页面更新。虽然这篇文章中的有些代码特定于购物车示例，但是演示的技
术可以应用于任何 Ajax 应用程序。清单 1 显示了购物车示例使用的有关 HTML 代码，整篇文章中都会使用这个 HTML。</p>
<br>
<a name="Listing 1"><b>清单1. 购物车示例的有关片断</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>&lt;!-- Table of products from store's catalog, one row per item --&gt;<br>&lt;th&gt;Name&lt;/th&gt; &lt;th&gt;Description&lt;/th&gt; &lt;th&gt;Price&lt;/th&gt; &lt;th&gt;&lt;/th&gt;<br>...<br>&lt;tr&gt;<br>  &lt;!-- Item details --&gt;<br>  &lt;td&gt;Hat&lt;/td&gt; &lt;td&gt;Stylish bowler hat&lt;/td&gt; &lt;td&gt;$19.99&lt;/td&gt;<br>  &lt;td&gt;<br>    &lt;!-- Click button to add item to cart via Ajax request --&gt;<br>    &lt;button onclick="addToCart('hat001')"&gt;Add to Cart&lt;/button&gt;<br>  &lt;/td&gt;<br>&lt;/tr&gt;<br>...<br><br>&lt;!-- Representation of shopping cart, updated asynchronously --&gt;<br>&lt;ul id="cart-contents"&gt;<br><br>  &lt;!-- List-items will be added here for each item in the cart --&gt;<br>  <br>&lt;/ul&gt;<br><br>&lt;!-- Total cost of items in cart displayed inside span element --&gt;<br>Total cost: &lt;span id="total"&gt;$0.00&lt;/span&gt;<br></code></pre></td></tr></tbody>
</table>
<br>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAJDAKB"><span class="atitle">Ajax 往返过程</span></a></p>
<p>Ajax 交互开始于叫作 <code>XMLHttpRequest</code> 的 JavaScript 对象。顾名思义，它允许客户端脚本执行 HTTP 请求，并解析 XML 服务器响应。Ajax 往返过程的第一步是创建 <code>XMLHttpRequest</code> 的实例。在 <code>XMLHttpRequest</code> 对象上设置请求使用的 HTTP 方法（<code>GET</code> 或 <code>POST</code>）以及目标 URL。</p>
<p>现在，您还记得 Ajax 的第一个 <i>a</i> 是代表 <i>异步（asynchronous）</i> 吗？在发送 HTTP 请求时，不想让浏览器挂着等候服务器响应。相反，您想让浏览器继续对用户与页面的交互进行响应，并在服务器响应到达时再进行处理。为了实现这个要求，可以在 <code>XMLHttpRequest</code> 上注册一个回调函数，然后异步地分派 <code>XMLHttpRequest</code>。然后控制就会返回浏览器，当服务器响应到达时，会调用回调函数。</p>
<p>在 Java Web 服务器上，请求同其他 <code>HttpServletRequest</code> 一样到达。在解析了请求参数之后，servlet 调用必要的应用程序逻辑，把响应序列化成 XML，并把 XML 写入 <code>HttpServletResponse</code>。</p>
<p>回到客户端时，现在调用注册在 <code>XMLHttpRequest</code> 上的回调函数，处理服务器返回的 XML 文档。最后，根据服务器返回的数据，用 JavaScript 操纵页面的 HTML DOM，把用户界面更新。图 1 是 Ajax 往返过程的顺序图。</p>
<br>
<a name="figure1"><b>图 1. Ajax 往返过程</b></a><br>
<img alt=" Ajax 往返过程的顺序图" src="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/ajax.gif" height="630" width="566"><br>
<p>现在您对 Ajax 往返过程有了一个高层面的认识。下面我将放大其中的每一步骤，进行更详细的观察。如果过程中迷了路，请回头看图 1 —— 由于 Ajax 方式的异步性质，所以顺序并非十分简单。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAQFAKB"><span class="atitle">分派 XMLHttpRequest</span></a></p>
<p>我将从 Ajax 序列的起点开始：创建和分派来自浏览器的 <code>XMLHttpRequest</code>。不幸的是，不同的浏览器创建 <code>XMLHttpRequest</code> 的方法各不相同。清单 2 的 JavaScript 函数消除了这些依赖于浏览器的技巧，它可以检测当前浏览器要使用的正确方式，并返回一个可以使用的 <code>XMLHttpRequest</code>。最好是把它当作辅助代码：只要把它拷贝到 JavaScript 库，并在需要 <code>XMLHttpRequest</code> 的时候使用它就可以了。</p>
<br>
<a name="listing2"><b>清单 2. 创建跨浏览器的 XMLHttpRequest</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>/*<br> * Returns a new XMLHttpRequest object, or false if this browser<br> * doesn't support it<br> */<br>function newXMLHttpRequest() {<br><br>  var xmlreq = false;<br><br>  if (window.XMLHttpRequest) {<br><br>    // Create XMLHttpRequest object in non-Microsoft browsers<br>    xmlreq = new XMLHttpRequest();<br><br>  } else if (window.ActiveXObject) {<br><br>    // Create XMLHttpRequest via MS ActiveX<br>    try {<br>      // Try to create XMLHttpRequest in later versions<br>      // of Internet Explorer<br><br>      xmlreq = new ActiveXObject("Msxml2.XMLHTTP");<br><br>    } catch (e1) {<br><br>      // Failed to create required ActiveXObject<br><br>      try {<br>        // Try version supported by older versions<br>        // of Internet Explorer<br><br>        xmlreq = new ActiveXObject("Microsoft.XMLHTTP");<br><br>      } catch (e2) {<br><br>        // Unable to create an XMLHttpRequest with ActiveX<br>      }<br>    }<br>  }<br><br>  return xmlreq;<br>}<br>  </code></pre></td></tr></tbody>
</table>
<br>
<p>稍后将讨论处理那些不支持 <code>XMLHttpRequest</code> 的浏览器的技术。目前，示例假设清单 2 的 <code>newXMLHttpRequest</code> 函数总能返回 <code>XMLHttpRequest</code> 实例。</p>
<p>返回示例的购物车场景，想要当用户在目录项目上点击 Add to Cart 时启动 Ajax 交互。名为 <code>addToCart()</code> 的 <code>onclick</code> 处理函数负责通过 Ajax 调用来更新购物车的状态（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#listing1">清单 1</a>）。正如清单 3 所示，<code>addToCart()</code> 需要做的第一件事是通过调用清单 2 的 <code>newXMLHttpRequest()</code> 函数得到 <code>XMLHttpRequest</code> 对象。接下来，它注册一个回调函数，用来接收服务器响应（我稍后再详细解释这一步；请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#listing6">清单 6</a>）。</p>
<p>因为请求会修改服务器上的状态，所以将用 HTTP <code>POST</code> 做这个工作。通过 <code>POST</code> 发送数据要求三个步骤。第一，需要打开与要通信的服务器资源的 <code>POST</code> 连接 —— 在这个示例中，服务器资源是一个映射到 URL <code>cart.do</code> 的 servlet。然后，我在 <code>XMLHttpRequest</code> 上设置一个头，指明请求的内容是表单 编码的数据。最后，用表单编码的数据作为请求体发送请求。</p>
<p>清单 3 把这些步骤放在了一起。</p>
<br>
<a name="listing3"><b>清单 3. 分派 Add to Cart XMLHttpRequest</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>/*<br> * Adds an item, identified by its product code, to the shopping cart<br> * itemCode - product code of the item to add.<br> */<br>function addToCart(itemCode) {<br><br>  // Obtain an XMLHttpRequest instance<br>  var req = newXMLHttpRequest();<br><br>  // Set the handler function to receive callback notifications<br>  // from the request object<br>  var handlerFunction = getReadyStateHandler(req, updateCart);<br>  req.onreadystatechange = handlerFunction;<br>  <br>  // Open an HTTP POST connection to the shopping cart servlet.<br>  // Third parameter specifies request is asynchronous.<br>  req.open("POST", "cart.do", true);<br><br>  // Specify that the body of the request contains form data<br>  req.setRequestHeader("Content-Type", <br>                       "application/x-www-form-urlencoded");<br><br>  // Send form encoded data stating that I want to add the <br>  // specified item to the cart.<br>  req.send("action=add&amp;item="+itemCode);<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<p>这就是建立 Ajax 往返过程的第一部分，即创建和分派来自客户机的 HTTP 请求。接下来是用来处理请求的 Java servlet 代码。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDA4AKKB"><span class="atitle">servlet 请求处理</span></a></p>
<p>用 servlet 处理 <code>XMLHttpRequest</code>，与处理普通的浏览器 HTTP 请求一样。可以用 <code>HttpServletRequest.getParameter()</code> 得到在 POST 请求体中发送的表单编码数据。Ajax 请求被放进与来自应用程序的常规 Web 请求一样的 <code>HttpSession</code> 中。对于示例购物车场景来说，这很有用，因为这可以把购物车状态封装在 JavaBean 中，并在请求之间在会话中维持这个状态。</p>
<p>清单 4 是处理 Ajax 请求、更新购物车的简单 servlet 的一部分。<code>Cart</code> bean 是从用户会话中获得的，并根据请求参数更新它的状态。然后 <code>Cart</code> 被序列化成 XML，XML 又被写入 <code>ServletResponse</code>。重要的是把响应的内容类型设置为 <code>application/xml</code>，否则 <code>XMLHttpRequest</code> 不会把响应内容解析成 XML DOM。</p>
<br>
<a name="listing4"><b>清单 4. 处理 Ajax 请求的 servlet 代码</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>public void doPost(HttpServletRequest req, HttpServletResponse res)<br>                        throws java.io.IOException {<br><br>  Cart cart = getCartFromSession(req);<br><br>  String action = req.getParameter("action");<br>  String item = req.getParameter("item");<br>  <br>  if ((action != null)&amp;&amp;(item != null)) {<br><br>    // Add or remove items from the Cart<br>    if ("add".equals(action)) {<br>      cart.addItem(item);<br><br>    } else if ("remove".equals(action)) {<br>      cart.removeItems(item);<br><br>    }<br>  }<br><br>  // Serialize the Cart's state to XML<br>  String cartXml = cart.toXml();<br><br>  // Write XML to response.<br>  res.setContentType("application/xml");<br>  res.getWriter().write(cartXml);<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<p>清单 5 显示了 <code>Cart.toXml()</code> 方法生成的示例 XML。它很简单。请注意 <code>cart</code> 元素的 <code>generated</code> 属性，它是 <code>System.currentTimeMillis()</code> 生成的一个时间戳。</p>
<br>
<a name="listing5"><b>清单 5. Cart 对象的XML 序列化示例 </b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>&lt;?xml version="1.0"?&gt;<br>&lt;cart generated="1123969988414" total="$171.95"&gt;<br>  &lt;item code="hat001"&gt;<br>    &lt;name&gt;Hat&lt;/name&gt;<br>    &lt;quantity&gt;2&lt;/quantity&gt;<br>  &lt;/item&gt;<br>  &lt;item code="cha001"&gt;<br>    &lt;name&gt;Chair&lt;/name&gt;<br>    &lt;quantity&gt;1&lt;/quantity&gt;<br>  &lt;/item&gt;<br>  &lt;item code="dog001"&gt;<br>    &lt;name&gt;Dog&lt;/name&gt;<br>    &lt;quantity&gt;1&lt;/quantity&gt;<br>  &lt;/item&gt;<br>&lt;/cart&gt;<br></code></pre></td></tr></tbody>
</table>
<br>
<p>如果查看应用程序源代码（可以从 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#download">下载</a> 一节得到）中的 Cart.java，可以看到生成 XML 的方式只是把字符串添加在一起。虽然对这个示例来说足够了，但是对于从 Java 代码生成 XML 来说则是最差的方式。这个系列的下一期中介绍一些更好的方式。</p>
<p>现在您已经知道了 <code>CartServlet</code> 响应 <code>XMLHttpRequest</code> 的方式。下一件事就是返回客户端，查看如何用 XML 响应更新页面状态。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAZDKKB"><span class="atitle">用 JavaScript 进行响应处理</span></a></p>
<p><code>XMLHttpRequest</code> 的 <code>readyState</code> 属性是一个数值，它指出请求生命周期的状态。它从 0（代表“未初始化”）变化到 4（代表“完成”）。每次 <code>readyState</code> 变化时，<code>readystatechange</code> 事件就触发，由 <code>onreadystatechange</code> 属性指定的事件处理函数就被调用。</p>
<p>在 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#listing3">清单 3</a> 中已经看到了如何调用 <code>getReadyStateHandler()</code> 函数创建事件处理函数。然后把这个事件处理函数分配给 <code>onreadystatechange</code> 属性。<code>getReadyStateHandler()</code> 利用了这样一个事实：函数是 JavaScript 中的一级对象。这意味着函数可以是其他函数的参数，也可以创建和返回其他函数。<code>getReadyStateHandler()</code> 的工作是返回一个函数，检查 <code>XMLHttpRequest</code> 是否已经完成，并把 XML 响应传递给调用者指定的事件处理函数。清单 6 是 <code>getReadyStateHandler()</code> 的代码。</p>
<br>
<a name="listing6"><b>清单 6.  getReadyStateHandler() 函数</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>/*<br> * Returns a function that waits for the specified XMLHttpRequest<br> * to complete, then passes its XML response to the given handler function.<br> * req - The XMLHttpRequest whose state is changing<br> * responseXmlHandler - Function to pass the XML response to<br> */<br>function getReadyStateHandler(req, responseXmlHandler) {<br><br>  // Return an anonymous function that listens to the <br>  // XMLHttpRequest instance<br>  return function () {<br><br>    // If the request's status is "complete"<br>    if (req.readyState == 4) {<br>      <br>      // Check that a successful server response was received<br>      if (req.status == 200) {<br><br>        // Pass the XML payload of the response to the <br>        // handler function<br>        responseXmlHandler(req.responseXML);<br><br>      } else {<br><br>        // An HTTP problem has occurred<br>        alert("HTTP error: "+req.status);<br>      }<br>    }<br>  }<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<table align="right" border="0" cellpadding="0" cellspacing="0" width="40%">
<tbody><tr><td width="10"><img src="http://www.ibm.com/i/c.gif" alt="" height="1" width="10"></td><td><table border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td bgcolor="#eeeeee"><a name="IDA2FKKB"><b>HTTP 状态码</b></a><br><p>在清单 6 中，检查 <code>XMLHttpRequest</code> 的  <code>status</code> 属性以查看请求是否成功完成。<code>status</code> 包含服务器响应的 HTTP 状态码。在执行简单的 <code>GET</code> 和 <code>POST</code> 请求时，可以假设任何大于 200 （OK）的码都是错误。如果服务器发送重定向响应（例如 301 或 302），浏览器会透明地进行重定向并从新的位置获取资源；<code>XMLHttpRequest</code> 看不到重定向状态码。而且，浏览器会自动添加 <code>Cache-Control: no-cache</code> 头到所有 <code>XMLHttpRequest</code>，这样客户代码永远也不用处理 304（未经修改）服务器响应。</p></td></tr></tbody></table></td></tr></tbody>
</table>
<p><a name="IDACHKKB"><span class="smalltitle">关于 getReadyStateHandler()</span></a></p>
<p><code>getReadyStateHandler()</code> 是段相对复杂的代码，特别是如果您不习惯阅读 JavaScript 的话。但是通过把这个函数放在 JavaScript 库中，就可以处理 Ajax 服务器响应，而不必处理 <code>XMLHttpRequest</code> 的内部细节。重要的是要理解如何在自己的代码中使用 <code>getReadyStateHandler()</code>。</p>
<p>在 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#listing3">清单 3</a> 中看到了 <code>getReadyStateHandler()</code> 像这样被调用：<code>handlerFunction = getReadyStateHandler(req,
updateCart)</code>。在这个示例中，<code>getReadyStateHandler()</code> 返回的函数将检查在 <code>req</code> 变量中的 <code>XMLHttpRequest</code> 是否已经完成，然后用响应的 XML 调用名为 <code>updateCart</code> 的函数。</p>
<p><a name="IDAVIKKB"><span class="smalltitle">提取购物车数据</span></a></p>
<p>清单 7 是 <code>updateCart()</code> 本身的代码。函数用 DOM 调用检查购物车的 XML 文档，然后更新 Web 页面（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#listing1">清单 1</a>），反映新的购物车内容。这里的重点是用来从 XML DOM 提取数据的调用。<code>cart</code> 元素的 <code>generated</code>  属性是在 <code>Cart</code> 序列化为 XML 时生成的一个时间戳，检查它可以保证新的购物车数据不会被旧的数据覆盖。Ajax 请求天生是异步的，所以这个检查可以处理服务器响应未按次序到达的情况。</p>
<br>
<a name="listing7"><b>清单 7. 更新页面，反映购物车的 XML 文档</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>function updateCart(cartXML) {<br><br> // Get the root "cart" element from the document<br> var cart = cartXML.getElementsByTagName("cart")[0];<br><br> // Check that a more recent cart document hasn't been processed<br> // already<br> var generated = cart.getAttribute("generated");<br> if (generated &gt; lastCartUpdate) {<br>   lastCartUpdate = generated;<br><br>   // Clear the HTML list used to display the cart contents<br>   var contents = document.getElementById("cart-contents");<br>   contents.innerHTML = "";<br><br>   // Loop over the items in the cart<br>   var items = cart.getElementsByTagName("item");<br>   for (var I = 0 ; I &lt; items.length ; I++) {<br><br>     var item = items[I];<br><br>     // Extract the text nodes from the name and quantity elements<br>     var name = item.getElementsByTagName("name")[0]<br>                                               .firstChild.nodeValue;<br>                                               <br>     var quantity = item.getElementsByTagName("quantity")[0]<br>                                               .firstChild.nodeValue;<br><br>     // Create and add a list item HTML element for this cart item<br>     var li = document.createElement("li");<br>     li.appendChild(document.createTextNode(name+" x "+quantity));<br>     contents.appendChild(li);<br>   }<br> }<br><br> // Update the cart's total using the value from the cart document<br> document.getElementById("total").innerHTML = <br>                                          cart.getAttribute("total");<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<p>到此，整个 Ajax 往返过程完成了，但是您可能想让 Web 应用程序运行一下查看实际效果（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#download">下载</a> 一节）。这个示例非常简单，有很多需要改进之处。例如，我包含了从购物车中清除项目的服务器端代码，但是无法从 UI 访问它。作为一个好的练习，请试着在应用程序现有的 JavaScript 代码之上构建出能够实现这个功能的代码。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDA4JKKB"><span class="atitle">使用 Ajax 的挑战</span></a></p>
<p>就像任何技术一样，使用 Ajax 也有许多出错的可能性。我目前在这里讨论的问题还缺乏容易的解决方案，但是会随着 Ajax 的成熟而改进。随着开发人员社区增加开发 Ajax 应用程序的经验，将会记录下最佳实践和指南。</p>
<p><a name="IDAEKKKB"><span class="smalltitle">XMLHttpRequest 的可用性</span></a></p>
<p>Ajax 开发人员面临的一个最大问题是：在没有 <code>XMLHttpRequest</code> 可用时该如何响应？虽然主要的现代浏览器都支持 <code>XMLHttpRequest</code>，但仍然有少数用户的浏览器不支持，或者浏览器的安全设置阻止使用 <code>XMLHttpRequest</code>。如果开发的 Web 应用程序要部署在企业内部网，那么可能拥有指定支持哪种浏览器的权力，从而可以认为 <code>XMLHttpRequest</code> 总能使用。但是，如果要部署在公共 Web 上，那么就必须当心，如果假设 <code>XMLHttpRequest</code> 可用，那么就可能会阻止那些使用旧的浏览器、残疾人专用浏览器和手持设备上的轻量级浏览器的用户使用您的应用程序。</p>
<p>所以，您应当努力让应用程序“平稳降级”，在没有 <code>XMLHttpRequest</code> 支持的浏览器中也能够工作。在购物车的示例中，把应用程序降级的最好方式可能是让 Add to Cart 按钮执行一个常规的表单提交，刷新页面来反映购物车更新后的状态。Ajax 的行为应当在页面装入的时候就通过 JavaScript 添加到页面，只有在 <code>XMLHttpRequest</code> 可用时才把 JavaScript 事件处理函数附加到每个 Add to Cart 按钮。另一种方式是在用户登录时检测 <code>XMLHttpRequest</code> 是否可用，然后相应地提供应用程序的 Ajax 版本或基于表单的普通版本。</p>
<p><a name="IDANLKKB"><span class="smalltitle">可用性考虑</span></a></p>
<p>关于 Ajax 应用程序的某些可用性问题比较普遍。例如，让用户知道他们的输入已经注册了可能是重要的，因为沙漏光标和 spinning 浏览器的常用反馈机制“throbber”对 <code>XMLHttpRequest</code> 不适用。一种技术是用“Now updating...”类型的信息替换 Submit 按钮，这样用户在等候响应期间就不会反复单击按钮了。</p>
<p>另
一个问题是，用户可能没有注意到他们正在查看的页面的某一部分已经更新了。可以使用不同的可视技术，把用户的眼球带到页面的更新区域，从而缓解这个问题。
由 Ajax 更新页面造成的其他问题还包括：“破坏了”浏览器的后退按钮，地址栏中的 URL 也无法反映页面的整个状态，妨碍了设置书签。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#resources">参考资料</a> 一节，获得专门解决 Ajax 应用程序可用性问题的文章。</p>
<p><a name="IDA4LKKB"><span class="smalltitle">服务器负载</span></a></p>
<p>用
Ajax 实现代替普通的基于表单的 UI，会大大提高对服务器发出的请求数量。例如，一个普通的 Google Web
搜索对服务器只有一个请求，是在用户提交搜索表单时出现的。而 Google Suggest
试图自动完成搜索术语，它要在用户输入时向服务器发送多个请求。在开发 Ajax
应用程序时，要注意将要发送给服务器的请求数量以及由此造成的服务器负荷。降低服务器负载的办法是，在客户机上对请求进行缓冲并且缓存服务器响应（如果可
能的话）。还应该尝试将 Ajax Web 应用程序设计为在客户机上执行尽可能多的逻辑，而不必联络服务器。</p>
<p><a name="IDAEMKKB"><span class="smalltitle">处理异步</span></a></p>
<p>非常重要的是，要理解无法保证 <code>XMLHttpRequest</code> 会按照分派它们的顺序完成。实际上，应当假设它们不会按顺序完成，并且在设计应用程序时把这一点记在心上。在购物车的示例中，使用最后更新的时间戳来确保新的购物车数据不会被旧的数据覆盖（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax1/#listing7">清单 7</a>）。这个非常基本的方式可以用于购物车场景，但是可能不适合其他场景。所以在设计时请考虑如何处理异步的服务器响应。</p>
<img src ="http://www.blogjava.net/sunbaoyu/aggbug/17436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sunbaoyu/" target="_blank">bluesky</a> 2005-10-30 15:36 <a href="http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ajax 的 Java 对象序列化(转贴)</title><link>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17435.html</link><dc:creator>bluesky</dc:creator><author>bluesky</author><pubDate>Sun, 30 Oct 2005 07:32:00 GMT</pubDate><guid>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17435.html</guid><wfw:comment>http://www.blogjava.net/sunbaoyu/comments/17435.html</wfw:comment><comments>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17435.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sunbaoyu/comments/commentRss/17435.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sunbaoyu/services/trackbacks/17435.html</trackback:ping><description><![CDATA[<blockquote>如果您正在使用异步 JavaScript 和 XML（Ajax）进行 Java™ Web 开发，那么您最关心的问题可能就是把数据从服务器传递给客户机。在 <i>面向 Java 开发人员的 Ajax</i> 系列的第二篇文章中，Philip McCarthy 介绍了 Java 对象序列化的五种方式，并提供了选择最适合应用程序的数据格式和技术所需要的全部信息。</blockquote>
<p>在这个系列的 <a HREF="/sunbaoyu/archive/2005/10/30/17436.html">第一篇文章</a> 中，我介绍了 Ajax 的构造块：</p>
<ul>
<li>如何用 JavaScript <code>XMLHttpRequest</code> 对象从 Web 页面向服务器发送异步请求。</li><li>如何用 Java servlet 处理和响应请求（向客户机返回 XML 文档）。</li><li>如何在客户端用响应文档更新页面视图。</li>
</ul>
<p>这一次，将继续讨论 Ajax 开发的基础知识，但是将侧重于许多 Java Web 开发人员最关心的问题：为客户机生成数据。</p>
<p>多
数 Java 开发人员已经把模型-视图-控制器（MVC）模式应用在他们的 Web 应用程序上。在传统的 Web 应用程序中，视图组件由 JSP
或者其他表示技术（例如 Velocity 模板）构成。这些表示组件动态地生成全新的 HTML
页面，替代用户以前正在查看的页面，从而更新用户界面。但是，在 Java Web 应用程序使用 Ajax UI 的情况下，基于从 <code>XMLHttpRequest</code> 的响应接收到的数据，JavaScript 客户端代码对于更新用户看到的内容负有最终责任。从服务器的角度来看，视图成为它响应客户机请求而发送的数据表示。</p>
<p>这
篇文章侧重于可以用来生成 Java 对象以数据为中心的视图的技术。我将演示可以把 JavaBeans 变成 XML
文档的各种方法，并且讨论每种方法的优劣。您将看到为什么 XML 并不总是最好的途径：对于简单的 Ajax
请求来说，传输纯文本更好。最后，我将介绍 JavaScript 对象标注（JSON）。JSON 允许数据以序列化的 JavaScript
对象图的形式传输，在客户端代码中处理序列化的 JavaScript 对象图极为容易。</p>
<p><a name="IDADDKTB"><span class="smalltitle">关于示例</span></a></p>
<p>&nbsp;&nbsp;&nbsp; 使用一个示例应用程序和几个用例来演示这里讨论的技术特性和技术。图 1 显示的极为简单的数据模型可以表示示例用例。这个模型代表在线商店中的顾客帐户。顾客拥有以前订单的集合，每个订单包含几个商品。</p>
<br>
<a name="figure1"><b>图 1. 简单的对象模型</b></a><br>
<img alt="代表顾客帐户的对象模型" src="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/ajaxobjects.jpg" height="133" width="541"><br>
<p>虽然 <code>XMLHttpRequest</code> 对于发送数据使用的格式没有做任何限制，但是对于多数目的来说，只发送传统的表单数据是适合的，所以我的讨论集中在服务器的响应上。响应也可以有基于文本的格式，但是正如它的名字表示的，<code>XMLHttpRequest</code> 具有内置的处理 XML 响应数据的能力。这使 XML 成为 Ajax 响应的默认选择，所以我们从 XML 格式开始讨论。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDA4DKTB"><span class="atitle">从 Java 类产生 XML</span></a></p>
<p>把
Ajax 响应作为 XML 来传递有许多原因：每个支持 Ajax 的浏览器都有导航 XML 文档的方法，也有许多服务器端技术可以处理 XML
数据。通过制定一个方案，描述要交换的文档类型，在 Ajax
客户端和服务器端之间很容易定义合约，而且如果服务器端架构采用面向服务的方式，那么使用 XML 也可以允许非 Ajax 客户机使用您提供的数据。</p>
<p>&nbsp;&nbsp;&nbsp; 我们从 Java 对象产生 XML 数据的三种方法，并讨论每种方法的优劣。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAFEKTB"><span class="atitle">自行进行序列化</span></a></p>
<p>首先，可以从对象图以编程的方式生成 XML。这种方式可以简单到只是在每个 JavaBean 类中实现 <code>toXml()</code>
方法即可。然后就可以选择合适的 XML API，让每个 bean
提供表示自己状态的元素，并递归地对自己的成员调用对象图。显然，这种方式无法扩展到大量的类，因为每个类都需要专门编写自己的 XML
生成代码。从好的方面来看，这是一个实现起来简单的方式，没有额外的配置支出或者更复杂的构建过程支出，任何 JavaBean
图都可以只用几个调用就变成 XML 文档。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.ibm.com/developerworks/cn/java/j-ajax1/">前一篇文章</a> 的示例代码中，把 XML 标记字符串连接在一起，实现了 <code>toXml()</code> 方法。上次我就提到过，这是个糟糕的方法，因为它把确保标记配对、实体编码等工作的负担放在每个 <code>toXml()</code> 方法的代码中。在 Java 平台上有几个 XML API 可以替您做这些工作，这样您就可以把精力集中在 XML 的内容上。清单 1 用 JDOM API 实现了在线商店示例中表示订单的类中的 <code>toXml()</code>（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/#figure1">图 1</a>）。</p>
<br>
<a name="code1"><b>清单 1. Order 类的 toXml() 的 JDOM 实现</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>public Element toXml() {<br><br>  Element elOrder = new Element("order");<br>  elOrder.setAttribute("id",id);<br><br>  elOrder.setAttribute("cost",getFormattedCost());<br><br>  Element elDate = new Element("date").addContent(date);<br>  elOrder.addContent(elDate);<br><br>  Element elItems = new Element("items");<br>  for (Iterator<item> iter = <br>   items.iterator() ; iter.hasNext() ; ) {<br>    elItems.addContent(iter.next().toXml());<br>  }<br>  elOrder.addContent(elItems);<br><br>  return elOrder;<br>}<br></item></code></pre></td></tr></tbody>
</table>
<br>
<p>在这里可以看到用 JDOM 创建元素、使用属性和添加元素内容有多么简单。递归地调用复合 JavaBean 的 <code>toXml()</code> 方法是为了取得它们子图的 <code>Element</code> 表示。例如，<code>items</code> 元素的内容是通过调用 <code>Order</code> 聚合的每个 <code>Item</code> 对象上的 <code>toXml()</code> 得到的。</p>
<p>一旦所有的 JavaBean 都实现了 <code>toXml()</code> 方法，那么把任意对象图序列化成 XML 文档并返回给 Ajax 客户机就简单了，如清单 2 所示。</p>
<br>
<a name="code2"><b>清单 2. 从 JDOM 元素生成 XML 响应</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>public void doGet(HttpServletRequest req, HttpServletResponse res)<br>  throws java.io.IOException, ServletException {<br><br>    String custId = req.getParameter("username");<br>    Customer customer = getCustomer(custId);<br><br>    Element responseElem = customer.toXml();<br>    Document responseDoc = new Document(responseElem);<br><br>    res.setContentType("application/xml");<br>    new XMLOutputter().output(responseDoc,res.getWriter());<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<p>JDOM 再次把工作变得非常简单。只需要在对象图返回的 XML 元素外面包装一个 <code>Document</code>，然后用 <code>XMLOutputter</code> 把文档写入 servlet 响应即可。清单 3 显示了用这种方式生成的 XML 示例，用 JDOM <code>Format.getPrettyFormat()</code> 对 <code>XMLOutputter</code> 进行初始化，格式化得非常好。在这个示例中，顾客只做了一个订单，包含两个商品。</p>
<br>
<a name="code3"><b>清单 3. 代表顾客的 XML 文档</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br><br><customer username="jimmy66"><br>  <realname>James Hyrax</realname><br>  <orders><br>    <order id="o-11123" cost="$349.98"><br>      <date>08-26-2005</date><br>      <items><br>        <item id="i-55768"><br>          <name>Oolong 512MB CF Card</name><br>          <description>512 Megabyte Type 1 CompactFlash card. <br>          Manufactured by Oolong Industries</description><br>          <price>$49.99</price><br>        </item><br>        <item id="i-74491"><br>          <name>Fujak Superpix72 Camera</name><br>          <description>7.2 Megapixel digital camera featuring six <br>          shooting modes and 3x optical zoom. Silver.</description><br>          <price>$299.99</price><br>        </item><br>      </items><br>    </order><br>  </orders><br></customer><br></code></pre></td></tr></tbody>
</table>
<br>
<p><a name="IDANHKTB"><span class="smalltitle">自行序列化的不足</span></a></p>
<p>有趣的是，清单 3 中的代码展示了让 JavaBean 把自己序列化为 XML 的一个主要不足。假设要用这个文档表示顾客的订单历史视图。在这种情况下，不太可能要显示每个历史订单中每个商品的完整说明，或者告诉顾客他或她自己的姓名。但是如果应用程序有一个 <code>ProductSearch</code> 类，它就是以 <code>Item</code> bean 列表的形式返回搜索结果，那么在 <code>Item</code> 的 XML 表示中包含说明可能会有帮助。而且，<code>Item</code> 类上代表当前库存水平的额外字段，在产品搜索视图中可能就是需要显示的有用信息。但是，不管当前的库存水平是否与当前情况相关（比如对顾客的订单历史来说），这个字段都会从包含 <code>Item</code> 的任何对象图中序列化出来。</p>
<p>从
设计的角度来看，这是数据模型与视图生成耦合的经典问题。每个 bean 只能用一种途径序列化自己，一成不变的方式意味着 Ajax
交互最终要交换它们不需要交换的数据，因此造成客户端代码要从文档中找到需要的信息更加困难，而且也会增加带宽消耗和客户端的 XML
解析时间。这种耦合的另一个后果就是 XML 的语法不能脱离 Java 类独立变化。例如，对顾客文档的方案做修改，可能会影响多个 Java
类，造成它们也不得不做修改和重新编译。</p>
<p>稍后会解决这些问题，但是首先来看一个对自行序列化方式的可伸缩性问题的解决方案：XML 绑定框架。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDANA0TB"><span class="atitle">XML 绑定框架</span></a></p>
<p>近
些年来，已经开发了多个 Java API 来简化 XML 文档到 Java 对象图的绑定过程。多数都提供了 XML
编排和拆解；也就是说，它们可以在 Java 对象图和 XML 之间执行双向会话。这些框架封装了 XML
处理的全部工作，这意味着应用程序代码只需要处理普通的 Java
类。它们还希望提供有用的辅助功能，例如文档验证。笼统来说，这些框架采用了两种不同的方式：代码生成和对象到 XML 映射。我将分别解释这两种方式。</p>
<p><a name="IDATA0TB"><span class="smalltitle">代码生成方式</span></a></p>
<p>使
用代码生成的框架包括 XMLBeans、JAXB、Zeus 和 JBind。Castor 也能使用这项技术。这类框架的起点是描述文档数据类型的
XML 方案。使用框架提供的工具，就可以生成代表这些方案定义类型的 Java
类。最后，用这些生成的类编写应用程序，表示自己的模型数据，并通过框架提供的一些辅助机制把数据序列化成 XML。</p>
<p>如果应用程序要使用大
型 XML 语法，那么代码生成方式是个很好的方法。在数十个类上编写定制 XML
序列化代码的可伸缩性问题由此消除。另一方面，也不再需要定义自己的 JavaBean。框架生成的 Java 类通常非常符合 XML
的结构，所以对它们进行编码很难。而且，生成的类变成哑数据容器，因为一般不能向它们添加行为。一般来说，在应用程序代码中要做些妥协，才能很好地处理方
案生成的类型。另一个缺陷是如果修改方案，会造成生成的类也要修改，所以也就会对围绕它们编写的代码带来相应的影响。</p>
<p>这种类型的 XML 绑定框架在数据拆解时最有用（例如，使用 XML 文档并把它们转化成 Java 对象）。除非拥有大型数据模型而且有可能从生成的类中获益，否则基于代码生成的框架对于 Ajax 应用程序来说可能有很大的杀伤力。</p>
<p><a name="IDA1A0TB"><span class="smalltitle">映射方式</span></a></p>
<p>采
用映射方式的框架包括 Castor 和 Apache Commons
Betwixt。映射通常是比代码生成更灵活和更轻量的解决方案。首先，可以像通常一样编写
JavaBean，包括任何行为以及任何自己喜欢的方便的方法。然后，在运行时，调用框架中基于内省的编排器，并根据对象成员的类型、名称和值生成
XML 文档。通过定义类的映射文件，可以覆盖默认的绑定策略，并就类在 XML 中的表示方式对编排器提出建议。</p>
<p>这种方法是在可伸缩性与
灵活性之间的良好折中。可以按照自己喜欢的方式编写 Java 类，编排器负责处理
XML。虽然映射定义文件编写起来简单，可伸缩性也足够好，但是映射规则最多只能改变标准的绑定行为，而且在对象结构和它们的 XML
表示之间总要残留一些耦合。最终，可能不得不在 Java 表示或 XML 格式之间任选一个做些折中，才能让映射方法起作用。</p>
<p><a name="IDACB0TB"><span class="smalltitle">数据绑定总结</span></a></p>
<p>Dennis Sosnoski 就 XML 数据绑定 API 的主题，在代码生成和代码映射两个方面写了深入的文章。如果想进一步研究这个领域，我推荐他在 Castor 和代码生成框架方面的精彩文章（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/#resources">参考资料</a> 中的链接）。</p>
<p>总之，代码生成方式损失了过多的灵活性和方便性，对于典型的 Ajax 应用程序用处不大。另一方面，基于映射的框架可能工作得很好，但是要恰到好处地调整它们的映射策略，以便从对象生成需要的 XML。</p>
<p>所
有的 XML 绑定 API 都具有手工序列化技术的一个主要不足：模型和视图的耦合。被限制为一个类型一个 XML
表示，就意味着在网络上总要有冗余数据传输。更严重的问题是，在情况要求客户端代码使用专门视图时，客户端代码却无法得到它，所以可能要费力地处理给定对
象图的一成不变的视图。</p>
<p>在传统的 Web 应用程序开发中，采用页面模板系统把视图生成与控制器逻辑和模型数据干净地分离。这种方法在 Ajax 场景中也会有帮助。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAQB0TB"><span class="atitle">页面模板系统</span></a></p>
<p>任何通用目的的页面模板技术都可以用来生成 XML，从而使 Ajax 应用程序根据自己的数据模型生成任何 XML 响应文档。额外收获是：模板可以用简单的、表现力强的标记语言编写，而不是用一行行的 Java 代码编写。清单 5 是一个 JSP 页面，采用了 <code>Customer</code> bean 并表示出定制的 XML 视图，适合客户端代码生成订单历史组件。</p>
<br>
<a name="code4"><b>清单 4. 生成订单历史文档的 JSP</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br><br>&lt;%@ page contentType="application/xml" %&gt;<br>&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;<br><c:set var="cust" value="${requestScope.customer}"><br><br><orderhistory username="${cust.username}"><br><c:foreach var="order" items="${cust.orders}"><br>  <order id="${order.id}" cost="${order.formattedCost}"><br>    <date>${order.date}</date><br>    <items><br>    <c:foreach var="item" items="${order.items}"><br>      <item id="${item.id}"><br>        <name><c:out value="${item.name}" escapexml="true"></c:out><br>        <price>${item.formattedPrice}</price><br>      </name><br>    </item><br>    </c:foreach><br>  </items><br></order><br></c:foreach><br></orderhistory></c:set></code></pre></td></tr></tbody>
</table>
<br>
<p>这个简洁的模板只输出订单历史视图需要的数据，不输出不相关的资料（例如商品说明）。创建产品搜索视图的定制 XML 应当同样简单，这个视图包含每个商品的完整说明和库存水平。</p>
<p><a name="IDADC0TB"><span class="smalltitle">模板的问题</span></a></p>
<p>另
一方面，现在我需要为每个不同视图创建一个新
JSP，而不能仅仅把需要的对象图组织起来并序列化它。从设计的角度来说，许多人可能会有争议，认为这无论如何是件好事，因为这意味着正式地考虑服务器要
生成的文档类型。而且，因为我现在要处理通用的模板环境，而不是特定于 XML 的 API，所以确保标记匹配、元素和属性的顺序正确以及 XML
实体（例如 <code>&lt;</code> 或 <code>&amp;</code>）正确转义就成了我的责任。JSP 的核心 <code>out</code> 标记使后面这项工作变得很容易，但是不是所有的模板技术都提供了这样的机制。最后，没有方便的途径可以在服务器端根据方案检验生成的 XML 文档的正确性，但这毕竟不是要在生产环境中做的事，可以方便地在开发期间处理它。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAWC0TB"><span class="atitle">不用 XML 的响应数据</span></a></p>
<p>迄
今为止，我介绍的所有技术都用 XML 文档的形式生成服务器响应。但是，XML 有一些问题。其中一个就是延迟。浏览器不能立即解析 XML
文档并生成 DOM 模型，所以这会降低某些 Ajax
组件需要的“迅捷”感，特别是在较慢的机器上解析大型文档的时候更是如此。“现场搜索”就是一个示例，在这种搜索中，当用户输入搜索术语时，就会从服务器
提取搜索结果并显示给用户。对于现场搜索组件来说，迅速地响应输入是非常重要的，但是同时它还需要迅速而持续地解析服务器的响应。</p>
<p>延迟是一个重要的考虑因素，但是避免使用 XML 的最大原因是差劲的客户端 DOM API。清单 5 显示了使用跨浏览器兼容的方式通过 DOM 得到某个值的时候，通常不得不面对的困难。</p>
<br>
<a name="code5"><b>清单 5. 在 JavaScript 中导航 XML 响应文档</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>// Find name of first item in customer's last order<br>var orderHistoryDoc = req.responseXML;<br><br>var orders = orderHistoryDoc.getElementsByTagName("order");<br>var lastOrder = orders[orders.length - 1];<br><br>var firstItem = lastOrder.getElementsByTagName("item")[0];<br>var itemNameElement = firstItem.firstChild;<br><br>var itemNameText = itemNameElement.firstChild.data;<br></code></pre></td></tr></tbody>
</table>
<br>
<p>当元素中间存在空白时，情况就变得更加复杂，因为每个元素的 <code>firstChild</code> 经常是个空白文本节点。现在有 JavaScript 库可以缓解处理 XML 文档的麻烦。这些库包括 Sarissa （请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/#resources">参考资料</a>）和 Google-ajaXSLT，这两个库都把 XPath 功能添加到了大多数浏览器中。</p>
<p>但是，想想替代方案还是值得的。除了 <code>responseXML</code> 之外，<code>XMLHttpRequest</code> 对象还提供了名为 <code>responseText</code> 的属性，这个属性只是以字符串的方式提供服务器的响应体。</p>
<p><a name="IDA2D0TB"><span class="smalltitle">responseText 属性</span></a></p>
<p>当服务器需要向客户机发送非常简单的值时，<code>responseText</code>
特别方便，它可以避免 XML 导致的带宽支出和处理支出。例如，简单的 true/false
响应可以由服务器以纯文本方式返回，可以是逗号分隔的简单的名称或数字列表。但是，一般来说，最好不要在同一个应用程序中把 XML
响应和纯文本响应混合使用；保持单一数据格式可以让代码抽象和重用更加简单。</p>
<p><code>responseText</code> 与
XML 响应数据结合时也会有用。在只需要从响应文档中提取单一值的场景中，“欺骗性”地把 XML
当作文本字符串，而不把它当作结构化的文档对待，会更方便。例如，清单 6
显示了如何用正则表达式从顾客的订单历史中提取第一笔订单的日期。不过，这实际是种花招，一般不应当依赖 XML 文档的词汇表达。</p>
<br>
<a name="code6"><b>清单 6. 用正则表达式处理 XMLHttpRequest 的 responseText 对象</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>var orderHistoryText = req.responseText;<br>var matches = orderHistoryText.match(/<date>(.*?)&lt;\/date&gt;/);<br><br>var date = matches[1];<br></date></code></pre></td></tr></tbody>
</table>
<br>
<p>在某些情况下，采用即时方式使用 <code>responseText</code> 会比较方便。但是，理想情况下，应当有种途径，可以用一种能够让 JavaScript 轻松导航、却没有 XML 处理支出的格式表示复杂的结构化数据。幸运的是，确实存在这样一种格式。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDAZE0TB"><span class="atitle">JavaScript 对象标注</span></a></p>
<p>实
际上，JavaScript 对象的大部分都由联合数组、数字索引数组、字符串、数字或者这些类型的嵌套组合而成。因为所有类型都可以用
JavaScript 直接声明，所以可以在一条语句中静态地定义对象图。清单 7 使用 JSON
语法声明了一个对象，并演示了如何访问这个对象。大括号表示联合数组（即对象），它的键 -值组合由逗号分隔。方括号表示数字索引数组。</p>
<br>
<a name="code7"><b>清单 7. 用 JSON 在 JavaScript 中直接声明一个简单对象</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>var band = {<br>  name: "The Beatles",<br>  members: [<br>    {<br>      name: "John",<br>      instruments: ["Vocals","Guitar","Piano"]<br>    },<br>    {<br>      name: "Paul",<br>      instruments: ["Vocals","Bass","Piano","Guitar"]<br>    },<br>    {<br>      name: "George",<br>      instruments: ["Guitar","Vocals"]<br>    },<br>    {<br>      name: "Ringo",<br>      instruments: ["Drums","Vocals"]<br>    }<br>  ]<br>};<br><br>// Interrogate the band object<br>var musician = band.members[3];<br>alert( musician.name<br>        + " played " + musician.instruments[0] <br>        + " with " + band.name );<br></code></pre></td></tr></tbody>
</table>
<br>
<p>既然 JSON 是一个有趣的语言特性，那么它对
Ajax 有什么意义呢？妙处在于可以用 JSON 在 Ajax 服务器响应中通过网络发送 JavaScript
对象图。这意味着在客户端可以避免使用笨拙的 DOM API 对 XML 进行导航 —— 只需要分析 JSON 响应，就会立即得到可以访问的
JavaScript 对象图。但是，首先需要把 JavaBean 变成 JSON。</p>
<p><a name="IDAHF0TB"><span class="smalltitle">从 Java 类产生 JSON</span></a></p>
<p>不同 XML 生成技术所具有的优缺点也适用于 JSON 的产生。而且可以证明，存在需要再次使用表示模板技术的情况。但是，使用 JSON 在理念上更接近于在应用层之间传递序列化的对象，而不是创建应用程序状态的视图。我将介绍如何用 <code>org.json</code> 这个 Java API 在 Java 类上创建 <code>toJSONObject()</code> 方法。然后，就可以把 <code>JSONObject</code> 简单地序列化成 JSON。清单 8 反映了 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/#code1">清单 1</a> 讨论的 XML，显示了 <code>Order</code> 类的 <code>toJSONObject()</code> 实现。</p>
<br>
<a name="code8"><b>清单 8. Order 类的 toJSONObject() 方法实现</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>public JSONObject toJSONObject() {<br><br>  JSONObject json = new JSONObject();<br>  json.put("id",id);<br>  json.put("cost",getFormattedCost());<br>  json.put("date",date);<br><br>  JSONArray jsonItems = new JSONArray();<br>  for (Iterator<item> iter = <br>   items.iterator() ; iter.hasNext() ; ) {<br>    jsonItems.put(iter.next().toJSONObject());<br>  }<br>  json.put("items",jsonItems);<br><br>  return json;<br>}<br></item></code></pre></td></tr></tbody>
</table>
<br>
<p>可以看到，<code>org.json</code> API 非常简单。 <code>JSONObject</code> 代表 JavaScript 对象（即联合数组），有不同的 <code>put()</code> 方法，方法接受的 <code>String</code> 键和值是原生类型、<code>String</code> 类型或其他 JSON 类型。<code>JSONArray</code> 代表索引数组，所以它的 <code>put()</code> 方法只接受一个值。请注意在清单 8 中，创建 <code>jsonItems</code> 数组，然后再用 <code>put()</code> 把它附加到 <code>json</code> 对象上；可以用另外一种方法做这项工作，就是对每个项目调用 <code>json.accumulate("items",iter.next().toJSONObject());</code>。<code>accumulate()</code> 方法与 <code>put()</code> 类似，区别在于它把值添加到按照键进行识别的索引数组。</p>
<p>清单 9 显示了如何序列化 <code>JSONObject</code> 并把它写入 servlet 响应。</p>
<br>
<a name="code9"><b>清单 9. 从 JSONObject 生成序列化的 JSON 响应</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>public void doGet(HttpServletRequest req, HttpServletResponse res) <br>  throws java.io.IOException, ServletException {<br><br>	String custId = req.getParameter("username");<br>	Customer customer = getCustomer(custId);<br><br>	res.setContentType("application/x-json");<br>	res.getWriter().print(customer.toJSONObject());<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<p>可以看到，它实际上什么也没有做。在这里隐式调用的 <code>JSONObject</code> 的 <code>toString()</code> 方法做了所有工作。请注意，<code>application/x-json</code> 内容类型还有一点不确定 —— 在编写这篇文章的时候，关于 JSON 应当属于什么 MIME 类型还没有定论。但是，目前 <code>application/x-json</code> 是合理的选择。清单 10 显示了这个 servlet 代码的示例响应。</p>
<br>
<a name="code10"><b>清单 10. Customer bean 的 JSON 表示</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>{<br>  "orders": [<br>    {<br>      "items": [<br>        {<br>          "price": "$49.99",<br>          "description": "512 Megabyte Type 1 CompactFlash card. <br>                              Manufactured by Oolong Industries",<br>          "name": "Oolong 512MB CF Card",<br>          "id": "i-55768"<br>        },<br>        {<br>          "price": "$299.99",<br>          "description": "7.2 Megapixel digital camera featuring six <br>            shooting modes and 3x optical zoom. Silver.",<br>          "name": "Fujak Superpix72 Camera",<br>          "id": "i-74491"<br>        }<br>      ],<br>      "date": "08-26-2005",<br>      "cost": "$349.98",<br>      "id": "o-11123"<br>    }<br>  ],<br>  "realname": "James Hyrax",<br>  "username": "jimmy66"<br>}<br></code></pre></td></tr></tbody>
</table>
<br>
<p><a name="IDAMJ0TB"><span class="smalltitle">在客户端使用 JSON </span></a></p>
<p>处理的最后一步是把在客户端把 JSON 数据变成 JavaScript 对象。这可以通过对 <code>eval()</code> 的简单调用实现，这个函数可以即时地解释包含 JavaScript 表达式的字符串。清单 11 把 JSON 响应转变成 JavaScript 对象图，然后执行清单 5 的任务，从顾客的最后一次订单中得到第一个商品的名称。</p>
<br>
<a name="code11"><b>清单 11. 评估 JSON 响应</b></a><br>
<table bgcolor="#eeeeee" border="1" cellpadding="5" cellspacing="0" width="100%">
<tbody><tr><td><pre><code class="section"><br>var jsonExpression = "(" + req.responseText + ")";<br>var customer = eval(jsonExpression);<br><br>// Find name of first item in customer's last order<br>var lastOrder = customer.orders[customer.orders.length-1];<br>var name = lastOrder.items[0].name;<br></code></pre></td></tr></tbody>
</table>
<br>
<p>比较清单 11 和 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajax2/#code5">清单 5</a> 可以发现使用 JSON 的客户端的优势。如果在 Ajax 项目中要在客户端对许多复杂的服务器响应进行导航，那么 JSON 可能适合您的需要。JSON 和 <code>XMLHttpRequest</code> 结合还会让 Ajax 交互看起来更像 RPC 调用而不是 SOA 请求，这对应用程序的设计可能会有意义。在下一篇文章中，我要研究的框架，就是明确地为了让 JavaScript 代码对服务器端对象进行远程方法调用而设计的。</p>
<p><a name="IDAIK0TB"><span class="smalltitle">JSON 的不足</span></a></p>
<p>JSON 也有它的不足。使用这里介绍的 JSON 方式，就没有办法针对每个请求对对象的序列化进行裁剪，所以不需要的字段可能经常会在网络上发送。另外，添加 <code>toJSONObject()</code>
方法到每个 JavaBean，可伸缩性不太好，虽然用内省和标注编写一个通用的 JavaBean 到 JSON
的序列化器可能很简单。最后，如果服务器端代码是面向服务的，没有单独针对处理 Ajax 客户请求调整过，那么由于对 XML 一致的支持，XML
会是更好的选择。</p>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table style="width: 1px; height: 20px;" class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDATK0TB"><span class="atitle">比较序列化技术</span></a></p>
<p>现
在已经看到了把 Java 状态传输到 Ajax 客户端的五种不同技术。我讨论了自行手工编码 XML 序列化、通过代码生成的 XML
绑定、通过映射机制的 XML 绑定、基于模板的 XML 生成以及手工编码到 JSON
的序列化。每种技术都有自己的优势和不足，分别适用于不同的应用程序架构。
</p>
<p>为了总结每种方式的优势与不足，表 1 从六个方面进行了粗略的评分：</p>
<dl>
<dt><b>可伸缩性</b></dt><dd>描述技术适应大量数据类型的容易程度。对于每个附加类型，编码和配置工作量是否会增长？</dd><dt><b>易于集成</b></dt><dd>评估把技术集成到项目的简单程度。是否需要更加复杂的构建过程？是否增加了部署的复杂性？</dd><dt><b>Java 类 API</b></dt><dd>描述以指定方式处理服务器端 Java 对象的容易程度。是可以编写普通的 bean，还是不得不处理笨拙的文档表示？</dd><dt><b>对输出的控制</b></dt><dd>描述对类的序列化表示控制的精确程度。</dd><dt><b>视图灵活性</b></dt><dd>评估从同一组对象是否可以创建不同的、定制的数据序列化。</dd><dt><b>客户端数据访问</b></dt><dd>描述 JavaScript 代码处理服务器响应数据的难易程度。</dd>
</dl>
<table class="data-table-1" summary="数据生成技术的相对价值" border="0" cellpadding="0" cellspacing="0" width="100%">
<caption><em>
表 1. 数据生成技术的相对价值</em></caption><tbody><tr><th><br>
</th><th>自行编写 XML</th><th>通过代码生成的 XML 绑定</th><th>通过映射的 XML 绑定</th><th>页面模板 XML</th><th>手工编码的 JSON 序列化</th></tr><tr><td class="tb-row">可伸缩性</td><td>差</td><td>好</td><td>一般</td><td>一般</td><td>差</td></tr><tr class="alt-row"><td class="tb-row">易于集成</td><td>好</td><td>差</td><td>一般</td><td>一般</td><td>好</td></tr><tr><td class="tb-row">Java 类 API</td><td>好</td><td>差</td><td>好</td><td>好</td><td>好</td></tr><tr class="alt-row"><td class="tb-row">对输出的控制</td><td>好</td><td>好</td><td>一般</td><td>好</td><td>好</td></tr><tr><td class="tb-row">视图灵活性</td><td>差</td><td>差</td><td>差</td><td>好</td><td>差</td></tr><tr class="alt-row"><td class="tb-row">客户端数据访问</td><td>差</td><td>差</td><td>差</td><td>一般</td><td>好</td></tr></tbody>
</table>
<br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody><tr><td><img alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" width="100%"></td></tr></tbody>
</table>
<table class="no-print" align="right" cellpadding="0" cellspacing="0">
<tbody><tr align="right"><td><br>
</td></tr></tbody>
</table>
<br>
<br>
<p><a name="IDARN0TB"><span class="atitle">结束语</span></a></p>
<p>表
1
中的数据并不表明某项序列化技术比其他的技术好。毕竟，六种标准的相对重要性取决于项目的具体情况。例如，如果要处理数百种数据类型，这时想要的是可伸缩
性，那么代码生成可能就是最好的选择。如果需要为同一数据模型生成多个不同视图，那么就应当使用页面模板。如果处理的是小规模项目，想降低需要编写的
JavaScript 代码数量，那么请考虑 JSON。</p>
<p>希望这篇文章为您提供了选择适合自己应用程序的序列化技术所需要的信息。</p>
<img src ="http://www.blogjava.net/sunbaoyu/aggbug/17435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sunbaoyu/" target="_blank">bluesky</a> 2005-10-30 15:32 <a href="http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用JavaScript屏蔽[鼠标右键、Ctrl+N、Shift+F10、Alt+F4、F11、F5刷新、退格键]</title><link>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17410.html</link><dc:creator>bluesky</dc:creator><author>bluesky</author><pubDate>Sun, 30 Oct 2005 02:40:00 GMT</pubDate><guid>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17410.html</guid><wfw:comment>http://www.blogjava.net/sunbaoyu/comments/17410.html</wfw:comment><comments>http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17410.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/sunbaoyu/comments/commentRss/17410.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sunbaoyu/services/trackbacks/17410.html</trackback:ping><description><![CDATA[<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">html</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">head</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>  </SPAN><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">meta </SPAN><SPAN style="COLOR: #ff0000">http-equiv</SPAN><SPAN style="COLOR: #0000ff">="Content-Type"</SPAN><SPAN style="COLOR: #ff0000"> content</SPAN><SPAN style="COLOR: #0000ff">="text/html; charset=gb2312"</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>  </SPAN><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">noscript</SPAN><SPAN style="COLOR: #0000ff">><</SPAN><SPAN style="COLOR: #800000">meta </SPAN><SPAN style="COLOR: #ff0000">http-equiv</SPAN><SPAN style="COLOR: #0000ff">="refresh"</SPAN><SPAN style="COLOR: #ff0000"> content</SPAN><SPAN style="COLOR: #0000ff">="0;url=about:noscript"</SPAN><SPAN style="COLOR: #0000ff">></</SPAN><SPAN style="COLOR: #800000">noscript</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>  </SPAN><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">title</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000">屏蔽鼠标右键、Ctrl+N、Shift+F10、Alt+F4、F11、F5刷新、退格键</SPAN><SPAN style="COLOR: #0000ff"></</SPAN><SPAN style="COLOR: #800000">title</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff"></</SPAN><SPAN style="COLOR: #800000">head</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">body</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG id=Codehighlighter1_280_1691_Open_Image onclick="this.style.display='none'; Codehighlighter1_280_1691_Open_Text.style.display='none'; Codehighlighter1_280_1691_Closed_Image.style.display='inline'; Codehighlighter1_280_1691_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_280_1691_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_280_1691_Closed_Text.style.display='none'; Codehighlighter1_280_1691_Open_Image.style.display='inline'; Codehighlighter1_280_1691_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff"><</SPAN><SPAN style="COLOR: #800000">script </SPAN><SPAN style="COLOR: #ff0000">language</SPAN><SPAN style="COLOR: #0000ff">="Javascript"</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN id=Codehighlighter1_280_1691_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_280_1691_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"><!--</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>  </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽鼠标右键、Ctrl+N、Shift+F10、F11、F5刷新、退格键 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">Author: meizz(梅花雨) 2002-6-18 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG id=Codehighlighter1_395_420_Open_Image onclick="this.style.display='none'; Codehighlighter1_395_420_Open_Text.style.display='none'; Codehighlighter1_395_420_Closed_Image.style.display='inline'; Codehighlighter1_395_420_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_395_420_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_395_420_Closed_Text.style.display='none'; Codehighlighter1_395_420_Open_Image.style.display='inline'; Codehighlighter1_395_420_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> document.oncontextmenu()</SPAN><SPAN id=Codehighlighter1_395_420_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_395_420_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{event.returnValue</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;}</SPAN></SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽鼠标右键 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG id=Codehighlighter1_455_468_Open_Image onclick="this.style.display='none'; Codehighlighter1_455_468_Open_Text.style.display='none'; Codehighlighter1_455_468_Closed_Image.style.display='inline'; Codehighlighter1_455_468_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_455_468_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_455_468_Closed_Text.style.display='none'; Codehighlighter1_455_468_Open_Image.style.display='inline'; Codehighlighter1_455_468_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> window.onhelp()</SPAN><SPAN id=Codehighlighter1_455_468_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_455_468_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">return</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">}</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽F1帮助 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> document.onkeydown() <BR><IMG id=Codehighlighter1_511_1689_Open_Image onclick="this.style.display='none'; Codehighlighter1_511_1689_Open_Text.style.display='none'; Codehighlighter1_511_1689_Closed_Image.style.display='inline'; Codehighlighter1_511_1689_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_511_1689_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_511_1689_Closed_Text.style.display='none'; Codehighlighter1_511_1689_Open_Image.style.display='inline'; Codehighlighter1_511_1689_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_511_1689_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_511_1689_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{ <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> ((window.event.altKey)</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&&</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>      ((window.event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">37</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">)</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">||</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">   </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽 Alt+ 方向键 ← </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">       (window.event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">39</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">)))   </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽 Alt+ 方向键 → </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG id=Codehighlighter1_657_730_Open_Image onclick="this.style.display='none'; Codehighlighter1_657_730_Open_Text.style.display='none'; Codehighlighter1_657_730_Closed_Image.style.display='inline'; Codehighlighter1_657_730_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_657_730_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_657_730_Closed_Text.style.display='none'; Codehighlighter1_657_730_Open_Image.style.display='inline'; Codehighlighter1_657_730_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN id=Codehighlighter1_657_730_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_657_730_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{ <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>     alert(</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">不准你使用ALT+方向键前进或后退网页！</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">); <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>     event.returnValue</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">; <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>  }</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG id=Codehighlighter1_738_860_Open_Image onclick="this.style.display='none'; Codehighlighter1_738_860_Open_Text.style.display='none'; Codehighlighter1_738_860_Closed_Image.style.display='inline'; Codehighlighter1_738_860_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_738_860_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_738_860_Closed_Text.style.display='none'; Codehighlighter1_738_860_Open_Image.style.display='inline'; Codehighlighter1_738_860_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>     </SPAN><SPAN id=Codehighlighter1_738_860_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_738_860_Open_Text><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">/*</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"> 注：这还不是真正地屏蔽 Alt+ 方向键， <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>     因为 Alt+ 方向键弹出警告框时，按住 Alt 键不放， <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>     用鼠标点掉警告框，这种屏蔽方法就失效了。以后若 <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>     有哪位高手有真正屏蔽 Alt 键的方法，请告知。</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">*/</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> ((event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">8</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">)  </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">||</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">                 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽退格删除键 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">      (event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">116</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">)</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">||</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">                 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽 F5 刷新键 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG id=Codehighlighter1_1020_1093_Open_Image onclick="this.style.display='none'; Codehighlighter1_1020_1093_Open_Text.style.display='none'; Codehighlighter1_1020_1093_Closed_Image.style.display='inline'; Codehighlighter1_1020_1093_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1020_1093_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1020_1093_Closed_Text.style.display='none'; Codehighlighter1_1020_1093_Open_Image.style.display='inline'; Codehighlighter1_1020_1093_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">      (event.ctrlKey </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&&</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">82</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">))</SPAN><SPAN id=Codehighlighter1_1020_1093_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1020_1093_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{ </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">Ctrl + R </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">     event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">0</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">; <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>     event.returnValue</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">; <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>     }</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG id=Codehighlighter1_1121_1162_Open_Image onclick="this.style.display='none'; Codehighlighter1_1121_1162_Open_Text.style.display='none'; Codehighlighter1_1121_1162_Closed_Image.style.display='inline'; Codehighlighter1_1121_1162_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1121_1162_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1121_1162_Closed_Text.style.display='none'; Codehighlighter1_1121_1162_Open_Image.style.display='inline'; Codehighlighter1_1121_1162_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> (event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">122</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">)</SPAN><SPAN id=Codehighlighter1_1121_1162_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1121_1162_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">0</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;event.returnValue</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;}</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽F11 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> (event.ctrlKey </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&&</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">78</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">) event.returnValue</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;   </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽 Ctrl+n </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> (event.shiftKey </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&&</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">121</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">)event.returnValue</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;  </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽 shift+F10 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> (window.event.srcElement.tagName </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">A</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&&</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> window.event.shiftKey)  <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>      window.event.returnValue </SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;             </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽 shift 加鼠标左键新开一网页 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">if</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> ((window.event.altKey)</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&&</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(window.event.keyCode</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">==</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">115</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">))             </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">屏蔽Alt+F4 </SPAN><SPAN style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><BR><IMG id=Codehighlighter1_1573_1686_Open_Image onclick="this.style.display='none'; Codehighlighter1_1573_1686_Open_Text.style.display='none'; Codehighlighter1_1573_1686_Closed_Image.style.display='inline'; Codehighlighter1_1573_1686_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1573_1686_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1573_1686_Closed_Text.style.display='none'; Codehighlighter1_1573_1686_Open_Image.style.display='inline'; Codehighlighter1_1573_1686_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">  </SPAN><SPAN id=Codehighlighter1_1573_1686_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1573_1686_Open_Text><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{ <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>      window.showModelessDialog(</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">about:blank</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">""</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">dialogWidth:1px;dialogheight:1px</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">); <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>      </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">return</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> </SPAN><SPAN style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">false</SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">; <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>  }</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></SPAN><SPAN style="COLOR: #0000ff"></</SPAN><SPAN style="COLOR: #800000">script</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>屏蔽鼠标右键、Ctrl+N、Shift+F10、Alt+F4、F11、F5刷新、退格键 <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff"></</SPAN><SPAN style="COLOR: #800000">body</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"> <BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff"></</SPAN><SPAN style="COLOR: #800000">html</SPAN><SPAN style="COLOR: #0000ff">></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV><img src ="http://www.blogjava.net/sunbaoyu/aggbug/17410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sunbaoyu/" target="_blank">bluesky</a> 2005-10-30 10:40 <a href="http://www.blogjava.net/sunbaoyu/archive/2005/10/30/17410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>