在 ajax 应用程序中实现数据之间交换

易语言-Web服务器与Ajax异步交互易语言 本例程是一HTML写的股票K线图。数据是使用AJAX向易语言程序请求交互取到的。虽然wke浏览器也可以交互数据,但个人感觉还是Ajax顺手。像做Web应用系统一样做易语言程序,是一种什么样的feel? 用html写窗口UI,然后用Ajax交互数据。把web应用搬到窗口程序中,不是梦。不需要IIS、Apache之类的东西就可以使用。做漂亮的程序不是梦。 声明:因为程序只是为了讲解原理,所以有bug自己修复 立即下载

ajax 核心 api(即所谓的 xmlhttprequest)的唯一用途就是发送 http 请求,在 web 浏览器与服务器之间进行数据交换。web 页面中运行的 javascript 代码,可以使用 xmlhttprequest 将该请求参数提交至服务器端脚本,例如 servlet 或 jsp 页面。调用的 servlet/jsp 将发回一个响应,其中包含了一般用于不需刷新整个页面即可更新用户查看内容的数据。此种方法在性能和可用性方面均体现出了独有的优势,因为这将降低网络通信量,而且 web ui 的使用几乎与桌面 gui 一样。

  但是,开发这种用户界面并不简单,因为您必须在客户端上使用 javascript、在服务器端上使用 java(或等效语言)实施数据交换、验证以及处理。然而,在许多情况下,考虑到将会由此获得的益处,付出额外精力构建一个基于 ajax 的界面是值得的。

  在本文中,我将介绍一种用于在 ajax 客户端和服务器之间传输数据的主要方法,并比较传统 web 应用程序模型与该 ajax 模型的不同点。此外,文中还将探讨在服务器端与客户端处理数据的技巧。

  首先,您将了解如何在客户端使用 javascript 编码请求对象的参数。您可以使用所谓的 url 编码(web 浏览器使用的默认编码),或可将请求参数包含在 xml 文档中。服务器将处理该请求,并返回一个其数据也必须进行编码的响应。本文将探讨 javascript object notation (json) 和 xml,这些都是主要的响应数据格式选项。

  本文的大部分内容将主要介绍 ajax 应用程序中通常使用的与 xml 相关的 api。在客户端,xml api 的作用虽非常有限,但已够用。在多数情况下,利用 xmlhttprequest 即可完成所有必需操作。此外,还可使用 javascript 在 web 浏览器中分析 xml 文档并串行化 dom 树。在服务器端,可用于处理 xml 文档的 api 和框架有很多种。本文将介绍如何使用针对 xml 的标准 java api 来实施基本任务,该 api 支持 xml 模式、xpath、dom 以及许多其他标准。

  通过本文,您可以了解到在 ajax 应用程序中实现数据交换所用的最佳技巧和最新的 api。其中涉及的示例代码分别位于以下三个程序包中:util、model 和 feed。util 程序包中的类提供了用于 xml 分析、基于模式的验证、基于 xpath 的查询、dom 串行化以及 json 编码的方法。model 程序包包含的示例数据模型可用于从 xml 文档进行初始化,然后再转换至 json 格式。model 目录中还有一个 schema 示例,可用于 xml 验证。feed 程序包中的类可用于模拟数据馈送,其通过 ajax 每 5 秒检索一次来获得信息,以刷新 web 页面。本文阐释了如何通过终止未完成的 ajax 请求并在使用完 xmlhttprequest 对象后将其删除,避免 web 浏览器的内存泄漏。

  web 目录中包含了 jsp 和 javascript 示例。ajaxutil.js 中包含了发送 ajax 请求、终止请求以及处理 http 错误的实用函数。该文件还提供了可用于 xml 和 url 编码、xml 分析以及 dom 串行化的 javascript 实用程序。ajaxctrl.jsp 文件充当 ajax 控制器,接收每一个 ajax 请求、转发参数至数据模型,或供给处理,然后返回 ajax 响应。其余的 web 文件都是演示如何使用该实用方法的示例。

  在客户端构建请求

  将数据发送至 web 服务器的最简单方法是将请求编码为查询字符串,该字符串根据使用的 http 方法,既可附加至 url,也可包含在请求正文中。如果需要发送复杂的数据结构,更好的解决方案是将信息编码在 xml 文档中。我将在本部分中介绍这两种方法。

  编码请求参数。开发传统 web 应用程序时,无需担心表单数据的编码,因为 web 浏览器会在用户提交数据时自动执行该操作。但是,在 ajax 应用程序中,您必须亲自编码请求参数。javascript 提供了一个非常有用的函数 escape(),该函数用 %hh(其中 hh 是十六进制代码)替换任何无法成为 url 一部分的字符。例如,任何空白字符都用 %20 替换。

  示例代码下载中提供了一个实用函数 buildquerystring(),该函数可连接检索自数组的参数,通过 = 将每个参数的名称和值相分离,并将 & 字符置于每个名称-值对之间:

function buildquerystring(params) {
var query = "";
for (var i = 0; i <  params.length; i++) {
query += (i > 0 ? "&" : "")
+ escape(params[i].name) + "="
+ escape(params[i].value);
    }
return query;
}


  假设您要编码以下参数:

var someparams = [
{ name:"name",  value:"john smith" },
{ name:"email", value:"john@company.com" },
{ name:"phone", value: "(123) 456 7890" }
];

buildquerystring(someparams) 调用将生成包含以下内容的结果:

name=john%20smith&email=john@company.com&phone=%28123%29%20456%207890
 


  如果希望使用 get 方法,则必须将查询附加至 url 的 ? 字符之后。使用 post 时,应通过 setrequestheader() 将 content-type 标题设置为 application/x-www-form-urlencoded,且必须将该查询字符串传递至 xmlhttprequest 的 send() 方法,这会将该 http 请求发送至服务器。

创建 xml 文档。利用字符串通过其属性和数据构建元素是用 javascript 创建 xml 文档最简单的方法。如果采用这种解决方案,则需要一个实用方法来转义 &、< 、>、"、以及  字符:

function escapexml(content) {
if (content == undefined)
return "";
if (!content.length || !content.charat)
content = new string(content);
var result = "";
var length = content.length;
for (var i = 0; i <  length; i++) {
var ch = content.charat(i);
switch (ch) {
case &:
result += "&";
break;
case < :
result += "< ";
break;
case >:
result += ">";
break;
case /":
result += """;
break;
case //:
result += "&apos;";
break;
default:
result += ch;
        }
    }
return result;
}


  要使任务更为简单,还需要一些其他实用程序方法,例如:

function attribute(name, value) {
return " " + name + "=/"" + escapexml(value) + "/"";
}


  以下示例从一个具有以下三个属性的对象的数组构建一个 xml 文档:symbol、shares 和 paidprice:

function buildportfoliodoc(stocks) {
var xml = "< portfolio>";
for (var i = 0; i <  stocks.length; i++) {
var stock = stocks[i];
xml += "< stock ";
xml += attribute("symbol", stock.symbol);
xml += attribute("shares", stock.shares);
xml += attribute("paidprice", stock.paidprice);
xml += "";
    }
xml += "< /portfolio>";
return xml;
}


  如果您喜好使用 dom,则可使用 web 浏览器的 api 分析 xml 和串行化 dom 树。通过 ie,您可以用新的 activexobject("microsoft.xmldom") 创建一个空文档。然后,可以使用 loadxml() 或 load() 方法分别从字符串或 url 分析该 xml。在使用 ie 的情况下,每个节点都有一个称为 xml 的属性,您可以利用它获得该节点及其所有子节点的 xml 表示。因此,您可以分析 xml 字符串、修改 dom 树,然后将该 dom 串行化回 xml。

firefox 和 netscape 浏览器允许您使用 document.implementation.createdocument(...) 创建一个空文档。然后,可以使用 createelement()、createtextnode()、createcdatasection() 等创建 dom 节点。mozilla 浏览器还提供了两个分别名为 domparser 和 xmlserializer 的 api。domparser api 包含 parsefromstream() 和 parsefromstring() 方法。xmlserializer 类具有串行化 dom 树的相应方法:serializetostream() 和 serializetostring()。

  以下函数分析一个 xml 字符串并返回 dom 文档:

function parse(xml) {
var dom;
try{
dom = new activexobject("microsoft.xmldom");
dom.async = false;
dom.loadxml(xml);
} catch (error) {
try{
var parser = new domparser();
dom = parser.parsefromstring(xml, "text/xml");
delete parser;
} catch (error2) {
if (debug)
alert("xml parsing is not supported.");
        }
    }
return dom;
}


  第二个函数串行化一个 dom 节点及其所有子节点,将 xml 作为字符串返回:

function serialize(dom) {
var xml = dom.xml;
if (xml == undefined) {
try{
var serializer = new xmlserializer();
xml = serializer.serializetostring(dom);
delete serializer;
} catch (error) {
if (debug)
alert("dom serialization is not supported.");
        }
    }
return xml;
}


  还可以使用 xmlhttprequest 作为分析程序或串行化程序。在从服务器接收到对 ajax 请求的响应后,该响应会自动进行分析。可通过 xmlhttprequest 的 responsetext 和 responsexml 属性分别访问文本版本和 dom 树。此外,在将 dom 树传递至 send() 方法时自动将其串行化。

  发送请求。在先前的文章中,我介绍了 xmlhttprequest api 和一个实用函数 sendhttprequest(),您可以在提供下载的示例中的 ajaxutil.js 文件中找到。该函数有四个参数(http 方法、url、一个参数数组和一个回调),可创建 xmlhttprequest 对象,设置其属性并调用 send() 方法。如果提供了回调参数,则异步发送请求,并在收到响应后调用回调函数。否则,将同步发送请求,您可以在 sendhttprequest() 返回后即刻处理响应。

  如您所见,在使用 xmlhttprequest 时必须进行一些重要选择

  将要使用的 http 方法(get 或 post)
  用于编码请求参数的格式(本文前面已探讨了 xml 和 url 编码)
  是进行同步(等待响应)调用还是异步(使用回调)调用
  响应的格式,如 xml、xhtml、html 或 javascript object notation (json)(本文稍后将对此进行探讨)。假设您希望从数据馈送了解一些股价信息,且无需用户干预即可定期刷新信息。在本例中,应异步发送 http 请求,这是为了在检索信息时不阻塞用户界面。请求参数是一个符号数组,可在 url 中进行编码。由于服务器可能超载,因此您不希望在进行频繁请求时发送 xml 文档。由于您只对最新的股价感兴趣,因此应终止任何未完成的先前请求:

var ctrlurl = "ajaxctrl.jsp";
var feedrequest = null;

function sendinforequest(symbols, callback) {
if (feedrequest)
abortrequest(feedrequest);
var params = new array();
for (var i = 0; i <  symbols.length; i++)
params[i] = {
name:"symbol",
value:symbols[i]
        };
feedrequest = sendhttprequest(
"get", ctrlurl, params, callback);
}
 


  在调用请求对象的 abort() 方法之前,abortrequest() 函数(可在 ajaxutil.js 文件中找到)会将 onreadystatechange 属性设置为不执行任何操作的回调。此外,删除该请求对象以避免内存泄漏,这点至关重要:

function abortrequest(request) {
function donothing() {
    }
request.onreadystatechange = donothing;
request.abort();
delete feedrequest;
}


  我们来考虑另一种情况:在传输要保存在数据库中的整个用户数据时,应同步发送请求,因为您可能不希望用户在保存这些数据进行时对其进行修改。在这种情况下,首选 xml 格式,这是因为在文档中进行对象模型编码通常要比使用很多字符串参数更简单。此外,保存数据的请求并不频繁,服务器可以毫无问题地处理负载。可将 xml 文档编码为参数,这样您就可以使用 el 语法 (${param.xml}) 在 jsp 页面中访问该文档了。以下就是发送在 xml 文档中编码的模型数据的函数:

function sendsaverequest(xml) {
var params = [ { name:"xml", value:xml } ];
var saverequest = sendhttprequest("post", ctrlurl, params);
if (saverequest)
delete saverequest;
}


  如果需要恢复对象模型,则也可同步发送请求,从服务器检索数据。在这种情况下,服务器应当返回一个 json 响应,以便您可利用 eval(loadrequest.responsetext) 轻松将其转换为 javascript 对象树:

function sendloadrequest() {
var model = null;
var loadrequest = sendhttprequest("get", ctrlurl);
if (loadrequest) {
model = eval(loadrequest.responsetext);
delete loadrequest;
    }
return model;
}


  以下两部分介绍了通常在服务器上对 xml 文档执行的操作,以及如何响应 ajax 请求。

在服务器端处理请求

  servlet/jsp 容器分析各个 http 请求并创建一个 servletrequest 实例,该实例使您可以通过 getparameter() / getparametervalues() 获得请求参数,或通过 getinputstream() 获得请求正文。在 jsp 页面中,也可以使用 el 语法(${param...} 和 ${paramvalues...})获得这些参数。请注意,只有在 ajax 客户端使用了类似于 buildquerystring() 之类的实用函数,通过 application/x-www-form-urlencoded 格式来编码数据(本文前一部分有述)的情况下,才可通过 getparameter() 或 ${param...} 获得请求参数。如果在客户端上将 xml 文档或 dom 树传递至 xmlhttprequest 的 send() 方法,则必须在服务器端使用 servletrequest 的 getinputstream() 方法。

  数据验证。典型的 web 应用程序会进行许多数据验证操作。多数可能的错误相当简单,例如缺少请求参数、数字格式错误等等。这些错误通常是由于用户忘记输入表单元素的值或提供了无效值引起的。web 框架(如 jsf 和 oracle adf faces)非常善于处理这些用户错误。在 ajax 应用程序中,这些错误可以在客户端使用 javascript 来捕获和处理。例如,您可使用 isnan(new number(value)) 验证数字值是否无效。

  出于安全和可靠性的考虑,应当在服务器端对数据进行重新验证,而不应想当然地认为 xml 请求格式设置正确。xml 模式是在服务器端验证复杂请求的有用工具。示例代码下载中包含了一个名为 xmlutil 的类,它提供用于加载和使用模式文档的方法。以下代码段显示了如何初始化 schemafactory:

import javax.xml.*;
import javax.xml.validation.*;
...
protected static schemafactory schemafactory;
static {
schemafactory = schemafactory.newinstance(
xmlconstants.w3c_xml_schema_ns_uri);
schemafactory.seterrorhandler(newerrorhandler());
}

the newerrorhandler() method returns a sax error handler:

import org.xml.sax.*;
...
public static errorhandler newerrorhandler() {
return new errorhandler() {
public void warning(saxparseexception e)
throws saxexception {
logger.global.warning(e.getmessage());
        }

public void error(saxparseexception e)
throws saxexception {
throw e;
        }

public void fatalerror(saxparseexception e)
throws saxexception {
throw e;
        }
    };
}
 


  可以使用 getresourceasstream() 查找并加载某个目录中的 xsd 文件或 classpath 中指定的 jar:

public static inputstream getresourceasstream(string name)
throws ioexception {
inputstream in = xmlutil.class.getresourceasstream(name);
if (in == null)
throw new filenotfoundexception(name);
return in;
}


  然后,使用 schemafactory 实例通过 newschema() 方法获取 schema 对象:

import javax.xml.validation.*;
...
public static schema newschema(string name)
throws ioexception, saxexception {
schema schema;
inputstream in = getresourceasstream(name);
try{
schema = schemafactory.newschema(new streamsource(in));
}finally{
in.close();
    }
return schema;
}

您还可以使用以下方法创建 oracle xmlschema 对象:

import oracle.xml.parser.schema.xmlschema;
import oracle.xml.parser.schema.xsdbuilder;
...
public static xmlschema neworacleschema(string name)
throws ioexception, saxexception {
xmlschema schema;
inputstream in = getresourceasstream(name);
try{
xsdbuilder builder = new xsdbuilder();
schema = builder.build(new inputsource(in));
} catch (exception e){
throw new saxexception(e);
}finally{
in.close();
    }
return schema;
}


  接下来,您需要创建一个 documentbuilderfactory。如果在 classpath 中找到的是 jaxp 1.1 实现,则由 jaxp 1.2 定义的 setschema() 方法可能会抛出 unsupportedoperationexception,此时需要将 jaxp 1.1 实现替换为 java se 5.0 的 jaxp 1.2 实现。在这种情况下,您仍可使用 neworacleschema() 创建模式对象,并通过 setattribute()方法对其进行设置:

import javax.xml.parsers.*;
import oracle.xml.jaxp.jxdocumentbuilderfactory;
...
public static documentbuilderfactory newparserfactory(
string schemaname) throws ioexception, saxexception {
documentbuilderfactory parserfactory
= documentbuilderfactory.newinstance();
try{
parserfactory.setschema(newschema(schemaname));
} catch (unsupportedoperationexception e) {
if (parserfactory instanceof jxdocumentbuilderfactory) {
parserfactory.setattribute(
jxdocumentbuilderfactory.schema_object,
neworacleschema(schemaname));
        }
    }
return parserfactory;
}


  然后,创建一个 documentbuilder 对象,并使用该对象验证和分析 xml 文档:

import javax.xml.parsers.*;
...
public static documentbuilder newparser(
documentbuilderfactory parserfactory)
throws parserconfigurationexception {
documentbuilder parser = parserfactory.newdocumentbuilder();
parser.seterrorhandler(newerrorhandler());
return parser;
};


  假设您要根据 portfolio.xsd 模式示例验证 xml 文档:

< xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema">

< xsd:element name="portfolio" type="portfoliotype"

< xsd:complextype name="portfoliotype">
< xsd:sequence>
< xsd:element name="stock"
minoccurs="0" maxoccurs="unbounded">
< xsd:complextype>
< xsd:attribute name="symbol"
type="xsd:string" use="required"/>
< xsd:attribute name="shares"
type="xsd:positiveinteger" use="required"/>
< xsd:attribute name="paidprice"
type="xsd:decimal" use="required"/>
< /xsd:complextype>
< /xsd:element>
< /xsd:sequence>
< /xsd:complextype>

< /xsd:schema>
 

 datamodel 类的 parseportfoliodoc() 方法使用 xmlutil 验证和分析 xml 参数,并返回一个 dom 文档:

private static final string schema_name
= "/ajaxapp/model/portfolio.xsd";
private static documentbuilderfactory parserfactory;
   
private static document parseportfoliodoc(string xml)
throws ioexception, saxexception,
parserconfigurationexception {
synchronized (datamodel.class) {
if (parserfactory == null)
parserfactory = xmlutil.newparserfactory(schema_name);
    }
documentbuilder parser = xmlutil.newparser(parserfactory);
inputsource in = new inputsource(new stringreader(xml));
return parser.parse(in);
}


  现在,您拥有了一个 dom 树,接下来要获取形成 dom 节点所需的数据。

  提取所需信息。您可以使用 dom api 或查询语言(如 xquery 或 xpath)来浏览 dom 树。java 为 xpath 提供了标准的 api,后面会用到。xmlutil 类创建一个具有 newxpath() 方法的 xpathfactory:

import javax.xml.xpath.*;
...
protected static xpathfactory xpathfactory;
static {
xpathfactory = xpathfactory.newinstance();
}
   
public static xpath newxpath() {
return xpathfactory.newxpath();
}


  以下方法在给定的上下文中求解 xpath 表达式,返回结果值:

import javax.xml.xpath.*;
import org.w3c.dom.*;
...
public static string evaltostring(string expression,
object context) throws xpathexpressionexception {
return (string) newxpath().evaluate(expression, context,
xpathconstants.string);
}
   
public static boolean evaltoboolean(string expression,
object context) throws xpathexpressionexception {
return ((boolean) newxpath().evaluate(expression, context,
xpathconstants.boolean)).booleanvalue();
}
   
public static double evaltonumber(string expression,
object context) throws xpathexpressionexception {
return ((double) newxpath().evaluate(expression, context,
xpathconstants.number)).doublevalue();
}
   
public static node evaltonode(string expression,
object context) throws xpathexpressionexception {
return (node) newxpath().evaluate(expression, context,
xpathconstants.node);
}
   
public static nodelist evaltonodelist(string expression,
object context) throws xpathexpressionexception {
return (nodelist) newxpath().evaluate(expression, context,
xpathconstants.nodeset);
}

 datamodel 的 setdata() 方法使用 xpath 求解方法从组合 xml 文档提取信息:

public synchronized void setdata(string xml)
throws ioexception, saxexception,
parserconfigurationexception,
xpathexpressionexception {
try{
arraylist stocklist
= new arraylist();
document doc = parseportfoliodoc(xml);
nodelist nodelist = xmlutil.evaltonodelist(
"/portfolio/stock", doc);
for (int i = 0; i <  nodelist.getlength(); i++) {
node node = nodelist.item(i);
stockbean stock = new stockbean();
stock.setsymbol(
xmlutil.evaltostring("@symbol", node));
stock.setshares(
(int) xmlutil.evaltonumber("@shares", node));
stock.setpaidprice(
xmlutil.evaltonumber("@paidprice", node));
stocklist.add(stock);
        }
this.stocklist = stocklist;
} catch (exception e){
logger.global.logp(level.severe, "datamodel", "setdata",
e.getmessage(), e);
    }
}


  一旦服务器端的数据模型中具备了数据,就可根据应用程序的要求对其进行处理了。然后,您必须响应 ajax 请求。

  在服务器端生成响应

  将 html 作为 ajax 请求的响应而返回是一种最简单的解决方案,这是因为您可以使用 jsp 语法构建标记,而 ajax 客户端只需使用 < div> 或 < span> 元素的 innerhtml 属性在页面某处插入 html。但是,向 ajax 客户端返回不带任何表示标记的数据则更为有效。您可以使用 xml 格式或 json。


  生成 xml 响应。java ee 提供了很多创建 xml 文档的选项:可通过 jsp 生成、通过 jaxb 从对象树创建、或利用 javax.xml.transform 生成。以下示例中的转换程序将串行化一个 dom 树:

import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
...
public static transformerfactory serializerfctory;
static {
serializerfctory = transformerfactory.newinstance();
}
   
public static void serialize(node node, outputstream out)
throws transformerexception {
transformer serializer = serializerfctory.newtransformer();
properties serializerprops = new properties();
serializerprops.put(outputkeys.method, "xml");
serializer.setoutputproperties(serializerprops);
source source = new domsource(node);
result result = new streamresult(out);
serializer.transform(source, result);
}


  有这么多可在服务器端生成 xml 的标准选项和开发源框架,您唯一所要做的就是选择一个适合你的选项。但是,在客户端上,由于只能使用 dom 来分析 xml,因此情况非常不同。某些浏览器还支持 xpath 和 xslt。

在先前的 ajax 文章中,您学习了如何通过 jsp 生成 xml,然后在客户端上利用 javascript 和 dom 对其进行分析。另一个解决方案是使用 json 而非 xml 作为响应 ajax 请求的数据格式。如前所述,json 字符串可通过 eval() 函数转化为 javascript 对象树。较之利用 javascript 从 dom 树提取信息而言,这更为简单些。您所需的就是一个在服务器端生成 json 的良好实用类。

  json 编码。jsonencoder 类提供了编码文字、对象和数组的方法。结果存储在 java.lang.stringbuilder 中:

package ajaxapp.util;

public class jsonencoder {
private stringbuilder buf;
   
public jsonencoder() {
buf = new stringbuilder();
    }

    ...
}
 


  character() 方法编码单一字符:

public void character(char ch) {
switch (ch) {
case //:
case //":
case ///:
buf.append(///);
buf.append(ch);
break;
case / :
buf.append(///);
buf.append( );
break;
case /
:
buf.append(///);
buf.append(
);
break;
case /
:
buf.append(///);
buf.append(
);
break;
default:
if (ch >= 32 && ch <  128)
buf.append(ch);
else{
buf.append(///);
buf.append(u);
for (int j = 12; j >= 0; j-=4) {
int k = (((int) ch) >> j) & 0x0f;
int c = k <  10 ? + k :a + k - 10;
buf.append((char) c);
                }
            }
    }
}


  string() 方法编码整个字符串:

public void string(string str) {
int length = str.length();
for (int i = 0; i <  length; i++)
character(str.charat(i));
}

 literal() 方法编码 javascript 文字:

public void literal(object value) {
if (value instanceof string) {
buf.append(/");
string((string) value);
buf.append(/");
} else if (value instanceof character) {
buf.append(//);
character(((character) value).charvalue());
buf.append(//);
} else
buf.append(value.tostring());
}


  comma() 方法附加一个逗号字符:

private void comma() {
buf.append(,);
}


  deletelastcomma() 方法将移除缓冲区末尾最后一个逗号字符(如果有的话):

private void deletelastcomma() {
if (buf.length() > 0)
if (buf.charat(buf.length()-1) == ,)
buf.deletecharat(buf.length()-1);
}


  startobject() 方法附加一个 { 字符,用于表示一个 javascript 对象的开始:

public void startobject() {
buf.append({);
}


  property() 方法编码 javascript 属性:

public void property(string name, object value) {
buf.append(name);
buf.append(:);
literal(value);
comma();
}


  endobject() 方法附加一个 } 字符,用于表示一个 javascript 对象的结束:

public void endobject() {
deletelastcomma();
buf.append(});
comma();
}

startarray() 方法附加一个 [ 字符,用于表示一个 javascript 数组的开始:

public void startarray() {
buf.append([);
}


  element() 方法编码 javascript 数组的元素:

public void element(object value) {
literal(value);
comma();
}


  endarray() 方法附加一个 ] 字符,用于表示一个 javascript 数组的结束:

public void endarray() {
deletelastcomma();
buf.append(]);
comma();
}


  tostring() 方法返回 json 字符串:

public string tostring() {
deletelastcomma();
return buf.tostring();
}


  clear() 方法清空缓冲区:

public void clear() {
buf.setlength(0);
}


  datamodel 使用 jsonencoder 类来编码其维护的数据:

public synchronized string getdata() {
jsonencoder json = new jsonencoder();
json.startarray();
for (int i = 0; i <  stocklist.size(); i++) {
stockbean stock = stocklist.get(i);
json.startobject();
json.property("symbol", stock.getsymbol());
json.property("shares", stock.getshares());
json.property("paidprice", stock.getpaidprice());
json.endobject();
    }
json.endarray();
return json.tostring();
}

如果提供了 xml 请求参数,则 ajaxctrl.jsp 页面将设置模型的数据。否则,该页面会使用 ${datamodel.data} el 表达式输出 getdata() 返回的 json 字符串:

< %@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
< jsp:usebean id="datamodel" scope="session"
class="ajaxapp.model.datamodel" />

< c:choose>
    ...
< c:when test="${!empty param.xml}">
< c:set target="${datamodel}"
property="data"
value="${param.xml}" />
< /c:when>
< c:otherwise>
${datamodel.data}
< /c:otherwise>
< /c:choose>
 


  这个作业并未完成,因为 ajax 客户端必须处理 json 数据。

  在客户端处理响应

  在典型的 web 应用程序中,您使用 jsp、web 框架和标记库在服务器端生成内容。ajax 应用程序非常适合这种情况,因为 web 框架(如 javaserver faces 和 oracle adf faces)在构建 ajax 应用程序时非常有用。然而,ajax 和非 ajax 应用程序之间仍然存在着明显不同。使用 ajax 时,您必须在客户端处理数据,并用 javascript 动态生成内容来向用户提供数据。

  如果使用 json 格式进行数据转换,则使用 javascript 提供的 eval() 函数将文本转换为对象树非常容易。如果喜欢使用 xml,则还需要执行许多其他操作,但这种格式也有其自身的优势。例如,许多类型的客户端可以使用 xml,而 json 只在 javascript 环境中易于分析。此外,在使用 xml 的情况下,可以更快地发现并修正错误,从而缩短了调试时间。

  使用 javascript 访问 dom 树。javascript 的 dom api 非常类似于 java 的 org.w3c.dom 程序包。主要的区别在于对属性的访问。在 javascript 中可直接访问属性,而 java 将属性视为私有,您需要通过 get 和 set 方法进行访问。例如,您可通过 dom.documentelement 获得文档的根元素。

  dom 是一种低级的 api,利用它可以访问已分析文档的结构。例如,在大多数情况下您都想忽略注释,并可能不愿意拥有相邻的文本节点。来看下面这个简单示例:

var xml = "< element>da< !--comment-->ta&"
+ "< ![cdata[cdata< /element>";


  您可以使用先前介绍的实用函数分析上述 xml 字符串:

var dom = parse(xml);


  您可以在 ajaxutil.js 中找到 parse() 函数的代码;本例中,该函数返回一个 dom 树,其根元素包含一个文本节点,其后是一条注释、另一个文本节点和一个字符数据节点。如果希望包含的文本不带注释,则必须迭代元素的子元素,连接文本和字符数据节点的值(其类型分别为 3 和 4):

var element = dom.documentelement;
var childnodes = element.childnodes;
var text = "";
for (var i = 0; i <  childnodes.length; i++)
if (childnodes[i].nodevalue) {
var type = childnodes[i].nodetype;
if (type == 3 || type == 4)
text += childnodes[i].nodevalue;
    }

使用 dom 时,应当构建一个小的实用函数集,以避免处理上述这些低级细节。

  使用 javascript 生成动态内容。web 浏览器使您可以通过文档对象访问 web 页面的 dom 结构。例如,您可以利用 document.getelementbyid(...) 非常轻松地找到一个元素。还可以创建可插入现有文档的新元素和文本节点。然而,如下所示,通过连接字符串构建 html 要更为简单:

function updateinfo(request) {
var shares = eval(request.responsetext);
var table = "< table border=1 cellpadding=5>";
table += "< tr>";
table += "< th>symbol< /th>";
table += "< th>trend< /th>";
table += "< th>last price< /th>";
table += "< /tr>";
for (var i = 0; i <  shares.length; i++) {
var share = shares[i];
var symbol = escapexml(share.symbol)
var trend = share.trend > 0 ? "+" : "-";
var lastprice = new number(share.lastprice).tofixed(2);
table += "< tr>";
table += "< td>" + symbol + "< /td>";
table += "< td>" + trend + "< /td>";
table += "< td>" + lastprice + "< /td>";
table += "< /tr>";
    }
table += "< /table>";
document.getelementbyid("table").innerhtml = table;
}


  通过设置由 getelementbyid() 返回的对象的 innerhtml 属性,可将生成的 html 插入空

元素中,例如:

< div id="table">
< /div>


  本文的示例将 updateinfo() 函数用作回调来处理对 ajax 请求的响应,该请求是通过 ajaxlogic.js 文件中的 sendinforequest 发送到服务器的。如果希望每 5 秒更新一次信息,可使用 javascript 的 setinterval() 函数:

var symbols = [ ... ];
setinterval("sendinforequest(symbols, updateinfo)", 5000);


  一个名为 datafeed 的类模拟服务器端的馈送。ajaxctrl.jsp 页面调用该馈送的 getdata() 方法,将响应作为 json 字符串返回。在客户端,updateinfo() 函数利用 eval(request.responsetext) 对该 json 字符串进行分析,如上述代码示例中所示。

      (责任编辑:包春林)


易语言做Web服务器与Ajax异步交互-易语言 易语言做Web服务器与Ajax异步交互 立即下载

相关推荐

e语言-Ajax XmlHttp对象参考手册

资源介绍:XmlHttp是什么?最通用的定义为:XmlHttp是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面。来自MSDN的解释:XmlHttp提供客户端同http服务器通讯的协议。客户端可以通过XmlHttp对象(MSXML2.XMLHTTP.3.0)向http服务器发送请求并使用微软XML文档对象模型Microsoft® XML Document Object Model (DOM)处理回应。 现在的绝对多数浏览器都增加了对XmlHttp的支持,IE中使用ActiveXObject方式创建XmlHttp对象,其他浏览器如:Firefox、Opera等通过window.XMLHttpRequest来创建xmlhttp对象。 资源界面:资源下载:

Ajax请求

完成Ajax请求大致可分为4步: 创建Ajax请求 开始链接 发送数据 等待接收数据 创建Ajax请求 IE浏览器并不兼容 var ajax=new XMLHttpRequest(); 处理兼容问题 if (window.XMLHttpRequest) { var ajax = new XMLHttpRequest(); } else { var ajax = new ActiveXObject(“Microsoft.XMLHTTP”); } 开始链接 ajax.open(“GET”, “

weixin_46178009的博客 443

Ajax开源代码(适合于ajax初学者)

提供了几个ajax的开源代码,适合于ajax的初学者

ajax post请求400、415错误的一种解决方法

400、415的错误是数据传送格式造成的。我遇到的情况是:后台需要接收一个对象,我开始的写法是: type : "post", url : URL, dataType : "json", contentType :"application/json", data:{ date: date,

y_onghuming的博客 2862

【小程序】支付宝直付通解决方案

支付宝直付通是支付宝为小程序提供的一种支付解决方案,可以实现小程序中直接使用支付宝进行支付。以上是一个简单的支付宝直付通解决方案及相关代码示例。具体的使用还需要根据自己的业务需求进行定制化开发和调整。

qq_31532979的贺公子之数据科学与艺术博客,致力于科技向善,拥抱开源,要用技术的影响力来领导团队,而不是威权和职位! 1281

Android 导出aar 用于Unity 百度语音唤醒

AndroidStudio版本下载地址Android Studio Arctic Fox Unity版本2021.3.26f1c1 新建AndroidStudio工程 新建module 这里注意一下,网上很多教程说要注意包名要和unity一样,但是测试下来,不一样也可以的 在新建的module里添加这两个jar包,并点击右键add as library 导入jniLibs 右键创建这几个package 代码就安装这个大佬的写参考代码 需要注意的的是在WakeupListener脚本里U

weixin_38777563的博客 633

易语言怎么模拟ajax数据类型,易语言模拟post获取json返回的值呢

网站上显示的时间是通过json post 回显,抓包没发现有返回值,怎么通过易语言模拟post获得返回的值呢。测试:http://a.jd.com/coupons.htmlQQ截图20170407172740.jpg (65.92 KB, 下载次数: 0)2017-4-7 17:27 上传ajax在这里/*** 在标签上添加[coupon-time="batchid"]属性, 调用这个方法会填充时...

weixin_39887748的博客 1166

以太网硬件核心:MAC、PHY、MII与交换机原理与实战排查

计算机网络通信的基础依赖于一套完整的硬件协议栈。在OSI模型中,数据链路层和物理层是实现设备间可靠、高效数据传输的基石。其核心原理在于将上层数据包封装成帧,并通过特定的介质访问控制与物理信号转换机制进行传输。这一过程的技术价值在于为上层应用提供了透明、稳定的通信信道,是互联网和所有局域网通信的物理承载。在嵌入式系统、网络设备开发及运维等应用场景中,深入理解底层硬件交互至关重要。本文将聚焦于以太网硬件的两大核心组件:负责逻辑成帧与流量控制的MAC控制器,以及负责数模转换与链路协商的PHY芯片。它们通过MII、

dgqvhtlwq472235338的博客 424

在ajax 应用程序中实现数据之间交换

在本文中,我将介绍一种用于在 Ajax 客户端和服务器之间传输数据的主要方法,并比较传统 Web 应用程序模型与该 Ajax 模型的不同点。此外,文中还将探讨在服务器端与客户端处理数据的技巧。   首先,您将了解如何在客户端使用 JavaScript 编码请求对象的参数。您可以使用所谓的 URL 编码(Web 浏览器使用的默认编码),或可将请求参数包含在 XML 文档中。服务器将处理该请求,并返...

开心的穷下去 166

使用循环神经网络预测温度

简介 本文以天气时间序列数据集为例,讨论如何使用深度学习模型预测未来天气温度。 使用的是由德国耶拿马克思普朗克生物地球化学研究所的气象站记录。 数据每10分钟记录一次,共记录14种不同的量,如气温、气压、湿度、风向等,原始数据可追溯到2003年,本例只使用2009-2016年的数据。 数据 下载并解压数据略。 加载数据: data_dir = r'E:\practice\tf2\temperature' fname = os.path.join(data_dir, 'jena_climate_2009_

guotianqing的博客 5282

量子计算入门指南:密度算符的核心概念与应用解析

本文深入解析了量子计算中密度算符的核心概念与应用。作为描述量子系统“状态的状态”的关键数学工具,密度算符能有效处理混合态与子系统描述,是理解量子噪声、量子纠错和开放系统演化的基石。文章通过对比纯态与混合态,阐释了密度矩阵的数学定义与物理意义,并结合代码示例演示了其在实际量子计算问题中的强大威力。

day7的博客 470

在Ajax 应用程序中实现数据之间交换

Ajax 核心 API(即所谓的 XMLHttpRequest)的唯一用途就是发送 HTTP 请求,在 Web 浏览器与服务器之间进行数据交换。Web 页面中运行的 JavaScript 代码,可以使用 XMLHttpRequest 将该请求参数提交至服务器端脚本,例如 Servlet 或 JSP 页面。调用的 Servlet/JSP 将发回一个响应,其中包含了一般用于不需刷新整个页面即可更新用户

154

在MATLAB和Simulink中设计并仿真一个电动汽车整车动力学模型与控制系统

电动汽车(EV, Electric Vehicle)的动力学建模与控制仿真在车辆开发过程中起着至关重要的作用。通过Simulink进行整车动力学模型的构建和控制策略的验证,可以有效评估车辆性能、优化系统设计并降低开发成本。以下是如何在MATLAB和Simulink中设计并仿真一个电动汽车整车动力学模型与控制系统的详细步骤。通过上述步骤,我们成功设计并实现了基于Simulink的电动汽车整车动力学模型与控制仿真。该系统能够模拟复杂的整车动力学行为,验证控制策略的有效性,并通过优化设计提高车辆的性能和可靠性。

xiaoheshang_123的博客 550

Ajax 应用程序中实现数据交换(转)

在 Ajax 应用程序中实现数据交换

Frank走在JAVA旅途 743

倾斜摄影与地面激光点云融合高精度建模研究

本文研究了倾斜摄影与地面激光点云融合精细化建模技术,并通过相应的源代码实现了建模过程。该方法将倾斜摄影和激光扫描相结合,能够获得高精度的三维建模结果,为相关领域的研究和应用提供了有力支持。近年来,倾斜摄影和激光扫描技术的快速发展为高精度三维建模提供了新的机遇和挑战。本文针对倾斜摄影与地面激光点云融合建模这一前沿领域展开研究,旨在通过相应的源代码实现精细化的建模过程。同时,使用激光扫描仪进行地面激光扫描,获取地面的点云数据。经过数据融合和精细化建模处理后,我们获得了高精度的三维建模结果。

LpmShell的博客 1248

【Envi风暴】Envi5.6安装图文教程(附Envi5.6完整版下载)

【Envi风暴】Envi5.6与应用商店app store安装图文教程(附Envi5.6完整版下载)从文末网盘下载完整的ENVI5.6安装包,如下所示:双击envi56-win.exe,开始安装。将f__x64下的两个补丁文件拷贝到安装路径。将f__x86下的两个补丁文件拷贝到安装路径。

智慧空间实验室 9210

java ee 5周 ajax

AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。Ajax的概念由杰西·詹姆士·贾瑞特所提出。 传统的Web应用允许用户端填写表单(form),当提交表单时就向网页服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中...

weixin_33757911的博客 62

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

ajax原生详解,js原生Ajax的封装和原理详解

原理及概念AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是一种用于创建快速动态网页的技术。动态网页:是指可以通过服务器语言结合数据库随时修改数据的网页。静态网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了——除非你修改页面代码。AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。AJ...

weixin_39873177的博客 250

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

在Ajax 应用程序中实现数据交换

在Ajax 应用程序中实现数据交换

hfdhjjj的博客 190

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

在 Ajax 应用程序中实现数据交换

作者:Andrei Cioroianu 了解如何利用 XML 和 JavaScript Object Notation 在 Ajax 客户端和 Java 服务器之间传输数据。2006 年 6 月发表 Ajax 核心 API(即所谓的 XMLHttpRequest)的唯一用途就是发送 HTTP 请求,在 Web 浏览器与服务器之间进行数据交换。Web 页面中运行的 JavaScrip

gispower的专栏 685

Ajax介绍以及工作原理和实现详解(JS实现Ajax 和 JQ实现Ajax)

注重版权,转载请注明原作者和原文链接 作者:码农BookSea 原文链接:https://editor.youkuaiyun.com/md?articleId=106881795 1.认识Ajax Ajax = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。 Ajax 不是新的编程语言,而是一种使用现有标准的新方法。 Ajax 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下,说的简单点就是Ajax可以实现局部刷新。(如百度地.

BookSea的博客 7044

【Java】数据交换 Json 和 异步请求 Ajax

Json是一种数据格式,用于表示数据,而Ajax是一种实现异步通信的技术。它们的结合可以帮助开发人员构建高效、流畅的Web应用。

dandelionl_的博客 4106

Servlet和AJAX实现不跳转页面交换数据

前言:今天写了一个简单的作业题答案搜索的网站,后端用的Servlet与mysql进行查询,然后将数据通过request.getRequestDispatcher(url).forward(request, response)实现数据交互,但是问题来了。 如果我用前端jsp的话无法实现在提交表单后不跳转或者无痕迹的情况下将答案显示出来,那么怎么办呢? 通过百度我找到了一个方法:用ajax实现前端...

江冷易水寒 1829

简述Ajax原理及实现步骤

简述Ajax原理及实现步骤 Ajax 1、Ajax简介 概念 Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML)。 现在允许浏览器与务器通信而无须刷新当前页面的技术到叫做ajax。 Ajax:一种不用刷新整个页面便可与服务器通讯的办法。 应用 1.运用XHTML+CSS来表达信息; 2.运用JavaScript操作D...

lrhaoya 8532
上一篇: appistry公司的soa之路
下一篇: 中组部副部长:党风正则干群和 干群和则社会和
Labber
博客等级 码龄19年 26粉丝 1976原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值