网页表单存储到XMLajax提交文件form表单

导读:   级别: 中级   Andrei Cioroianu, 高级 Java 开发人员和顾问, Devsphere   2007 年 8 月 22 日   在这个包含两部分的系列文章中,作家兼 Java ?开发人员 Andrei Cioroianu 将教您如何使用 Ajax(Asynchronous JavaScript + XML)技术和 JSF(JavaServer Faces)技术自动保存 Java Web 应用程序中的表单数据。您将学会如何用 Ajax 提交 Web 表单、如何使用 JSF 框架处理 Ajax 请求、如何控制 JSF 请求处理生命周期、如何在服务器端管理表单数据,以及如何识别浏览器会话间的匿名用户。此外,本系列还将探究几个经常发生的开发错误,包括错误的表单数据编码和可能导致请求失败及内存泄漏的错误的 Ajax 请求管理。   简介   很多桌面应用程序允许用户随时保存文件,还有一些产品会自动保存正在编辑的文件以最小化因程序崩溃而造成的数据损失。当用户与 Web 应用程序进行交互时,通常只有当表单提交给服务器时,用户的数据才会被保存。大多数 Web 应用程序不允许用户保存只部分填充的表单,关闭浏览器,然后再继续此任务。此外,如果由于网络问题突然中断了连接,用户的数据将得不到保存,他们的某些工作成果也有可能会因此丢失。   developerWorks Ajax 资源中心   请访问 Ajax 资源中心,这里几乎囊括了关于 Ajax 编程模型的所有信息,包括各种文章、教程、论坛、博客、wikis、活动和新闻。   Ajax 是解决这类问题的理想解决方案。当使用 Ajax 提交表单数据时,页面不必刷新,滚动条的位置也可以保持不变,就好像所处理的是一个桌面应用程序一样。若用户需要填写复杂表单或者面临数据丢失的风险,他们将会非常青睐这种自动保存功能。例如,假设用户在测试一个产品,当他们填写支持表单以便报告测试问题时,这个 Web 支持表单就应该能定期地自动保存。在测试产品时,用户的系统可能会变得不稳定,在提交完整的表单前,他们可能需要多次重启计算机。表单自动保存功能可以节省时间并且能够防止这种情况下的数据丢失。   作为包含两部分的系列文章中的第 1 部分,本期的重点将放在如何用 Ajax 发送表单数据以及如何用 JSF 处理 Ajax 请求。它将向您展示实现数据自动保存的完整数据流程,内容涵盖如何使用 JavaScript 在 Web 浏览器中获取、编码和提交表单数据。本篇文章还会涉及到 JSF 侦听程序如何在服务器端处理已提交的数据,定制 JSF 请求处理生命周期以使它能有效地处理 Ajax 请求。无论是否需要表单自动保存功能或其他类似功能,您都可以将本篇文章介绍的技术应用到基于 Ajax 和 JSF 的任何 Java Web 应用程序中。   当用户与 Web 应用程序进行交互时,通常只有当表单提交给服务器后,用户的数据才会被保存。大多数 Web 应用程序不允许用户保存只部分填充的表单、关闭浏览器,然后再继续此任务。此外,如果由于网络问题突然中断了连接,用户的数据将得不到保存,他们的某些工作成果也有可能会因此丢失。Ajax 是解决这类问题的理想解决方案。   在客户端获取表单数据   本节将给出一个 JSF 表单,其数据通过 JavaScript 和 DOM 在 Web 浏览器中获得。 您可以在自已的 Web 表单应用程序中重用这里介绍的 JavaScript 代码。本节还将解释如何正确地编码表单数据以将它提交给服务器。   构建 JSF 表单   让我们先来看一个典型的 JSF 例子。SupportForm.jsp这个页面包括一些基本 HTML 的元素,比如输入框、列表、单选按钮、复选框和提交按钮。所有输入组件都将其值绑定到称为 SupportBean的 JavaBean 属性。这个页面的头部包括一个
Support Form
<h:inputText id=name size="40" required="true">
<h:selectOneRadio id=platform layout="lineDirection" required="true">
<h:inputTextarea id=problem rows="10" cols="40" required="true"/> <h:commandButton id=submit
action="#{supportBean.submit}"/>
  当用户为了打开 JSF 页面而单击一个 JSF 链接或输入一个 URL 时,Web 浏览器会构建 HTTP 请求并把此请求发送至 Web 服务器,服务器识别包含页面的应用程序并会调用 FacesServlet(在 web.xml内配置)来处理此请求。在进行了某些上下文初始化后,就会执行此页面,而且,JSF 框架还会创建组件树以镜像该 Web 页面所用的 JSF 标记。这些组件的呈现程序生成含有表单元素的 HTML 代码(见清单 2)。   清单 2. SupportForm.jsp 页面生成的 HTML 代码   
Support Form
Support Form
<FORM id=supportForm method=post action="/autosave/faces/SupportForm.jsp" enctype="application/x-www-form-urlencoded"> Name:
<INPUT id=supportForm:name name="supportForm:name" size="40" /> ... Platform:
<INPUT type=radio name=supportForm:platform value="Windows"> Windows <INPUT type=radio name=supportForm:platform value="Linux"> Linux <INPUT type=radio name=supportForm:platform value="Mac"> Mac
... Problem:
<TEXTAREA id=supportForm:problem name=supportForm:problem cols="40" rows="10">
<input id="supportForm:submit" type="submit"
name="supportForm:submit" value="Submit" />
<input type="hidden" name="com.sun.faces.VIEW"
value="H4sIAA..." />
  在这个 HTML 表单的结尾,有一些隐藏元素。如果 javax.faces.STATE_SAVING_METHOD参数在 web.xml文件中被设为 client,那么 JSF 实现会内部使用这些隐藏元素以识别所提交的表单和存储组件树在请求间的状态。从浏览器的角度看,一个 JSF 表单与其他 HTML 表单无异,可以使用 JavaScript 和 DOM 在 Web 浏览器中访问表单元素。
  获取及编码表单数据
  AutoSaveScript.js文件包含一个称为 getFormData()的 JavaScript 函数,它获取一个 form对象并对其元素进行迭代以构建包含名称-值对的字符串。这个字符串遵循标准的 application/x-www-form-urlencoded格式,用 &分隔参数,并在每个参数的名称和值之间使用 =。内部函数 addParam()可以对单一参数进行编码,所使用的是 JavaScript API 提供的 escape()函数。escape()函数用 %后跟被编码字符的两位 16 进制码代替了几乎所有非字母数字的 ASCII 字符。 我之所以说 “几乎所有非字母数字的 ASCII 字符”,是因为除此之外,还有字母数字字符以及无编码的其他一些字符(例如+)。
  例如,如果将字符串 a + b传递给 escape(),结果将是 a%20+%20b(20是空格符的 16 进制码)。这是一个符合 RFC 1738 的有效 URL 编码,但如果将这个已编码的字符串提交给服务器端脚本,例如 JSP,结果将是一个空格而不是 +字符。这也是正确的,因为描述 application/x-www-form-urlencoded格式的 RFC 1866 中规定空格符的编码为 +,并且所有非字母数字字符都以一个 %后跟 16 进制码替代。当服务器对这个字符串进行解码时,任何 +字符都会被还原成一个空格。
  总之,由 escape()执行的 URL 编码并不完全与 application/x-www-form-urlencoded一样,因为 escape()将 +字符保留,不做编码,而在 application/x-www-form-urlencoded中,空格则被编码为 +字符。解决这个问题最简单的方法是将所有 +字符都编码为 %2B(2B是 +的 16 进制代码)。也可以使用 replace()对 escape()的返回结果执行此操作。在本例中,可以将字符串 a + b编码为 a%20%2B%20b。清单 3 所示的是 addParam()内部函数,它将一个编码后的名称-值对添加到 getFormData()的本地 dataString变量。
  清单 3. 对单一请求参数进行编码
  
function getFormData(form) {
var dataString = "";
function addParam(name, value) {
dataString += (dataString.length >0 ? "&" : "")
+ escape(name).replace(//+/g, "%2B") + "="
+ escape(value ? value : "").replace(//+/g, "%2B");
  getFormData()函数获取 form对象的 elements数组,并根据每个元素的类型调用 addParam()。单个名称-值会针对每个文本框、密码和隐藏字段添加。只有当对应的表单元素被选中时,复选框和单选按钮的值才会被编码。如果是列表,单个名称-值对会针对每个选中项添加。之后,getFormData()会返回包含表单编码数据的字符串(见清单 4)。
  清单 4. 获取和编码表单数据
  
function getFormData(form) {
var elemArray = form.
for (var i = 0; i <elemArray. i++) {
var element = elemArray[i];
var elemType = element.type.toUpperCase();
var elemName = element.
if (elemName) {
if (elemType == "TEXT"
|| elemType == "TEXTAREA"
|| elemType == "PASSWORD"
|| elemType == "HIDDEN")
addParam(elemName, element.value);
else if (elemType == "CHECKBOX" &&element.checked)
addParam(elemName,
element.value ? element.value : "On");
else if (elemType == "RADIO" &&element.checked)
addParam(elemName, element.value);
else if (elemType.indexOf("SELECT") != -1)
for (var j = 0; j <element.options. j++) {
var option = element.options[j];
if (option.selected)
addParam(elemName,
option.value ? option.value : option.text);
return dataS
}
  用 Ajax 提交表单数据
  本节将展示如何使用 Ajax 向 JSF 页面发送表单数据,还会涵盖与之相关的其他一些主题,例如错误处理以及 XMLHttpRequest对象的正确管理,这些都是防止 Web 浏览器内的内存泄漏所必须了解的。
  创建和发送 Ajax 请求
  submitFormData()函数的代码可以在 AutoSaveScript.js文件中找到(请参见 下载部分),该函数使用 Ajax 请求对象向 Web 服务器提交编码后的数据。首先,它需要创建这个请求对象,如果是 Microsoft Internet Explorer,就使用 ActiveXObject(),如果是支持 Ajax 的其他浏览器,比如 Firefox、Netscape、Mozilla、Opera 和 Safari,就使用 XMLHttpRequest()。清单 5 显示了创建 XMLHttpRequest对象所需的代码。
  清单 5. 创建 Ajax 请求对象
  
function submitFormData(form) {
if (window.ActiveXObject)
xhr = new ActiveXObject("Microsoft.XMLHTTP");
else if (window.XMLHttpRequest)
xhr = new XMLHttpRequest();
  编码后的表单数据被提交给由表单的 actionURL 所识别的页面,使用的是特定的 HTTP method,在 JSF 表单的情况下,此方法即为 POST。submitFormData()函数也可以同非 JSF 表单一起使用,这类表单有可能会使用默认的 GET方法或 POST。即使这个表单没有指定 action URL,此代码仍可以工作。在这种情况下,submitFormData()将会使用由 document.URL获得的当前页面的 URL。编码后的表单数据可通过 getFormData()函数从 form对象检索到,该函数在前面已介绍过。如果此 HTTP 方法是 GET,那么编码后的数据会追加到 URL ?字符后面。之后,submitFormData()通过 open()方法初始化 xhr对象(见清单 6)。
  清单 6. 初始化 Ajax 请求对象
  
function submitFormData(form) {
var method = form.method ? form.method.toUpperCase() : "GET";
var action = form.action ? form.action : document.URL;
var data = getFormData(form);
if (data &&method == "GET")
url += "?" +
xhr.open(method, url, true);
  当从服务器收到对 Ajax 请求的响应时,会调用称为 submitCallback()的内部函数。如果 autoSaveDebug的值为 true,这个 Ajax 回调就会发出错误信号,请求虽完成(readyState为 4),但其状态却不对(status不是 200)。一旦发生错误,系统就会通过 alert()报告 xhr对象的 status和 statusText属性,而且 autoSaveDebug标记也会设为 false以防您一次又一次地收到错误消息(因为表单保存是周期性执行的)。如果重新加载此页面,JavaScript 代码就会重新初始化,若导致 HTTP 错误的问题仍没有得到解决,您将会再次看到错误消息。这个功能非常适合开发阶段的调试之用。在实际的生产环境中,当发生错误时,与显示告警信息相比,最好是将用户重新引导到其他页面。不管何种情况,xhr对象的 onreadystatechange属性都必须包含一个对 submitCallback()的引用以便此回调函数在 Ajax 请求的生命周期中能被调用(见清单 7)。
  清单 7. 回调函数
  
var autoSaveDebug =
function submitFormData(form) {
function submitCallback() {
if (autoSaveDebug &&xhr.readyState == 4
&&xhr.status != 200) {
autoSaveDebug =
alert("Auto-Save Error: "
+ xhr.status + " " + xhr.statusText);
xhr.onreadystatechange = submitC
  接下来,submitFormData()设定 Ajax-Request报头,它对示例应用程序是特定的,用来在服务器端识别 Ajax 请求,这将在本文后面的部分进行介绍。如果 HTTP 方法是 POST,那么 submitFormData()函数会设置标准 Content-Type报头并且会使用 xhr对象的 send()方法将表单数据提交给 JSF 页面。如果 HTTP 方法是 GET(当前未被 JSF 表单使用),那么表单数据应该已经追加到此 URL,并会用 null参数调用 send()。在提交表单数据后,此函数返回一个对 xhr对象的引用(见清单 8)。
  清单 8. 发送 Ajax 请求
  
function submitFormData(form) {
xhr.setRequestHeader("Ajax-Request", "Auto-Save");
if (method == "POST") {
xhr.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
xhr.send(data);
xhr.send(null);
  管理 XHR 实例
  当需要重复发送表单数据时,您很可能会倾向于重用 XMLHttpRequest(XHR) 对象,但在多数情况下,这并不是一个好主意,原因很多。首先,它将使代码变得复杂,因为您将不得不进行池的管理,也不得不跟踪 XHR 实例的生命周期。请记住,这些对象的状态通常是在 HTTP 请求完成后存取的,并且在不再需要任何 XHR 时,应用程序代码必须要告知管理该池的代码。此外,一些浏览器在为多重请求而重用 XHR 对象时可能也会存在问题。
  为每个 HTTP 请求创建一个新的 XHR 对象也有问题,因为只要应用程序需要这些对象,浏览器就不会从内存中删除它们。如果应用程序不使用 JavaScript delete操作符释放由 XHR 对象占用的内存,不断发送 Ajax 请求的 Web 页面就可能会导致 Web 浏览器中的内存泄漏。在这种情况下,如果在合理的时间段内没有得到响应,不妨采用一种有效策略:中止请求然后重新发送。服务器和客户机都必须做好获得不规范的 Ajax 请求和响应的准备,有些请求或响应甚至可能会丢失。如果这种方法行不通,可以使用 XMLHttpRequest发送同步请求。
  应用程序可以使用 Ajax 实现自动保存,但前提是表单应提供传统的提交按钮或使用同步请求发送数据以做处理。异步请求的不可靠性对于自动保存来说还是可以接受的,因为实现自动保存的作用只是在浏览器瘫痪或网络故障时进行部分恢复。
  AutoSaveScript.js文件包含一个函数,称为 submitAllForms(),它发送此 Web 页面所有表单的数据。这些 XHR 对象保存在一个数组内,数组为每个表单分配一个数组元素。在用 submitFormData()发送表单数据前,submitAllForms()函数会中止并删除前面那个自动保存表单曾使用过的请求。在成功完成了的请求上调用 abort()不起任何作用,并且仅当浏览器收到一个对旧请求的延时响应的情况下,onreadystatechange才被设置为一个空函数。清单 9 显示了对页面表单进行迭代的代码,以将表单数据提交给服务器。
  清单 9. 提交当前页面的所有表单
  
var autoSaveXHR = new Array(document.forms.length);
function submitAllForms() {
var formArray = document.
for (var i = 0; i <formArray. i++) {
if (autoSaveXHR[i]) {
var oldXHR = autoSaveXHR[i];
oldXHR.onreadystatechange = function() { };
oldXHR.abort();
delete oldXHR;
autoSaveXHR[i] = submitFormData(formArray[i]);
  由 submitFormData()返回的 XHR 对象将在下一次调用 submitAllForms()时删除。AutoSaveScript.js文件中的另一个函数是 setAutoSaving(),它能使用 JavaScript API 的 setInterval()函数启用表单的自动保存功能。每隔指定的毫秒数,浏览器都会调用 submitAllForms(),直到 setAutoSaving()被再次使用以借助 clearInterval() 清除之前调用的影响(见清单 10)。
  清单 10. 启动当前页面的表单自动保存功能
  
var autoSaveIntervalId =
function setAutoSaving(millisec) {
if (autoSaveIntervalId) {
clearInterval(autoSaveIntervalId);
autoSaveIntervalId =
if (millisec != 0)
autoSaveIntervalId = setInterval(
"submitAllForms()", millisec);
}
  使用 JSF 侦听程序处理 Ajax 请求
  到目前为止,您已经学会了如何用 Ajax 将表单数据提交给 JSF 页面。现在,让我们看一下如何在服务器端处理 Ajax 请求。我们先来简单介绍 JSF 请求处理生命周期,这是理解本文所附的 示例代码所必需的。JSF 规范包括了对请求处理生命周期的完整描述,在开发自已的 JSF 应用程序时,您会发现该规范非常有用。
  理解 JSF 请求处理生命周期
  JSF 框架处理一个典型的、发布表单数据的请求要经过六个阶段:
  恢复视图
  应用请求值
  处理验证
  更新模型值
  调用应用程序
  呈现响应
  首先,框架需要恢复表单页面的组件树。根据 javax.faces.STATE_SAVING_METHOD配置参数的值,组件树可能会从请求参数中解除序列化,也可能会从 HttpSession对象获取。
  然后,JSF 框架递归式地遍历组件树,更新组件状态。例如,一个实现 EditableValueHolder的输入组件的 submittedValue属性将会设置为相应的请求参数。如果组件的 immediate属性为 true,那么 JSF 框架还会转换并验证所提交的值,设置组件的 value属性。如果 immediate属性为 false,那么这个转换和验证就会在 JSF 请求处理生命周期的下一阶段执行。
  前三个阶段(恢复视图、应用请求值和处理验证)完成后,组件树就包含了所提交的表单数据,而且数据也已由 JSF 框架进行了解码、转换和验证。就目前而言,应用程序应保存 JSF 组件的值以便能在日后恢复 Web 表单的数据。
  一个能自动保存表单数据的 Ajax 请求处理生命周期必须在验证阶段过后终止。否则,JSF 框架将进入下一阶段:更新绑定到 JSF 组件的 JavaBean 属性的模型值。在用户单击按钮发生常规表单提交的情况下,JSF 框架还将调用与这个命令按钮相关的动作方法。最后一个阶段是呈现 HTML 响应。若表单是自动保存的,请求处理生命周期的这后三个阶段(更新模型值、调用应用程序和呈现响应)是不必要的。
  实现 PhaseListener接口
  表单自动保存不应妨碍应用程序的功能。这意味着当利用 Ajax 为自动保存的目的而提交表单时,不应设置任何 JavaBean 属性,也不应调用任何动作方法。此外,在自动保存后也不应生成任何 HTML 响应,因为浏览器不需要任何刷新。因此,应用程序需要控制 JSF 请求处理生命周期,这可以通过实现 PhaseListener很轻松地完成。在本文所附的示例应用程序中,JSF 侦听程序名为 AutoSaveListener并在 faces-config.xml文件中配置(见清单 11)。
  清单 11. 配置 JSF 阶段侦听程序
  
autosave.AutoSaveListener
  正如前面所说明的,验证阶段过后,对自动保存请求的处理必须终止以便 JSF 框架不会更新 JavaBean 数据模型,该模型不应受到自动保存的影响。因此,只有在验证阶段以后,侦听程序才开始接收通知,其 ID 通过 getPhaseId()方法返回。如果请求被标记为 Ajax-Request报头,那么侦听程序的 afterPhase()方法就会调用 FacesContext对象的 responseComplete()方法,告知 JSF 框架,它应该停止处理请求。 (见清单 12)。
  清单 12. 实现 JSF 阶段侦听程序
  
import ponent.EditableValueH
import ponent.UIC
import javax.faces.context.FacesC
import javax.faces.event.PhaseE
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseL
import java.util.I
import java.util.M
public class AutoSaveListener implements PhaseListener {
public PhaseId getPhaseId() {
return PhaseId.PROCESS_VALIDATIONS;
public void beforePhase(PhaseEvent e) {
public void afterPhase(PhaseEvent e) {
System.out.println();
System.out.print(e.getPhaseId());
System.out.print(" - ");
FacesContext ctx = e.getFacesContext();
Map headers = ctx.getExternalContext().getRequestHeaderMap();
if ("Auto-Save".equals(headers.get("Ajax-Request"))) {
System.out.println("Auto-Save");
ctx.responseComplete();
System.out.println("Submit");
printTree(ctx.getViewRoot(), 0);
  打印组件树
  除了在合适的时候停止请求处理外,侦听程序会通过称为 printTree()的递归方法打印组件树。此方法会输出组件成员、呈现程序类型、惟一 ID 及每个组件验证后的值(见清单 13)。
  清单 13. 打印 JSF 组件树
  
public class AutoSaveListener implements PhaseListener {
public void printTree(UIComponent comp, int level) {
if (comp == null)
Object value =
if (comp instanceof EditableValueHolder)
value = ((EditableValueHolder) comp).getValue();
for (int i = 0; i < i++)
System.out.print(" ");
System.out.print(comp.getFamily());
System.out.print(" - ");
System.out.print(comp.getRendererType());
System.out.print(" - [");
System.out.print(comp.getId());
System.out.print("]");
if (value != null) {
System.out.print(" - ");
if (value instanceof Object[]) {
Object array[] = (Object[])
for (int i = 0; i <array. i++) {
System.out.print(array[i]);
System.out.print(" ");
System.out.print(value);
System.out.println();
Iterator children = comp.getChildren().iterator();
while (children.hasNext()) {
UIComponent child = (UIComponent) children.next();
printTree(child, level + 1);
  清单 14 显示了所打印的组件树。
  清单 14. 打印出的组件树
  
PROCESS_VALIDATIONS 3 - Auto-Save
javax.faces.ViewRoot - null - [null]
javax.faces.Form - javax.faces.Form - [supportForm]
javax.faces.Output - javax.faces.Text - [_id0]
javax.faces.Message - javax.faces.Message - [_id1]
javax.faces.Input - javax.faces.Text - [name] - John Smith
javax.faces.Output - javax.faces.Text - [_id11]
javax.faces.Message - javax.faces.Message - [_id12]
javax.faces.SelectOne - javax.faces.Radio - [platform] -
javax.faces.SelectItem - null - [_id13]
javax.faces.SelectItem - null - [_id14]
javax.faces.SelectItem - null - [_id15]
javax.faces.Output - javax.faces.Text - [_id26]
javax.faces.Message - javax.faces.Message - [_id27]
javax.faces.Input - javax.faces.Textarea - [problem] -
Unable to ...
mand - javax.faces.Button - [submit]
  通过获取能实现 EditableValueHolder接口的输入组件的值,printTree()方法会从组件树实际获得已提交的表单数据。在本系列的第 2 部分,您将获得更多有关处理组件树和控制请求处理生命周期的 JSF 技巧。
  结束语
  本文向您展示了如何用 Ajax 编码和提交表单数据以及如何实现一个能从 JSF 组件树检索已提交数据的 JSF 侦听程序。请继续关注本系列的第 2 部分,在该部分中,您将了解如何在服务器端管理表单数据以及如何在用户关闭和重新打开浏览器后恢复 JSF 表单。第 2 部分将要给出的解决方案非常适合多用户和多表单的应用程序,同时还能识别浏览器会话间的匿名用户。
  下载
  描述 名字 大小 下载方法
  本文的示例应用程序 wa-aj-jsf1.zip 9KB
  参考资料
  学习
  您可以参阅本文在 developerWorks 全球站点上的 英文原文。
  在 Wikipedia查找更多 Ajax 资源。
  RFC 1738: Uniform Resource Locators (URL)描述了 URL 编码规则。
  RFC 1866: Hypertext Markup Language - 2.0包含有关 application/x-www-form-urlencoded 格式的更多细节。
  提供了有关 HTML 4.01 文档中的表单的所有信息。
  查看 developerWorks Ajax 资源中心以帮助您现在就开始 Ajax 应用程序的开发。
  获得产品和技术
  JavaServer Faces Technology - Download包含 JSF 参考实现和 JSF 规范。
  Apache MyFaces Project是另一个常见的 JSF 实现。
  讨论
  参与论坛讨论。
  关于作者
  Andrei Cioroianu 是 Devsphere公司的一名高级 Java 开发人员和顾问,该公司专门提供定制 Java EE 开发服务以及 Ajax/JSF 顾问服务。您可以通过 的联系表单与 Andrei 联系。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2452109次
积分:32820
积分:32820
排名:第51名
原创:899篇
转载:447篇
评论:584条
阅读:34444当前位置:&&
本页文章导读:
&&&&?比较详细的关于javascript 解析json的代码&&&&&&
JSON的规则很简单: 对象是一个无序的“‘名称/值'对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值' 对”之间使用“......&&&&?JQuery读取XML文件数据并显示的实现代码&&&&&&
准备工作 在开始之前我们需要做如下准备工作: 1.创建一个名为DEMO.html空白html文件;(推荐使用Editplus创建) 2.熟悉JQuery框架的基本语法;(不熟悉没关系,后面我会注释得很详细) 3.创......&&&&?js实现页面打印功能实例代码(附去页眉页脚功能代码)&&&&&&
代码如下: &html& &head&&/head& &style type="text/css" media="screen"& @media print{ .print {display:} .notPrint {display:} } &/style& &script language="javascript"& function preview() { bdhtml=windo......
&&&&&&最新IT科技资讯推荐:
[1]比较详细的关于javascript 解析json的代码
&&&&来源:&互联网& 发布时间:&
JSON的规则很简单: 对象是一个无序的“‘名称/值'对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值' 对”之间使用“,”(逗号)分隔。具体细节参考http://www.json.org/json-zh.html 举个简单的例子: js 代码
代码如下: function showJSON() { var user = { "username":"andy", "age":20, "info": { "tel": "123456", "cellphone": "98765"}, "address": [ {"city":"beijing","postcode":"222333"}, {"city":"newyork","postcode":"555666"} ] } alert(user.username); alert(user.age); .cellphone); alert(user.address[0].city); alert(user.address[0].postcode); }
这表示一个user对象,拥有username, age, info, address 等属性。 同样也可以用JSON来简单的修改数据,修改上面的例子 js 代码
代码如下: function showJSON() { var user = { "username":"andy", "age":20, "info": { "tel": "123456", "cellphone": "98765"}, "address": [ {"city":"beijing","postcode":"222333"}, {"city":"newyork","postcode":"555666"} ] } alert(user.username); alert(user.age); .cellphone); alert(user.address[0].city); alert(user.address[0].postcode); user.username = "Tom"; alert(user.username); }
JSON提供了json.js包,下载http://www.json.org/json.js 后,将其引入然后就可以简单的使用object.toJSONString()转换成JSON数据。 js 代码
代码如下: function showCar() { var carr = new Car("Dodge", "Coronet R/T", 1968, "yellow"); alert(carr.toJSONString()); } function Car(make, model, year, color) { this.make = this.model = this.year = this.color = }
可以使用eval来转换JSON字符到Object js 代码
代码如下: function myEval() { var str = '{ "name": "Violet", "occupation": "character" }'; var obj = eval('(' + str + ')'); alert(obj.toJSONString()); }
或者使用parseJSON()方法 js 代码
代码如下: function myEval() { var str = '{ "name": "Violet", "occupation": "character" }'; var obj = str.parseJSON(); alert(obj.toJSONString()); }
下面使用prototype写一个JSON的ajax例子。 先写一个servlet (我的是servlet.ajax.JSONTest1.java)就写一句话 java 代码 response.getWriter().print("{ \"name\": \"Violet\", \"occupation\": \"character\" }"); 再在页面中写一个ajax的请求 js 代码
代码如下: function sendRequest() { var url = "/MyWebApp/JSONTest1"; var mailAjax = new Ajax.Request( url, { method: 'get', onComplete: jsonResponse } ); } function jsonResponse(originalRequest) { alert(originalRequest.responseText); var myobj = originalRequest.responseText.parseJSON(); alert(myobj.name); }
prototype-1.5.1.js中提供了JSON的方法,String.evalJSON(), 可以不使用json.js, 修改上面的方法 js 代码
代码如下: function jsonResponse(originalRequest) { alert(originalRequest.responseText); var myobj = originalRequest.responseText.evalJSON(true); alert(myobj.name); }
JSON还提供了java的jar包 http://www.json.org/java/index.html API也很简单,下面举个例子 在javascript中填加请求参数 js 代码
代码如下: function sendRequest() { var carr = new Car("Dodge", "Coronet R/T", 1968, "yellow"); var pars = "car=" + carr.toJSONString(); var url = "/MyWebApp/JSONTest1"; var mailAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: jsonResponse } ); }
使用JSON请求字符串就可以简单的生成JSONObject并进行解析,修改servlet添加JSON的处理(要使用json.jar) java 代码
代码如下: private void doService(HttpServletRequest request, HttpServletResponse response) throws IOException { String s3 = request.getParameter("car"); try { JSONObject jsonObj = new JSONObject(s3); System.out.println(jsonObj.getString("model")); System.out.println(jsonObj.getInt("year")); } catch (JSONException e) { e.printStackTrace(); } response.getWriter().print("{ \"name\": \"Violet\", \"occupation\": \"character\" }"); }
同样可以使用JSONObject生成JSON字符串,修改servlet java 代码
代码如下: private void doService(HttpServletRequest request, HttpServletResponse response) throws IOException { String s3 = request.getParameter("car"); try { JSONObject jsonObj = new JSONObject(s3); System.out.println(jsonObj.getString("model")); System.out.println(jsonObj.getInt("year")); } catch (JSONException e) { e.printStackTrace(); } JSONObject resultJSON = new JSONObject(); try { resultJSON.append("name", "Violet") .append("occupation", "developer") .append("age", new Integer(22)); System.out.println(resultJSON.toString()); } catch (JSONException e) { e.printStackTrace(); } response.getWriter().print(resultJSON.toString()); }
代码如下: function jsonResponse(originalRequest) { alert(originalRequest.responseText); var myobj = originalRequest.responseText.evalJSON(true); alert(myobj.name); alert(myobj.age); }
参考 http://www.json.org/js.html http://www.blogjava.net/Jkallen/archive//37905.html http://www.json.org/ http://www.prototypejs.org/learn/json http://www.json.org/java/index.html /developerworks/cn/web/wa-ajaxintro10/index.html 使用JSON JSON也就是JavaScript Object Notation,是一个描述数据的轻量级语法。JSON的优雅是因为它是JavaScript语言的一个子集。接下来你将看到它为什么如此重要。首先,来比较一下JSON和XML语法。 JSON和XML都使用结构化方法描述数据。例如一个地址簿应用程序可以提供用来产生XML格式的地址卡的web服务:
代码如下: &?xml version='1.0' encoding='UTF-8'?& &card& &fullname&Sean Kelly&/fullname& &org&SK Consulting&/org& &emailaddrs& &address type='work'&kelly@seankelly.biz&/address& &address type='home' pref='1'&kelly@seankelly.tv&/address& &/emailaddrs& &telephones& &tel type='work' pref='1'&+1 214 555 1212&/tel& &tel type='fax'&+1 214 555 1213&/tel& &tel type='mobile'&+1 214 555 1214&/tel& &/telephones& &addresses& &address type='work' format='us'&1234 Main St Springfield, TX &/address& &address type='home' format='us'&5678 Main St Springfield, TX &/address& &/addresses& &urls& &address type='work'&http://seankelly.biz/&/address& &address type='home'&http://seankelly.tv/&/address& &/urls& &/card&
使用JSON, 形式如下:
代码如下: { "fullname": "Sean Kelly", "org": "SK Consulting", "emailaddrs": [ {"type": "work", "value": "kelly@seankelly.biz"}, {"type": "home", "pref": 1, "value": "kelly@seankelly.tv"} ], "telephones": [ {"type": "work", "pref": 1, "value": "+1 214 555 1212"}, {"type": "fax", "value": "+1 214 555 1213"}, {"type": "mobile", "value": "+1 214 555 1214"} ], "addresses": [ {"type": "work", "format": "us", "value": "1234 Main StnSpringfield, TX "}, {"type": "home", "format": "us", "value": "5678 Main StnSpringfield, TX "} ], "urls": [ {"type": "work", "value": "http://seankelly.biz/"}, {"type": "home", "value": "http://seankelly.tv/"} ] }
如你所看到的,JSON有结构化的嵌套数据元素,这一点和XML相似。JSON也是基于文本的,XML也是如此。两者都使用Unicode。JSON和XML都很容易阅读。主观上,JSON更清晰,冗余更少。JSON WEB站点严格地描述了JSON语法,目前就是这样的。它确实是一个简单的小语言! XML确实适合标记文档,但是JSON是数据交互的理想格式。每个JSON文档描述了一个这样一个对象,该对象包含有:嵌套对象、数组、字符串、数字、布尔值或空值。 在这些地址卡例子代码中,JSON版本是更轻量级的,只占用了682字节的空间,而XML版本需要744字节空间。尽管这不是一个可观的节省。而实际的好处则来自解析过程。 XML对比JSON:地位丧失 通过使用XMLHttpRequest对象,可以从你的基于AJAX的应用程序取得XML和JSON文件。典型的,交互代码如下:
代码如下: var req = new XMLHttpRequest(); req.open("GET", "http://localhost/addr?cardID=32", /*async*/true); req.onreadystatechange = myH req.send(/*no params*/null);
作为WEB服务器响应,你提供的处理器函数(myHandler函数)被多次调用,为你提供提前终止事务,更新进度条等机会。通常的,只有在web请求完成以后才起作用:那时,你就可以使用返回的数据了。 为了处理XML版本的地址卡数据,myHandler的代码如下:
代码如下: function myHandler() { if (req.readyState == 4 /*complete*/) { // Update address field in a form with first street address var addrField = document.getElementById('addr'); var root = req.responseXML; var addrsElem = root.getElementsByTagName('addresses')[0]; var firstAddr = addrsElem.getElementsByTagName('address')[0]; var addrText = fistAddr.firstC var addrValue = addrText.nodeV addrField.value = addrV } }
值得注意的是你不必解析XML文档:XMLHttpRequest对象自动地解析了,并使responseXML中的DOM树可用。通过使用responseXML属性,可以调用getElementsByTagName方法查找文档的地址部分,你还可以使用第一个去找到它。然后,可以再次调用getElementsByTagName在地址部分查找第一个地址元素。这就取得了文档的第一个DOM子节点,就是一个文本节点,并取得节点的值,这就是你想要的街道地址。最后,可以在表单域中显示结果。 确实不是一个简单的工作,现在,使用JSON再试一下:
代码如下: function myHandler() { if (req.readyState == 4 /*complete*/) { var addrField = document.getElementById('addr'); var card = eval('(' + req.responseText + ')'); addrField.value = card.addresses[0]. } }
你所做的第一件事情就是解析JSON响应。但是,因为JSON是JavaScript的一个子集,你可以使用JavaScript自己的编译器来解析它,通过调用eval函数。解析JSON仅需要一行!此外,操纵JSON中的对象就像操纵其他JavaScript对象一样。这显然要比通过DOM树来操纵简单,例如: card.addresses[0].value 是第一个街道地址, "1234 Main Stb &" card.addresses[0].type 是地址类型, "work" card.addresses[1] 是家庭地址对象 card.fullname 是card的名称, "Sean Kelly" 如果更仔细观察,你可能会发现XML格式中文档至少有一个跟元素,card。这在JSON里是不存在的,为什么? 大概就是,如果你正在开发JavaScript来访问Web服务,你已经知道你想要得到的。然而,你可以在JSON中这么使用: {"card": {"fullname": ...}} 使用这个技术,你的JSON文件总是以一个带有单一命名属性的对象开始,该属性标识了对象的种类。 JSON是快速可靠的吗? JSON提供轻量的小文档,并且JSON在JavaScript更容易使用。XMLHttpRequest自动为你解析了XML文档,而你还要手工解析JSON文件,但是解析JSON比解析XML更慢么?作者通过几千次的反复测试,使用XMLHttpRequest解析XML和解析JSON,结果是解析JSON比XML要快10倍!当把AJAX当作桌面应用看待时,速度是最重要的因素,很明显,JSON更优秀。 当然,你不能总是控制服务器端来为AJAX程序产生数据。你还可以使用第三方服务器代替服务器提供XML格式的输出。并且,如果服务器恰好提供JSON,你可以确定你真的想使用它吗? 代码中值得注意的是,你将响应文本直接传入到eval中。如果你控制着服务器,就可以这么做。如果不是,一个恶意服务器可以使你的浏览器执行危险操作。在这样的情况下,你最好使用写在JavaScript中的代码来解析JSON。幸运地,这已经有了。 说到解析,Python爱好者可能注意到JSON不只是JavaScript的子集,它还是Python的一个子集。你可以在Python中直接执行JSON,或者使用安全JSON解析代替。JSON.org网站列举了许多常用JSON解析器。 服务器端的JSON 到现在为止,你或许将焦点注意在运行在客户浏览器中的基于AJAX的web应用程序使用JSON。自然地,首先,JSON格式的数据必须在服务器端产生。幸运地是,创建JSON或将其他存在的数据转换成JSON是相当简单的。一些WEB应用程序框架,例如TurboGears,自动包括对JSON输出的支持。 此外商业WEB服务提供商也注意到了JSON。Yahoo最近创建了许多基于JSON的web服务。Yahoo的多种搜索服务,履行计划,del.icio.us,还有高速公路交通服务也都支持JSON输出。毫无疑问,其他主要WEB服务提供商也将加入到对JSON的支持中。 总结 JSON的聪明在于它是JavaScript和Python的子集,使得它更易用,为AJAX提供高效的数据交互。它解析更快,比XML更易使用。JSON正成为现在“Web 2.0”的最强音。每个开发者,无论是标准桌面应用程序或Web应用程序,越来越注意到了它的简单和便捷。我希望你能体会到在buzzword-compliant, Web-2.0-based, AJAX-enabled, 敏捷开发中应用到JSON的乐趣。
[2]JQuery读取XML文件数据并显示的实现代码
&&&&来源:&互联网& 发布时间:&
准备工作 在开始之前我们需要做如下准备工作: 1.创建一个名为DEMO.html空白html文件;(推荐使用Editplus创建) 2.熟悉JQuery框架的基本语法;(不熟悉没关系,后面我会注释得很详细) 3.创建一个名为data.xml的XML文件用来存储数据,XML的结构下面会涉及到,你也可以下载我打包好的文件查看; 4.一个loading.gif图片,这个图片用于在将XML读取出来的等待时间里面显示在空白html文档中 正式开始 Step 1:首先让我们看看这个data.xml的简单结构,我这里演示的数据是"Saturn为您推荐的几本书",故为书籍信息,那么xml就包括书籍的名称,缩略图和书籍描述信息; 以下为XML文件代码:
代码如下: &?xml version="1.0" encoding="utf-8" ?& &books& &book title="藏地密码" imageurl="images/Tibet_Code.jpg"& &description& 这里是概况(www.) &/description& &/book& &book title="剑桥雅思6" imageurl="images/ielts.jpg"& &description& 这里是概况(www.) &/description& &/book& &book title="Professional ASP.NET" imageurl="images/asp.jpg"& &description& 这里是概况(www.) &/description& &/book& &/books&
其次,让我们看看加载在空白HTML文档里面的JavaScript代码:
代码如下: $(document).ready(function() { $.get('myData.xml', function(d){ $('body').append('&h1& Saturn给你推荐几本书: &/h1&'); $('body').append('&dl /&'); $(d).find('book').each(function(){ var $book = $(this); var title = $book.attr("title"); var description = $book.find('description').text(); var imageurl = $book.attr('imageurl'); var html = '&dt& &img
alt="" src="' + imageurl + '" /& &/dt&'; html += '&dd& &span
alt="Loading" /&'; html += '&p &' + title + '&/p&'; html += '&p& ' + description + '&/p&' ; html += '&/dd&'; $('dl').append($(html)); $('.loadingPic').fadeOut(2000); }); }); });
Step 2:这里,我只讲下JavaScript代码原理与运行流程,不过分讨论语法,如果你对语法有任何疑问,请给我留言或者查看JQuery相关文档。 行1:当HTML文档准备完毕之后(即html和JavaScript都下载完毕),会自动触发JQuery的 $(document).ready方法及里面的过程。显然,这里首先执行的是$.get方法。 行3:$.get的第一个参数是XML文件的相对路径(注意路径要填写正确,这里我们把XML和网页文件放在同一文件夹)。第二个参数是一个Callback函数,即回调函数。就是说通过get方法来请求这个XML文件的内容,然后通过这个callback回调函数来操作里面的数据。而callback的参数d表示从XML回调过来的所有数据,有了这个参数d,我们就好进行下面的内容了。 行4:通过JavaScript在文档的BODY中动态添加一个标签&h1&,这个是页面的总标题,无关紧要; 行5:同样在BODY中动态添加一个标签&dl&,用来作为包含循环下面的内容容器。(行20会用到) 行7:这一行很重要,因为我们已经说过,回调函数的参数d表示从XML回调的所有数据,现在我们就需要对这些数据进行处理(筛选)和格式化;请注意:这里通过搜寻book标签(tag),然后循环执行each后面的函数,直到xml里面数据的条目完全循环完毕;(有点像PHP里面的foreach函数的功能) 行9:$(this)实际上就创建一个对象,目的是将d的当前一条书籍信息对象实例化,方便进行操作,这就是$book; 行10--行12:分别获取当前对象$book的书籍名称,描述和缩略图;(注意取属性值和取节点值的语法不同) 行14-行18:格式化书籍信息,以便输出; 行20:将格式化后的信息以HTML输出方式输出到文档中。 行22:为了告诉用户我们当前的信息正在从XML中读取,2000毫秒(2秒)后,图片逐渐消失。 Step 3:至此,大功告成。欢迎大家给我留言,共同讨论JQuery的开发和你所碰到的问题,请不吝赐教。另外,请将下载后的文件夹放在WEB环境下运行(IIS或虚拟主机),请不要直接点开运行。 代码打包下载
[3]js实现页面打印功能实例代码(附去页眉页脚功能代码)
&&&&来源:&互联网& 发布时间:&
代码如下: &html& &head&&/head& &style type="text/css" media="screen"& @media print{ .print {display:} .notPrint {display:} } &/style& &script language="javascript"& function preview() { bdhtml=window.document.body.innerHTML; sprnstr="&!--startprint--&"; eprnstr="&!--endprint--&"; prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17); prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr)); window.document.body.innerHTML= window.print(); } &/script& &body& &form id="WebForm1" method="post" & &center&本部分以上不被打印&/center& &!--startprint--& &div align="center"& &asp:DataGrid id="dgShow" runat="server"& &!--省略部分代码--& &/asp:DataGrid& &table& &tr&&td&打印打印打印打印打印打印打印打印&/td&&/tr& &/table& &/div& &!--endprint--& &center&本部分以下不被打印&/center& &div align="center"& &input type="button" name="print" value="预览并打印" onclick="preview()"& &/div& &style& @media Print { .Noprn { DISPLAY: none }} &/style& &p &不打印&/p& &table id="datagrid"& &tr& &td&打印&/td& &/tr& &/table& &input
type="button" onclick="window.print()" value="print"& &/form& &/body& &/html&
------------- 使用JS打印, 看代码
代码如下: &script language="javascript"& function preview() { bdhtml=window.document.body.innerHTML; sprnstr="&!--startprint--&"; eprnstr="&!--endprint--&"; prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17); prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr)); window.document.body.innerHTML= window.print(); } &/script&
这段代码,他是打印 &!--startprint--&和&!--endprint--& 这个标记之间的网页内容。 所以网页中要包含这个2个标签才行··· 下面是去除页脚页眉的js代码 代码如下:&script& var HKEY_Root,HKEY_Path,HKEY_K HKEY_Root="HKEY_CURRENT_USER"; HKEY_Path="\\Software\\Microsoft\\Internet Explorer\\PageSetup\\"; //设置网页打印的页眉页脚为空 function PageSetup_Null() { try { var Wsh=new ActiveXObject("WScript.Shell"); HKEY_Key="header"; Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,""); HKEY_Key="footer"; Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,""); } catch(e) {} } //设置网页打印的页眉页脚为默认值 function PageSetup_Default() { try { var Wsh=new ActiveXObject("WScript.Shell"); HKEY_Key="header"; Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"&w&b页码,&p/&P"); HKEY_Key="footer"; Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"&u&b&d"); } catch(e) {} } PageSetup_Default(); &/script&注意有可能执行时,会出现没有效果的错误,这时原因是可能你的浏览器限制了active对象的创建,只要取消限制就好了,取消方法如下: 打开你的ie浏览器internet选项—— 安全—— 自定义级别—— 把对没有标记为安全的activex控件进行初始化和脚本运行 设置为启用更多功能请参考现在用的代码。http://img./inc/content.js
最新技术文章:
特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!
(C)2012-,站长邮箱:www_169it_(请将#改为@)}

我要回帖

更多关于 网页表单代码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信