Ajax コア API (いわゆる XMLHttpRequest) の唯一の目的は、HTTP リクエストを送信して Web ブラウザとサーバーの間でデータを交換することです。 Web ページで実行される JavaScript コードは、XMLHttpRequest を使用して、サーブレットや JSP ページなどのサーバー側スクリプトにリクエスト パラメータを送信できます。呼び出し側のサーブレット/JSP は、ページ全体を更新せずにユーザーのビューを更新するために通常使用されるデータを含む応答を送り返します。このアプローチでは、ネットワーク トラフィックが削減され、Web UI がデスクトップ GUI とほぼ同じように使用できるため、パフォーマンスと使いやすさの点で独自の利点が得られます。
ただし、このようなユーザー インターフェイスの開発は簡単ではありません。クライアント側では JavaScript を使用し、サーバー側では Java (または同等の言語) を使用して、データ交換、検証、および処理を実装する必要があります。ただし、得られるメリットを考慮すると、多くの場合、Ajax ベースのインターフェイスを構築するための追加の労力は価値があります。
この記事では、Ajax クライアントとサーバー間でデータを転送するための主な方法の 1 つを紹介し、従来の Web アプリケーション モデルと Ajax モデルの違いを比較します。さらに、この記事ではサーバー側とクライアント側でデータを処理する手法についても説明します。
まず、JavaScript を使用してクライアント側でリクエスト オブジェクトのパラメーターをエンコードする方法を学びます。いわゆる URL エンコード (Web ブラウザで使用されるデフォルトのエンコード) を使用することも、XML ドキュメントにリクエスト パラメータを含めることもできます。サーバーはリクエストを処理し、データをエンコードする必要があるレスポンスを返します。この記事では、主要な応答データ形式オプションである JavaScript Object Notation (JSON) と XML について説明します。
この記事のほとんどは、Ajax アプリケーションで一般的に使用される XML 関連の API に焦点を当てます。クライアント側では、XML API は非常に制限されていますが、十分です。ほとんどの場合、必要な操作はすべて XMLHttpRequest を使用して実行できます。さらに、JavaScript を使用して XML ドキュメントを解析し、Web ブラウザで DOM ツリーをシリアル化することもできます。サーバー側には、XML ドキュメントの処理に使用できる API とフレームワークが多数あります。この記事では、XML スキーマ、XPath、DOM、およびその他の多くの標準をサポートする、XML 用の標準 Java API を使用して基本的なタスクを実行する方法について説明します。
この記事を通じて、Ajax アプリケーションでのデータ交換のための最良のテクニックと最新の API について学ぶことができます。関連するサンプル コードは、util、model、feed の 3 つのパッケージに含まれています。 util パッケージのクラスは、XML 解析、スキーマベースの検証、XPath ベースのクエリ、DOM シリアル化、および JSON エンコードのメソッドを提供します。モデル パッケージには、XML ドキュメントから初期化して JSON 形式に変換できるサンプル データ モデルが含まれています。モデル ディレクトリには、XML 検証に使用できるスキーマの例もあります。フィード パッケージ内のクラスを使用して、5 秒ごとに Ajax 経由で情報を取得して Web ページを更新するデータ フィードをシミュレートできます。この記事では、未処理の Ajax リクエストを終了し、使い終わった XMLHttpRequest オブジェクトを削除することで、Web ブラウザでのメモリ リークを回避する方法について説明します。
JSP および JavaScript のサンプルは Web ディレクトリに含まれています。 ajaxUtil.js には、Ajax リクエストの送信、リクエストの終了、HTTP エラーの処理のためのユーティリティ関数が含まれています。このファイルは、XML および URL エンコード、XML 解析、DOM シリアル化のための JavaScript ユーティリティも提供します。 ajaxCtrl.jsp ファイルは Ajax コントローラーとして機能し、各 Ajax 要求を受信し、パラメーターをデータ モデルに転送するか、処理を提供してから、Ajax 応答を返します。残りの Web ファイルは、この実用的な方法の使用方法を示す例です。
クライアント側で
データを Web サーバーに送信するリクエストを作成する最も簡単な方法は、リクエストをクエリ文字列としてエンコードすることです。クエリ文字列は、使用する HTTP メソッドに応じて URL に追加するか、リクエスト本文に含めることができます。複雑なデータ構造を送信する必要がある場合、より良い解決策は、情報を XML ドキュメントにエンコードすることです。このセクションでは両方の方法について説明します。
リクエストパラメータをエンコードします。従来の Web アプリケーションを開発する場合、ユーザーがデータを送信すると Web ブラウザーが自動的にエンコードを行うため、フォーム データのエンコードについて心配する必要はありません。ただし、Ajax アプリケーションでは、リクエスト パラメーターを自分でエンコードする必要があります。 JavaScript には、URL の一部にできない文字を %HH (HH は 16 進コード) で置き換える非常に便利な関数エスケープ() が用意されています。たとえば、空白文字はすべて %20 に置き換えられます。
サンプル コードのダウンロードでは、ユーティリティ関数 buildQueryString() が提供されています。この関数は、配列から取得したパラメータを連結し、各パラメータの名前と値を = で区切って、各名前と値のペアの間に & 文字を配置します
。
var クエリ = "";
for (var i = 0; i < params.length; i++) {
クエリ += (i > 0 ? "&" : "")
+ エスケープ(params[i].name) + "=
+ エスケープ(params[i].value);
}
クエリを返す;
}
次のパラメータをエンコードするとします。
var someParams = [
{ 名前: "名前"、値: "ジョン・スミス" },
{ 名前: "電子メール"、値: " [email protected] " }、
{ 名前:「電話」、値: 「(123) 456 7890」 }
];
buildQueryString(someParams) を呼び出すと、
[email protected]&phone=%28123%29%20456%207890 を含む結果が生成されます。
GET メソッドを使用する場合は、URL の ? 文字の後にクエリを追加する必要があります。 POST を使用する場合、Content-Type ヘッダーは setRequestHeader() を介して application/x-www-form-urlencoded に設定する必要があり、クエリ文字列を XMLHttpRequest の send() メソッドに渡す必要があります。このメソッドは HTTP リクエストを XMLHttpRequest に送信します。サーバ。
XMLドキュメントを作成します。文字列を使用して属性とデータから要素を構築することは、JavaScript で XML ドキュメントを作成する最も簡単な方法です。この解決策を採用する場合、&、<、>、"、および文字をエスケープするためのユーティリティ メソッドが必要になります。
functionscapeXML(content) {
if (内容 == 未定義)
戻る "";
if (!content.length || !content.charAt)
content = 新しい文字列(コンテンツ);
var 結果 = "";
var length = content.length;
for (var i = 0; i < length; i++) {
var ch = content.charAt(i);
スイッチ(ch) {
場合 &:
結果 += "&";
壊す;
場合<:
結果 += "< ";
壊す;
ケース >:
結果 += ">";
壊す;
場合 ":
結果 += """;
壊す;
場合 \:
結果 += "'";
壊す;
デフォルト:
結果 += ch;
}
}
結果を返します。
}
タスクを簡素化するには、次のような追加のユーティリティ メソッドが必要です。
functionattribute(name, value) {
return " " + 名前 + "="" +scapeXML(値) + """;
}
次の例では、symbol、shares、paidPrice の 3 つのプロパティを持つオブジェクトの配列から XML ドキュメントを構築します
。
var xml = "<ポートフォリオ>";
for (var i = 0; i <stocks.length; i++) {
var 株式 = 株式[i];
xml += "< 在庫 ";
xml += 属性("シンボル", Stock.symbol);
xml += 属性("株式",stock.shares);
xml += 属性("paidPrice",stock.paidPrice);
xml += "";
}
xml += "< /ポートフォリオ>";
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 という 2 つの API も提供されています。 DOMParser API には、parseFromStream() メソッドと parseFromString() メソッドが含まれています。 XMLSerializer クラスには、DOM ツリーをシリアル化するための対応するメソッド、serializeToStream() および SerializeToString() があります。
次の関数は XML 文字列を解析し、DOM ドキュメントを返します。
function parse(xml) {
ヴァルドム。
試す{
dom = 新しい ActiveXObject("Microsoft.XMLDOM");
dom.async = false;
dom.loadXML(xml);
} キャッチ (エラー) {
試す{
var parser = 新しい DOMParser();
dom = parser.parseFromString(xml, "text/xml");
パーサーを削除します。
} キャッチ (エラー 2) {
if(デバッグ)
alert("XML 解析はサポートされていません。");
}
}
ドムを返します。
}
2 番目の関数は、DOM ノードとそのすべての子ノードをシリアル化し、XML を文字列として返します
。
var xml = dom.xml;
if (xml == 未定義) {
試す{
varserializer = new XMLSerializer();
xml = シリアライザー.serializeToString(dom);
シリアライザーを削除します。
} キャッチ (エラー) {
if(デバッグ)
alert("DOM シリアル化はサポートされていません。");
}
}
XML を返します。
}
XMLHttpRequest をパーサーまたはシリアライザーとして使用することもできます。 Ajax リクエストに対する応答をサーバーから受信すると、その応答は自動的に解析されます。テキスト バージョンと DOM ツリーには、それぞれ XMLHttpRequest の responseText プロパティと responseXML プロパティを通じてアクセスできます。さらに、DOM ツリーは send() メソッドに渡されるときに自動的にシリアル化されます。
リクエストを送信します。前回の記事では、XMLHttpRequest API とユーティリティ関数 sendHttpRequest() を紹介しました。これらは、ダウンロード用に提供されているサンプルの ajaxUtil.js ファイルにあります。この関数は 4 つのパラメーター (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
関数 sendInfoRequest(シンボル、コールバック) {
if(フィードリクエスト)
abortRequest(feedRequest);
var params = 新しい Array();
for (var i = 0; i < シンボル.長さ; i++)
params[i] = {
名前:「シンボル」、
値:シンボル[i]
};
feedRequest = sendHttpRequest(
"GET"、ctrlURL、params、コールバック);
}
リクエスト オブジェクトの abort() メソッドを呼び出す前に、abortRequest() 関数 (ajaxUtil.js ファイルにあります) は、onreadystatechange プロパティを何も行わないコールバックに設定します。さらに、メモリ リークを避けるためにリクエスト オブジェクトを削除することが重要です。
function abortRequest(request) {
関数 doNothing() {
}
request.onreadystatechange = 何もしません;
request.abort();
feedRequest を削除します。
}
別のケースを考えてみましょう。データベースに保存するユーザー データ全体を転送する場合、このデータの保存中にユーザーがデータを変更することは望ましくないため、リクエストは同期的に送信される必要があります。この場合、多くの場合、多くの文字列パラメータを使用するよりもドキュメント内のオブジェクト モデルをエンコードする方が簡単であるため、XML 形式が推奨されます。さらに、データの保存要求はまれであり、サーバーは問題なく負荷を処理します。 XML ドキュメントはパラメータとしてエンコードできるため、EL 構文 (${param.xml}) を使用して JSP ページでアクセスできます。 XML ドキュメントでエンコードされたモデル データを送信する関数は次のとおりです。
function sendSaveRequest(xml) {
var params = [ { 名前:"xml", 値:xml } ];
var saveRequest = sendHttpRequest("POST", ctrlURL, params);
if(保存リクエスト)
saveRequest を削除します。
}
オブジェクト モデルを復元する必要がある場合は、リクエストを同期的に送信してサーバーからデータを取得することもできます。
function sendLoadRequest() {
を使用して JSON 応答を JavaScript オブジェクト ツリーに簡単に変換できるように、サーバーは JSON 応答を返す必要があります。
var モデル = null;
varloadRequest = sendHttpRequest("GET", ctrlURL);
if (loadRequest) {
モデル = eval(loadRequest.responseText);
ロードリクエストを削除します。
}
モデルを返します。
}
次の 2 つのセクションでは、サーバー上の XML ドキュメントに対して通常実行される操作と、Ajax リクエストに応答する方法について説明します。
サーバー側でのリクエストの処理
サーブレット/JSP コンテナは各 HTTP リクエストを分析し、ServletRequest インスタンスを作成します。これにより、getParameter() / getParameterValues() を通じてリクエスト パラメータを取得したり、getInputStream() を通じてリクエスト本文を取得したりできます。 JSP ページでは、これらのパラメータは EL 構文 (${param...} および ${paramValues...}) を使用して取得することもできます。 getParameter を渡すことができるのは、Ajax クライアントが buildQueryString() などのユーティリティ関数を使用してデータを application/x-www-form-urlencoded 形式 (この記事の前のセクションで説明) または $ にエンコードした場合にのみ可能であることに注意してください。 {param...} リクエストパラメータを取得します。 XML ドキュメントまたは DOM ツリーをクライアント側の XMLHttpRequest の send() メソッドに渡す場合は、サーバー側で ServletRequest の getInputStream() メソッドを使用する必要があります。
データの検証。一般的な Web アプリケーションは、多くのデータ検証操作を実行します。考えられるエラーのほとんどは、リクエスト パラメータの欠落、数値形式の誤りなど、非常に単純なものです。これらのエラーは通常、ユーザーがフォーム要素の値を入力し忘れたか、無効な値を指定したことが原因で発生します。 JSFやOracle ADF FacesなどのWebフレームワークは、これらのユーザー・エラーの処理に非常に優れています。 Ajax アプリケーションでは、JavaScript を使用してクライアント側でこれらのエラーを捕捉して処理できます。たとえば、isNaN(new Number(value)) を使用すると、数値が無効であることを確認できます。
セキュリティと信頼性の理由から、データはサーバー側で再検証される必要があり、XML リクエストが適切にフォーマットされていると想定すべきではありません。 XML スキーマは、サーバー側で複雑なリクエストを検証するための便利なツールです。サンプル コードのダウンロードには、スキーマ ドキュメントをロードして使用するためのメソッドを提供する XMLUtil というクラスが含まれています。次のコード スニペットは、SchemaFactory を初期化する方法を示しています
。
インポート javax.xml.validation.*;
...
保護された静的 SchemaFactory スキーマファクトリー;
静的 {
schemaFactory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setErrorHandler(newErrorHandler());
newErrorHandler() メソッドは、SAX エラー ハンドラーを返し
ます
。
...
public static ErrorHandler newErrorHandler() {
新しい ErrorHandler() を返す {
public void warning(SAXParseException e)
SAXException をスローします {
Logger.global.warning(e.getMessage());
パブリック
無効エラー(SAXParseException e)
SAXException をスローします {
eを投げます。
public void fatError(SAXParseException e
)
SAXException をスローします {
eを投げます。
}
};
}
getResourceAsStream() を使用すると、CLASSPATH で指定されたディレクトリまたは JAR 内の XSD ファイルを検索してロードできます。
public static InputStream getResourceAsStream(String name)
IOException をスローします {
InputStream in = XMLUtil.class.getResourceAsStream(name);
if (in == null)
新しい FileNotFoundException(名前) をスローします。
戻ってください。
}
次に、SchemaFactory インスタンスを使用して、 newSchema() メソッドを通じて Schema オブジェクトを
取得します。
...
public static スキーマ newSchema(文字列名)
IOException、SAXExceptionをスローします{
スキーマ スキーマ。
入力ストリーム = getResourceAsStream(name);
試す{
スキーマ = schemaFactory.newSchema(new StreamSource(in));
}ついに{
in.close();
}
スキーマを返します。
import oracle.xml.parser.schema.XMLSchema;
を使用して、Oracle XMLSchema オブジェクトを作成することもできます
。
oracle.xml.parser.schema.XSDBuilder をインポートします。
...
public static XMLSchema newOracleSchema(文字列名)
IOException、SAXExceptionをスローします{
XMLSchema スキーマ。
入力ストリーム = getResourceAsStream(name);
試す{
XSDBuilder ビルダー = new XSDBuilder();
スキーマ = builder.build(新しい入力ソース(in));
} catch (例外 e){
新しい SAXException(e) をスローします。
}ついに{
in.close();
}
スキーマを返します。
}
次に、DocumentBuilderFactory を作成する必要があります。 JAXP 1.1 実装が CLASSPATH で見つかった場合、JAXP 1.2 で定義された setSchema() メソッドは UnsupportedOperationException をスローする可能性があります。その場合、JAXP 1.1 実装を Java SE 5.0 の JAXP 1.2 実装に置き換える必要があります。この場合でも、 newOracleSchema() を使用してスキーマ オブジェクトを作成し、 setAttribute() メソッドでそれを設定できます
。
oracle.xml.jaxp.JXDocumentBuilderFactoryをインポートします。
...
public static DocumentBuilderFactory newParserFactory(
String schemaName) throws IOException、SAXException {
DocumentBuilderFactory パーサーファクトリー
= DocumentBuilderFactory.newInstance();
試す{
parserFactory.setSchema(newSchema(スキーマ名));
} catch (UnsupportedOperationException e) {
if (JXDocumentBuilderFactory の parserFactory インスタンス) {
parserFactory.setAttribute(
JXDocumentBuilderFactory.SCHEMA_OBJECT、
newOracleSchema(スキーマ名));
}
}
parserFactory を返します。
}
次に、DocumentBuilder オブジェクトを作成し、それを使用して XML ドキュメントを検証および解析します
。
...
public static DocumentBuilder newParser(
DocumentBuilderFactory パーサーファクトリー)
ParserConfigurationException をスローします {
DocumentBuilder パーサー = parserFactory.newDocumentBuilder();
parser.setErrorHandler(newErrorHandler());
パーサーを返します。
};
XML ドキュメントを、portfolio.xsd スキーマの例に対して検証するとします。
< xsd:schema xmlns:xsd=" http://www.w3.org/2001/XMLSchema ">
< xsd:element name="portfolio" type ="ポートフォリオタイプ "
< xsd:complexType name="ポートフォリオタイプ">
<xsd:シーケンス>
< xsd:要素名="ストック"
minOccurs="0" maxOccurs="無制限">
<xsd:complexType>
< xsd:属性名="シンボル"
type="xsd:string" use="required"/>
< xsd:属性名="共有"
type="xsd:positiveInteger" use="required"/>
<XSD:属性name = "paidprice"
type = "xsd:decimal" use = "必須"/>
< /xsd:complexType>
< /xsd:要素>
< /xsd:シーケンス>
< /xsd:complextype>
< /xsd:schema>
DataModel クラスの parsePortfolioDoc() メソッドは、XMLUtil を使用して XML パラメーターを検証および解析し、DOM ドキュメントを返します:
private static Final String SCHEMA_NAME
= "/ajaxapp/model/portfolio.xsd";
private static DocumentBuilderFactory parserFactory;
プライベート静的ドキュメントparsePortfolioDoc(String xml)
IOException、saxexception、
ParserConfigurationException {
同期化 (DataModel.class) {
if (parserFactory == null)
parserFactory = XMLUtil.newParserFactory(SCHEMA_NAME);
}
DocumentBuilder パーサー = XMLUtil.newParser(parserFactory);
入力ソース = 新しい入力ソース(新しい StringReader(xml));
parser.parse(in) を返します。
}
DOM ツリーを作成したので、DOM ノードを形成するために必要なデータを取得する必要があります。
必要な情報を抽出します。 DOM API またはクエリ言語 (XQuery や XPath など) を使用して、DOM ツリーを参照できます。 Java は XPath 用の標準 API を提供しており、これは後で使用されます。 XMLUtil クラスは、 newXPath() メソッドを
使用して XPathFactory を作成します。
...
保護された静的 XPathFactory xpathFactory;
静的 {
xpathFactory = XPathFactory.newInstance();
}
パブリック静的 XPath newXPath() {
xpathFactory.newXPath() を返します。
}
次のメソッドは、特定のコンテキストで XPath 式を評価し、結果の値を返します
。
org.w3c.dom.* をインポートします。
...
public static String evalToString(文字列式,
オブジェクト コンテキスト) XPathExpressionException をスローする {
return (String) newXPath().evaluate(式, コンテキスト,
XPathConstants.STRING);
}
public static boolean evalToBoolean(文字列式,
オブジェクト コンテキスト) XPathExpressionException をスローする {
return ((Boolean) newXPath().evaluate(式, コンテキスト,
XPathConstants.BOOLEAN)).booleanValue();
}
public static double evalToNumber(文字列式,
オブジェクト コンテキスト) XPathExpressionException をスローする {
return ((Double) newXPath().evaluate(式, コンテキスト,
XPathConstants.NUMBER)).doubleValue();
}
public static Node evalToNode(文字列式,
オブジェクト コンテキスト) XPathExpressionException をスローする {
return(node)newxpath()。evaluate(expression、context、
XPathConstants.NODE);
}
public static NodeList evalToNodeList(文字列式,
オブジェクト コンテキスト) XPathExpressionException をスローする {
return (NodeList) newXPath().evaluate(式, コンテキスト,
XPathConstants.NODESET);
DataModel の setData() メソッドは、XPath ソルバー メソッドを使用して、結合された XML ドキュメントから情報を抽出します。
public
synchronized void setData(String xml)
IOException、SAXException、をスローします。
パーサー構成例外、
XPathExpressionException {
試す{
ArrayListストックリスト
= 新しい ArrayList();
ドキュメント doc = parsePortfolioDoc(xml);
NodeList ノードリスト = XMLUtil.evalToNodeList(
"/portfolio/stock"、ドキュメント);
for (int i = 0; i < nodeList.getLength(); i++) {
node node = nodeList.item(i);
StockBean 在庫 = 新しい StockBean();
Stock.setSymbol(
XMLUtil.evalToString("@symbol", ノード));
Stock.setShares(
(int) XMLUtil.evalToNumber("@shares", ノード));
Stock.setPaidPrice(
XMLUtil.evalToNumber("@paidPrice", ノード));
在庫リスト.add(在庫);
}
this.stockList = 在庫リスト;
} catch (例外 e){
Logger.global.logp(Level.SEVERE, "DataModel", "setData",
e.getMessage(), e);
}
}
データがサーバー側のデータ モデルで利用可能になると、アプリケーションの要件に従って処理できます。次に、Ajax リクエストに応答する必要があります。
サーバー側での応答の生成
Ajax リクエストへの応答として HTML を返すのが最も簡単な解決策です。これは、JSP 構文を使用してマークアップを構築でき、Ajax クライアントは単に <div> または <span> 要素を使用するためです。 innerHTML プロパティは HTML を挿入します。ページのどこかに。ただし、プレゼンテーション マークアップを使用せずにデータを Ajax クライアントに返す方が効率的です。 XML 形式または JSON を使用できます。
XML 応答を生成します。 Java EE には、JSP 経由で生成、JAXB 経由でオブジェクト ツリーから作成、または javax.xml.transform を使用して生成など、XML ドキュメントを作成するための多くのオプションが用意されています。次の例のトランスフォーマーは DOM ツリーをシリアル化します
。
インポート javax.xml.transform.dom.*;
インポート javax.xml.transform.stream.*;
...
パブリック静的TransformerFactoryシリアライザーFctory;
静的 {
SerializerFctory = TransformerFactory.newInstance();
}
public static void Serialize(ノードノード、OutputStream out)
TransformerException {をスローします
Transformer serializer = serializerfctory.newtransformer();
プロパティserializerProps = new Properties();
SerializerProps.put(OutputKeys.METHOD, "xml");
Serializer.setOutputProperties(serializerProps);
ソース ソース = 新しい DOMSource(ノード);
結果 result = new StreamResult(out);
シリアライザー.transform(ソース, 結果);
}
サーバー側で XML を生成するための標準オプションと開発ソース フレームワークは多数あるため、必要なのは、自分に合ったものを選択することだけです。ただし、クライアントでは、XML は DOM を使用してのみ解析できるため、状況は大きく異なります。一部のブラウザは XPath と XSLT もサポートしています。
これまでの Ajax 記事では、JSP 経由で XML を生成し、それをクライアント上で JavaScript と DOM を使用して解析する方法を学びました。もう 1 つの解決策は、Ajax リクエストに応答するデータ形式として XML の代わりに JSON を使用することです。前述したように、JSON 文字列は eval() 関数を使用して JavaScript オブジェクト ツリーに変換できます。これは、JavaScript を使用して DOM ツリーから情報を抽出するよりも簡単です。必要なのは、サーバー側で JSON を生成する優れたユーティリティ クラスだけです。
JSONエンコーディング。 JSONEncoder クラスは、リテラル、オブジェクト、配列をエンコードするためのメソッドを提供します。結果は java.lang.StringBuilder に保存され
ます
。
プライベートStringBuilder Buf;
public JSONEncoder() {
buf = 新しい StringBuilder();
}
...
}
Character() メソッドは単一の文字をエンコードします。
public void Character(char ch) {
スイッチ(ch) {
場合 \:
場合 \":
場合\ :
buf.append( \ );
buf.append(ch);
壊す;
場合 :
buf.append( \ );
buf.append();
壊す;
場合
:
buf.append( \ );
buf.append(
);
壊す;
場合
:
buf.append( \ );
buf.append(
);
壊す;
デフォルト:
if (ch >= 32 && ch < 128)
buf.append(ch);
それ以外{
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 長 = str.length();
for (int i = 0; i < 長さ; i++)
文字(str.charAt(i));
literal
() メソッドは JavaScript リテラルをエンコードします:
public void literal(Object value) {
if (文字列の値インスタンス) {
buf.append(");
string((string)value);
buf.append( ");
} else if (文字のインスタンスの値) {
buf.append(\);
文字(((文字)値).charValue());
buf.append(\);
} それ以外
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(名前);
buf.append(:);
リテラル(値);
コンマ();
}
endObject() メソッドは、JavaScript オブジェクトの終わりを示すために } 文字を追加します。
public void endObject() {
deleteLastComma();
buf.append(});
コンマ();
、
JavaScript 配列の始まりを示す [ 文字を追加します。
public void startArray() {
buf.append([);
}
element() メソッドは、JavaScript 配列の要素をエンコードします。
public void element(Object value) {
リテラル(値);
コンマ();
}
(
)メソッドAPEDS A]文字は、JavaScriptアレイの終了を示しています。
deleteLastComma();
buf.append(]);
コンマ();
}
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 在庫 = StockList.get(i);
json.startobject();
json.property("シンボル", Stock.getSymbol());
json.property("株式",stock.getShares());
json.property("paidPrice",stock.getPaidPrice());
json.endObject();
}
json.endArray();
json.toString() を返します。
場合
、ajaxCtrl.jsp ページでモデルのデータが設定されます。それ以外の場合、ページは ${dataModel.data} EL 式を使用して、getData() によって返される JSON 文字列を出力します:
< %@ taglib prefix="c" uri=" http://java.sun.com/jsp/ jstl /core " %>
...
< jsp:useBean id="データモデル" スコープ="セッション"
class="ajaxapp.model.DataModel" />
< c:choose>
...
< c:when test="${!empty param.xml}">
< c:set target="${dataModel}"
プロパティ = "データ"
値="${param.xml}" />
< /c:いつ>
<c:その他>
${dataModel.data}
< /c:そうでない場合>
< /c:選択>
AJAXクライアントはJSONデータを処理する必要があるため、このジョブは完全ではありません。
クライアント側での応答の処理
典型的なWebアプリケーションでは、JSP、Webフレームワーク、タグライブラリを使用してサーバー側にコンテンツを生成します。 JavaServer FacesやOracle ADF FacesなどのWebフレームワークはAjaxアプリケーションの構築に非常に役立つため、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);
parse() 関数のコードは ajaxUtil.js にあります。この場合、関数はルート要素にテキスト ノード、その後にコメント、別のテキスト ノード、文字データ ノードが含まれる DOM ツリーを返します。コメントなしのテキストを含める場合は、要素の子要素を反復処理して、テキスト データ ノードと文字データ ノード (それぞれタイプ 3 と 4) の値を連結する必要があります
。
var childNodes = element.childNodes;
var text = "";
for (var i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeValue) {
var type = childNodes[i].nodeType;
if (タイプ == 3 || タイプ == 4)
テキスト += childNodes[i].nodeValue;
DOM
を操作するときは、これらの低レベルの詳細の処理を避けるために、ユーティリティ関数の小さなセットを構築する必要があります。
JavaScript を使用して動的コンテンツを生成します。 Web ブラウザを使用すると、ドキュメント オブジェクトを通じて Web ページの DOM 構造にアクセスできます。たとえば、document.getElementById(...)を使用して、要素を非常に簡単に見つけることができます。既存のドキュメントに挿入できる新しい要素やテキスト ノードを作成することもできます。
ただし、以下に示すように文字列を連結して HTMLを
構築する方が簡単です。
var 共有 = eval(request.responseText);
var table = "< table border=1 cellpadding=5>";
表 += "<tr>";
表 += "<th>シンボル< /th>";
テーブル += "< th>トレンド< /th>";
table += "< th>最終価格</ th>";
テーブル += "< /tr>";
for (var i = 0; i < share.length; i++) {
var share = shares [i];
var symbol = escapexml(share.symbol)
var trend = share.trend> 0: " - ";
var lastprice = new number(share.lastprice).tofixed(2);
表 += "<tr>";
表 + = "<td>" +記号 + "< /td>";
表 + = "<td>" + trend + "< /td>";
表 + = "<td>" + lastprice + "< /td>";
テーブル += "< /tr>";
}
表 += "< /table>";
document.getElementById( "table")。innerhtml = table;
}
生成されたHTMLは、getElementById()によって返されたオブジェクトの内側のHTMLプロパティを設定することにより、空の要素に挿入でき
ます
。
< /div>
この記事の例は、updateInfo()関数をコールバックとして使用して、ajaxlogic.jsファイルのsendinforequestを介してサーバーに送信されたajax要求への応答を処理します。 5秒ごとに情報を更新する場合は、JavaScriptのsetInterval()関数を使用できます
。
setInterval( "sendinforequest(symbols、updateinfo)"、5000);
DataFeedと呼ばれるクラスは、サーバー側のフィードをシミュレートします。 ajaxctrl.jspページは、フィードのgetData()メソッドを呼び出し、JSON文字列として応答を返します。クライアント側では、前のコード例に示すように、updateInfo()関数はeval(request.responsetext)を使用してjson文字列を解析します。