Satu-satunya tujuan API inti Ajax (disebut XMLHttpRequest) adalah mengirim permintaan HTTP untuk bertukar data antara browser Web dan server. Kode JavaScript yang berjalan di halaman Web dapat menggunakan XMLHttpRequest untuk mengirimkan parameter permintaan ke skrip sisi server, seperti halaman Servlet atau JSP. Servlet/JSP yang memanggil akan mengirimkan kembali respons yang berisi data yang biasanya digunakan untuk memperbarui tampilan pengguna tanpa menyegarkan seluruh halaman. Pendekatan ini menawarkan keuntungan unik dalam hal kinerja dan kegunaan karena lalu lintas jaringan berkurang dan UI Web hampir dapat digunakan seperti GUI desktop.
Namun, mengembangkan antarmuka pengguna seperti itu tidaklah mudah, karena Anda harus menerapkan pertukaran data, validasi, dan pemrosesan menggunakan JavaScript di sisi klien dan Java (atau bahasa yang setara) di sisi server. Namun, dalam banyak kasus, upaya ekstra untuk membangun antarmuka berbasis Ajax tidak sia-sia, mengingat manfaat yang akan diperoleh.
Pada artikel ini, saya akan memperkenalkan salah satu metode utama untuk mentransfer data antara klien dan server Ajax, dan membandingkan perbedaan antara model aplikasi Web tradisional dan model Ajax. Selain itu, artikel ini juga akan mengupas teknik pengolahan data pada sisi server dan sisi klien.
Pertama, Anda akan mempelajari cara menggunakan JavaScript untuk menyandikan parameter objek permintaan di sisi klien. Anda dapat menggunakan apa yang disebut pengkodean URL (pengkodean default yang digunakan oleh browser web), atau Anda dapat memasukkan parameter permintaan dalam dokumen XML. Server akan memproses permintaan dan mengembalikan respons yang datanya juga harus dikodekan. Artikel ini membahas Notasi Objek JavaScript (JSON) dan XML, yang merupakan opsi format data respons utama.
Sebagian besar artikel ini akan fokus pada API terkait XML yang biasa digunakan dalam aplikasi Ajax. Di sisi klien, XML API sangat terbatas namun cukup. Dalam kebanyakan kasus, semua operasi yang diperlukan dapat diselesaikan menggunakan XMLHttpRequest. Selain itu, JavaScript dapat digunakan untuk mengurai dokumen XML dan membuat serial pohon DOM di browser Web. Di sisi server, ada banyak API dan framework yang tersedia untuk memproses dokumen XML. Artikel ini menjelaskan cara melakukan tugas dasar menggunakan Java API standar untuk XML, yang mendukung Skema XML, XPath, DOM, dan banyak standar lainnya.
Melalui artikel ini, Anda dapat mempelajari teknik terbaik dan API terbaru untuk pertukaran data di aplikasi Ajax. Kode contoh yang terlibat ada dalam tiga paket: util, model, dan feed. Kelas dalam paket util menyediakan metode untuk penguraian XML, validasi berbasis skema, kueri berbasis XPath, serialisasi DOM, dan pengkodean JSON. Paket model berisi contoh model data yang dapat diinisialisasi dari dokumen XML dan kemudian dikonversi ke format JSON. Ada juga contoh Skema di direktori model yang dapat digunakan untuk validasi XML. Kelas-kelas dalam paket feed dapat digunakan untuk mensimulasikan feed data, yang mengambil informasi melalui Ajax setiap 5 detik untuk menyegarkan halaman Web. Artikel ini menjelaskan cara menghindari kebocoran memori di browser Web Anda dengan menghentikan permintaan Ajax yang luar biasa dan menghapus objek XMLHttpRequest ketika Anda selesai menggunakannya.
Sampel JSP dan JavaScript disertakan dalam direktori web. ajaxUtil.js berisi fungsi utilitas untuk mengirim permintaan Ajax, mengakhiri permintaan, dan menangani kesalahan HTTP. File ini juga menyediakan utilitas JavaScript untuk pengkodean XML dan URL, penguraian XML, dan serialisasi DOM. File ajaxCtrl.jsp bertindak sebagai pengontrol Ajax, menerima setiap permintaan Ajax, meneruskan parameter ke model data, atau menyediakan pemrosesan, dan kemudian mengembalikan respons Ajax. File Web lainnya adalah contoh yang menunjukkan cara menggunakan metode praktis ini.
Cara paling sederhanauntuk membuat permintaan di sisi klien
untuk mengirim data ke server Web adalah dengan mengkodekan permintaan tersebut sebagai string kueri, yang dapat ditambahkan ke URL atau disertakan dalam badan permintaan, bergantung pada metode HTTP yang digunakan. Jika Anda perlu mengirim struktur data yang kompleks, solusi yang lebih baik adalah dengan menyandikan informasi dalam dokumen XML. Saya akan membahas kedua metode di bagian ini.
Enkode parameter permintaan. Saat mengembangkan aplikasi Web tradisional, Anda tidak perlu khawatir tentang pengkodean data formulir karena browser Web melakukan ini secara otomatis saat pengguna mengirimkan data. Namun, dalam aplikasi Ajax, Anda harus mengkodekan sendiri parameter permintaan. JavaScript menyediakan fungsi escape() yang sangat berguna, yang menggantikan karakter apa pun yang tidak dapat menjadi bagian dari URL dengan %HH (HH adalah kode heksadesimal). Misalnya, karakter spasi apa pun diganti dengan %20.
Pengunduhan kode contoh menyediakan fungsi utilitas, buildQueryString(), yang menggabungkan parameter yang diambil dari array, memisahkan nama dan nilai setiap parameter dengan = dan menempatkan karakter & di antara setiap pasangan nama-nilai :
function buildQueryString(params) {
var kueri = "";
for (var i = 0; i < params.length; i++) {
pertanyaan += (i > 0 ? "&" : "")
+ escape(params[i].nama) + "="
+ escape(params[i].nilai);
}
mengembalikan permintaan;
}
Misalkan Anda ingin menyandikan parameter berikut:
var someParams = [
{ nama: "nama", nilai: "John Smith" },
{ nama: "email", nilai: " [email protected] " },
{ nama:"telepon", nilai: "(123) 456 7890" }
];
Panggilan ke buildQueryString(someParams) akan menghasilkan hasil yang berisi:
name=John%20Smith&[email protected]&phone=%28123%29%20456%207890
Jika Anda ingin menggunakan metode GET, Anda harus menambahkan kueri ke URL setelah karakter ?. Saat menggunakan POST, header Tipe Konten harus disetel ke application/x-www-form-urlencoded melalui setRequestHeader(), dan string kueri harus diteruskan ke metode send() XMLHttpRequest, yang akan mengirimkan permintaan HTTP ke server.
Buat dokumen XML. Menggunakan string untuk membangun elemen dari atribut dan datanya adalah cara paling sederhana untuk membuat dokumen XML dengan JavaScript. Jika Anda mengadopsi solusi ini, Anda memerlukan metode utilitas untuk menghindari karakter &, <, >, ", dan:
function escapeXML(content) {
jika (konten == tidak ditentukan)
kembali "";
if (!konten.panjang || !konten.charAt)
konten = String baru(konten);
var hasil = "";
var panjang = konten.panjang;
untuk (var i = 0; i < panjang; i++) {
var ch = konten.charAt(i);
beralih (ch) {
kasus &:
hasil += "&";
merusak;
kasus < :
hasil += "< ";
merusak;
kasus >:
hasil += ">";
merusak;
kasus ":
hasil += """;
merusak;
kasus \:
hasil += "'";
merusak;
bawaan:
hasil += ch;
}
}
hasil pengembalian;
}
Untuk membuat tugas lebih sederhana, beberapa metode utilitas tambahan diperlukan, seperti:
function atribut(name, value) {
kembali " " + nama + "="" + escapeXML(nilai) + """;
}
Contoh berikut membuat dokumen XML dari array objek dengan tiga properti: simbol, share, dan dibayarPrice:
function buildPortfolioDoc(stocks) {
var xml = "<portofolio>";
for (var i = 0; i < stok.panjang; i++) {
var stok = stok[i];
xml += "< stok ";
xml += atribut("simbol", stok.simbol);
xml += atribut("berbagi", stok.berbagi);
xml += atribut("Harga berbayar", stok.Harga berbayar);
xml += "";
}
xml += "< /portofolio>";
kembalikan xml;
}
Jika Anda lebih suka bekerja dengan DOM, Anda dapat menggunakan API browser web Anda untuk mengurai XML dan membuat serialisasi pohon DOM. Dengan IE, Anda dapat membuat dokumen kosong dengan ActiveXObject("Microsoft.XMLDOM") baru. XML kemudian dapat diurai dari string atau URL menggunakan metode loadXML() atau load() masing-masing. Dalam kasus IE, setiap node memiliki atribut yang disebut xml yang memungkinkan Anda memperoleh representasi XML dari node dan semua node turunannya. Oleh karena itu, Anda dapat mengurai string XML, memodifikasi pohon DOM, dan kemudian membuat serial DOM kembali ke XML.
Browser Firefox dan Netscape memungkinkan Anda membuat dokumen kosong menggunakan document.implementation.createDocument(...). Node DOM kemudian dapat dibuat menggunakan createElement(), createTextNode(), createCDATASection(), dll. Browser Mozilla juga menyediakan dua API bernama DOMParser dan XMLSerializer. API DOMParser berisi metode parseFromStream() dan parseFromString(). Kelas XMLSerializer memiliki metode yang sesuai untuk membuat serialisasi pohon DOM: serializeToStream() dan serializeToString().
Fungsi berikut mem-parsing string XML dan mengembalikan dokumen DOM:
function parse(xml) {
var dom;
mencoba{
dom = new ActiveXObject("Microsoft.XMLDOM");
dom.async = salah;
dom.loadXML(xml);
} tangkapan (kesalahan) {
mencoba{
var parser = DOMParser baru();
dom = parser.parseFromString(xml, "teks/xml");
hapus pengurai;
} tangkapan (kesalahan2) {
jika (men-debug)
alert("Penguraian XML tidak didukung.");
}
}
kembalikan dom;
}
Fungsi kedua membuat serialisasi node DOM dan semua node turunannya, mengembalikan XML sebagai string:
function serialize(dom) {
var xml = dom.xml;
jika (xml == tidak terdefinisi) {
mencoba{
var serializer = XMLSerializer baru();
xml = serializer.serializeToString(dom);
hapus pembuat serial;
} tangkapan (kesalahan) {
jika (men-debug)
alert("Serialisasi DOM tidak didukung.");
}
}
kembalikan xml;
}
Anda juga dapat menggunakan XMLHttpRequest sebagai parser atau serializer. Setelah respons terhadap permintaan Ajax diterima dari server, respons tersebut secara otomatis diuraikan. Versi teks dan pohon DOM dapat diakses melalui properti responText dan responXML masing-masing dari XMLHttpRequest. Selain itu, pohon DOM secara otomatis diserialkan ketika diteruskan ke metode send().
Kirim permintaan. Pada artikel sebelumnya, saya memperkenalkan API XMLHttpRequest dan fungsi utilitas, sendHttpRequest(), yang dapat Anda temukan di file ajaxUtil.js dalam contoh yang disediakan untuk diunduh. Fungsi ini mengambil empat parameter (metode HTTP, URL, array parameter, dan callback), membuat objek XMLHttpRequest, menetapkan propertinya, dan memanggil metode send(). Jika parameter panggilan balik disediakan, permintaan dikirim secara asinkron dan fungsi panggilan balik dipanggil setelah respons diterima. Jika tidak, permintaan akan dikirim secara sinkron dan Anda dapat menangani responsnya segera setelah sendHttpRequest() kembali.
Seperti yang Anda lihat, Anda harus membuat beberapa pilihan penting saat menggunakan XMLHttpRequest
. Metode HTTP mana yang akan digunakan (GET atau POST)?
Format yang digunakan untuk mengkodekan parameter permintaan (pengkodean XML dan URL telah dibahas sebelumnya di artikel ini)
Apakah akan melakukan panggilan secara synchronous (menunggu respon) atau asynchronous (menggunakan callback) Format respon, seperti XML, XHTML, HTML, atau JavaScript Object Notation (JSON) (dibahas nanti di artikel ini). Katakanlah Anda ingin mendapatkan informasi harga saham dari data feed dan menyegarkan informasi tersebut secara berkala tanpa campur tangan pengguna. Dalam hal ini, permintaan HTTP harus dikirim secara asinkron sehingga antarmuka pengguna tidak diblokir saat informasi diambil. Parameter permintaan adalah serangkaian simbol yang dapat dikodekan dalam URL. Karena server mungkin kelebihan beban, Anda tidak ingin mengirim dokumen XML ketika permintaan sering dibuat. Karena Anda hanya tertarik pada harga saham terkini, semua permintaan sebelumnya yang belum terselesaikan harus dihentikan:
var ctrlURL = "ajaxCtrl.jsp";
var feedRequest = null;
function sendInfoRequest(simbol, panggilan balik) {
jika(Permintaan umpan)
batalkanRequest(feedRequest);
var params = Array baru();
for (var i = 0; i < simbol.panjang; i++)
params[i] = {
nama:"simbol",
nilai:simbol[i]
};
feedRequest = kirimHttpRequest(
"DAPATKAN", ctrlURL, params, panggilan balik);
}
Sebelum memanggil metode abort() objek permintaan, fungsi abortRequest() (ditemukan dalam file ajaxUtil.js) menyetel properti onreadystatechange ke callback yang tidak melakukan apa pun. Selain itu, sangat penting untuk menghapus objek permintaan untuk menghindari kebocoran memori:
function abortRequest(request) {
fungsi tidak melakukan apa-apa() {
}
request.onreadystatechange = tidak melakukan apa pun;
permintaan.batalkan();
hapus feedRequest;
}
Mari kita pertimbangkan kasus lain: saat mentransfer seluruh data pengguna untuk disimpan dalam database, permintaan harus dikirim secara sinkron karena Anda mungkin tidak ingin pengguna mengubahnya saat penyimpanan data ini sedang berlangsung. Dalam hal ini, format XML lebih disukai karena seringkali lebih mudah untuk menyandikan model objek dalam dokumen daripada menggunakan banyak parameter string. Selain itu, permintaan untuk menyimpan data jarang terjadi dan server menangani beban tanpa masalah. Dokumen XML dapat dikodekan sebagai parameter sehingga Anda dapat mengaksesnya di halaman JSP menggunakan sintaks EL (${param.xml}). Berikut adalah fungsi yang mengirimkan data model yang dikodekan dalam dokumen XML:
function sendSaveRequest(xml) {
var params = [ { nama:"xml", nilai:xml } ];
var saveRequest = sendHttpRequest("POST", ctrlURL, params);
jika (simpan Permintaan)
hapus simpanPermintaan;
}
Jika Anda perlu memulihkan model objek, Anda juga dapat mengirim permintaan secara sinkron untuk mengambil data dari server. Dalam hal ini, server harus mengembalikan respons JSON sehingga Anda dapat dengan mudah mengonversinya menjadi pohon objek JavaScript menggunakan eval(loadRequest.responseText):
function sendLoadRequest() {
var model = nol;
var loadRequest = sendHttpRequest("GET", ctrlURL);
jika (memuatPermintaan) {
model = eval(loadRequest.responseText);
hapus loadRequest;
}
model pengembalian;
}
Dua bagian berikut menjelaskan operasi yang biasanya dilakukan pada dokumen XML di server dan cara merespons permintaan Ajax.
Menangani permintaan di sisi server
Kontainer Servlet/JSP menganalisis setiap permintaan HTTP dan membuat instance ServletRequest, yang memungkinkan Anda mendapatkan parameter permintaan melalui getParameter() / getParameterValues() atau isi permintaan melalui getInputStream(). Di halaman JSP, parameter ini juga dapat diperoleh menggunakan sintaks EL (${param...} dan ${paramValues...}). Perhatikan bahwa meneruskan getParameter hanya mungkin jika klien Ajax menggunakan fungsi utilitas seperti buildQueryString() untuk menyandikan data dalam format application/x-www-form-urlencoded (dijelaskan di bagian sebelumnya artikel ini () atau $ {param...} untuk mendapatkan parameter permintaan. Jika Anda meneruskan dokumen XML atau pohon DOM ke metode send() XMLHttpRequest di sisi klien, Anda harus menggunakan metode getInputStream() dari ServletRequest di sisi server.
Validasi data. Aplikasi web pada umumnya melakukan banyak operasi validasi data. Sebagian besar kesalahan yang mungkin terjadi cukup sederhana, seperti parameter permintaan yang hilang, format angka yang salah, dan sebagainya. Kesalahan ini biasanya disebabkan oleh pengguna yang lupa memasukkan nilai untuk elemen formulir atau memberikan nilai yang tidak valid. Kerangka kerja web seperti JSF dan Oracle ADF Faces sangat baik dalam menangani kesalahan pengguna ini. Dalam aplikasi Ajax, kesalahan ini dapat ditangkap dan ditangani di sisi klien menggunakan JavaScript. Misalnya, Anda dapat menggunakan isNaN(new Number(value)) untuk memverifikasi bahwa nilai numerik tidak valid.
Untuk alasan keamanan dan keandalan, data harus divalidasi ulang di sisi server, dan permintaan XML tidak boleh dianggap berformat baik. Skema XML adalah alat yang berguna untuk memvalidasi permintaan kompleks di sisi server. Pengunduhan kode contoh menyertakan kelas bernama XMLUtil yang menyediakan metode untuk memuat dan menggunakan dokumen skema. Cuplikan kode berikut menunjukkan cara menginisialisasi SchemaFactory:
import javax.xml.*;
import javax.xml.validasi.*;
...
SchemaFactory statis yang dilindungi SchemaFactory;
statis {
SchemaFactory = SchemaFactory.newInstance(
XMLConstants.W3C_XML_SCHEMA_NS_URI);
skemaFactory.setErrorHandler(newErrorHandler());
}
Metode newErrorHandler() mengembalikan pengendali kesalahan SAX:
import org.xml.sax.*;
...
ErrorHandler statis publik newErrorHandler() {
kembalikan ErrorHandler baru() {
peringatan kekosongan publik (SAXParseException e)
melempar SAXException {
Logger.global.warning(e.getMessage());
}
kesalahan kekosongan publik (SAXParseException e)
melempar SAXException {
melempar e;
}
kekosongan publik fatalError(SAXParseException e)
melempar SAXException {
melempar e;
}
};
}
Anda dapat menggunakan getResourceAsStream() untuk menemukan dan memuat file XSD di direktori atau JAR yang ditentukan dalam CLASSPATH:
public static InputStream getResourceAsStream(String name)
melempar IOException {
InputStream di = XMLUtil.class.getResourceAsStream(nama);
jika (dalam == nol)
lempar FileNotFoundException(nama);
kembali;
}
Kemudian, gunakan instance SchemaFactory untuk mendapatkan objek Skema melalui metode newSchema():
import javax.xml.validation.*;
...
Skema statis publik skema baru (nama string)
melempar IOException, SAXException {
Skema skema;
InputStream di = getResourceAsStream(nama);
mencoba{
skema = skemaFactory.newSchema(StreamSource baru(dalam));
}Akhirnya{
melampirkan();
}
skema pengembalian;
}
Anda juga dapat membuat objek Oracle XMLSchema menggunakan:
import Oracle.xml.parser.schema.XMLSchema;
impor Oracle.xml.parser.schema.XSDBuilder;
...
XMLSchema statis publik newOracleSchema (Nama string)
melempar IOException, SAXException {
skema XMLSchema;
InputStream di = getResourceAsStream(nama);
mencoba{
Pembuat XSDBuilder = XSDBuilder baru();
skema = pembangun.build(InputSource baru(dalam));
} tangkapan (Pengecualian e){
lempar SAXException baru(e);
}Akhirnya{
melampirkan();
}
skema pengembalian;
}
Selanjutnya, Anda perlu membuat DocumentBuilderFactory. Jika implementasi JAXP 1.1 ditemukan di CLASSPATH, metode setSchema() yang ditentukan oleh JAXP 1.2 mungkin memunculkan UnsupportedOperationException, dalam hal ini implementasi JAXP 1.1 perlu diganti dengan implementasi JAXP 1.2 dari Java SE 5.0. Dalam hal ini, Anda masih dapat membuat objek skema menggunakan newOracleSchema() dan mengaturnya melalui metode setAttribute():
import javax.xml.parsers.*;
impor Oracle.xml.jaxp.JXDocumentBuilderFactory;
...
DocumentBuilderFactory statis publik newParserFactory(
String SchemaName) melempar IOException, SAXException {
ParserFactory DocumentBuilderFactory
= DocumentBuilderFactory.newInstance();
mencoba{
parserFactory.setSchema(newSchema(schemaName));
} tangkapan (UnsupportedOperationException e) {
if (parserFactory instance dari JXDocumentBuilderFactory) {
parserFactory.setAttribute(
JXDocumentBuilderFactory.SCHEMA_OBJECT,
newOracleSchema(namaskema));
}
}
kembalikan parserFactory;
}
Kemudian, buat objek DocumentBuilder dan gunakan untuk memvalidasi dan mengurai dokumen XML:
import javax.xml.parsers.*;
...
DocumentBuilder statis publik newParser(
ParserFactory DocumentBuilderFactory)
melempar ParserConfigurationException {
Pengurai DocumentBuilder = parserFactory.newDocumentBuilder();
parser.setErrorHandler(newErrorHandler());
kembalikan pengurai;
};
Misalkan Anda ingin memvalidasi dokumen XML terhadap skema portfolio.xsd contoh:
< xsd:schema xmlns:xsd=" http://www.w3.org/2001/XMLSchema ">
< xsd:element name="portfolio" type ="portfolioType "
< xsd:complexType nama="portfolioType">
<xsd:urutan>
< xsd: nama elemen = "stok"
minOccurs="0" maxOccurs="tidak terbatas">
<xsd:tipe kompleks>
< xsd: nama atribut = "simbol"
ketik = "xsd: string" gunakan = "diperlukan"/>
< xsd: nama atribut = "berbagi"
ketik = "xsd: PositiveInteger" gunakan = "wajib"/>
< xsd: nama atribut = "Harga berbayar"
ketik = "xsd: desimal" gunakan = "wajib"/>
< /xsd:tipekompleks>
< /xsd:elemen>
< /xsd:urutan>
< /xsd:complexType>
< /xsd:skema>
Metode parsePortfolioDoc() kelas DataModel menggunakan XMLUtil untuk memvalidasi dan mengurai parameter xml dan mengembalikan dokumen DOM:
private static final String SCHEMA_NAME
= "/ajaxapp/model/portfolio.xsd";
parserFactory DocumentBuilderFactory statis pribadi;
Dokumen statis pribadi parsePortfolioDoc (String xml)
melempar IOException, SAXException,
ParserConfigurationException {
disinkronkan (DataModel.kelas) {
jika (parserFactory == nol)
parserFactory = XMLUtil.newParserFactory(SCHEMA_NAME);
}
Parser DocumentBuilder = XMLUtil.newParser(parserFactory);
InputSource di = New InputSource(new StringReader(xml));
return parser.parse(dalam);
}
Sekarang Anda memiliki pohon DOM, Anda perlu mendapatkan data yang dibutuhkan untuk membentuk node DOM.
Ekstrak informasi yang diperlukan. Anda dapat menggunakan DOM API atau bahasa kueri (seperti XQuery atau XPath) untuk menelusuri pohon DOM. Java menyediakan API standar untuk XPath, yang akan digunakan nanti. Kelas XMLUtil membuat XPathFactory dengan metode newXPath():
import javax.xml.xpath.*;
...
xpathFactory statis yang dilindungi xpathFactory;
statis {
xpathFactory = XPathFactory.newInstance();
}
XPath statis publik newXPath() {
kembalikan xpathFactory.newXPath();
}
Metode berikut mengevaluasi ekspresi XPath dalam konteks tertentu dan mengembalikan nilai yang dihasilkan:
import javax.xml.xpath.*;
import org.w3c.dom.*;
...
String statis publik evalToString (ekspresi string,
Konteks objek) melempar XPathExpressionException {
return (String) newXPath().evaluate(ekspresi, konteks,
XPathConstants.STRING);
}
boolean statis publik evalToBoolean(Ekspresi string,
Konteks objek) melempar XPathExpressionException {
return ((Boolean) newXPath().evaluate(ekspresi, konteks,
XPathConstants.BOOLEAN)).booleanValue();
}
public static double evalToNumber (Ekspresi string,
Konteks objek) melempar XPathExpressionException {
return ((Double) newXPath().evaluate(ekspresi, konteks,
XPathConstants.NUMBER)).doubleValue();
}
Node statis publik evalToNode (ekspresi string,
Konteks objek) melempar XPathExpressionException {
kembali (Node) newXPath().evaluate(ekspresi, konteks,
XPathConstants.NODE);
}
NodeList statis publik evalToNodeList (ekspresi string,
Konteks objek) melempar XPathExpressionException {
kembali (NodeList) newXPath().evaluate(ekspresi, konteks,
XPathConstants.NODESET);
}
Metode setData() DataModel menggunakan metode pemecah XPath untuk mengekstrak informasi dari dokumen XML gabungan:
public synced void setData(String xml)
melempar IOException, SAXException,
Pengecualian ParserConfiguration,
XPathExpressionException {
mencoba{
Daftar saham ArrayList
= Daftar Array baru();
Dokumen doc = parsePortfolioDoc(xml);
NodeList nodeList = XMLUtil.evalToNodeList(
"/portfolio/stok", dok);
untuk (int i = 0; i < nodeList.getLength(); i++) {
Node simpul = nodeList.item(i);
Stok StockBean = StockBean baru();
stok.setSimbol(
XMLUtil.evalToString("@simbol", simpul));
stok.setBagikan(
(int) XMLUtil.evalToNumber("@shares", simpul));
stok.setPaidPrice(
XMLUtil.evalToNumber("@paidPrice", simpul));
stockList.add(stok);
}
this.stockList = daftar stok;
} tangkapan (Pengecualian e){
Logger.global.logp(Level.SEVERE, "DataModel", "setData",
e.getMessage(), e);
}
}
Setelah data tersedia dalam model data sisi server, data tersebut dapat diproses sesuai dengan kebutuhan aplikasi. Kemudian, Anda harus menanggapi permintaan Ajax.
Menghasilkan respons di sisi server
Mengembalikan HTML sebagai respons terhadap permintaan Ajax adalah solusi paling sederhana karena Anda dapat membuat markup menggunakan sintaks JSP dan klien Ajax cukup menggunakan elemen <div> atau <span> di suatu tempat di halaman. Namun, lebih efisien mengembalikan data ke klien Ajax tanpa markup presentasi apa pun. Anda bisa menggunakan format XML atau JSON.
Hasilkan respons XML. Java EE menyediakan banyak opsi untuk membuat dokumen XML: dibuat melalui JSP, dibuat dari pohon objek melalui JAXB, atau dibuat menggunakan javax.xml.transform. Transformator dalam contoh berikut akan membuat serialisasi pohon DOM:
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
...
serializerFctory statis publik TransformerFactory;
statis {
serializerFctory = TransformerFactory.newInstance();
}
serialisasi kekosongan statis publik (Node node, OutputStream keluar)
melempar TransformerException {
Serializer transformator = serializerFctory.newTransformer();
Properti serializerProps = Properti baru();
serializerProps.put(OutputKeys.METHOD, "xml");
serializer.setOutputProperties(serializerProps);
Sumber sumber = DOMSource baru(node);
Hasil hasil = StreamResult baru (keluar);
serializer.transform(sumber, hasil);
}
Ada begitu banyak opsi standar dan kerangka sumber pengembangan untuk menghasilkan XML di sisi server sehingga satu-satunya hal yang harus Anda lakukan adalah memilih salah satu yang sesuai untuk Anda. Namun, pada klien, situasinya sangat berbeda karena XML hanya dapat diurai menggunakan DOM. Beberapa browser juga mendukung XPath dan XSLT.
Di artikel Ajax sebelumnya, Anda mempelajari cara membuat XML melalui JSP dan kemudian menguraikannya di klien menggunakan JavaScript dan DOM. Solusi lain adalah dengan menggunakan JSON, bukan XML sebagai format data untuk merespons permintaan Ajax. Seperti disebutkan sebelumnya, string JSON dapat diubah menjadi pohon objek JavaScript menggunakan fungsi eval(). Ini lebih sederhana daripada menggunakan JavaScript untuk mengekstrak informasi dari pohon DOM. Yang Anda perlukan hanyalah kelas utilitas bagus yang menghasilkan JSON di sisi server.
Pengkodean JSON. Kelas JSONEncoder menyediakan metode untuk menyandikan literal, objek, dan array. Hasilnya disimpan di java.lang.StringBuilder:
package ajaxapp.util;
public class JSONEncoder {
penggemar StringBuilder pribadi;
JSONEncoder publik() {
buf = StringBuilder baru();
}
...
}
Metode character() mengkodekan satu karakter:
public void character(char ch) {
beralih (ch) {
kasus \:
kasus \":
kasus \ :
buf.tambahkan( \ );
buf.append(ch);
merusak;
kasus :
buf.tambahkan( \ );
buf.tambahkan( );
merusak;
kasus
:
buf.tambahkan( \ );
buf.tambahkan(
);
merusak;
kasus
:
buf.tambahkan( \ );
buf.tambahkan(
);
merusak;
bawaan:
jika (ch >= 32 && ch < 128)
buf.append(ch);
kalau tidak{
buf.tambahkan( \ );
buf.tambahkan(u);
untuk (int j = 12; j >= 0; j-=4) {
int k = (((int) ch) >> j) & 0x0f;
ke dalam c = k < 10 ? + k :a + k - 10;
buf.append((char) c);
}
}
}
}
Metode string() mengkodekan seluruh string:
public void string(String str) {
int panjang = str.panjang();
untuk (int i = 0; i < panjang; i++)
karakter(str.charAt(i));
}
metode literal() mengkodekan literal JavaScript:
public void literal(Nilai objek) {
if (nilai instanceof String) {
buf.tambahkan(");
string((String) nilai);
buf.tambahkan(");
} else if (nilai contoh Karakter) {
buf.tambahkan(\);
karakter(((Karakter) nilai).charValue());
buf.tambahkan(\);
} kalau tidak
buf.append(nilai.toString());
}
Metode koma() menambahkan karakter koma:
private void comma() {
buf.tambahkan(,);
}
Metode deleteLastComma() akan menghapus karakter koma terakhir di akhir buffer (jika ada):
private void deleteLastComma() {
if (buf.panjang() > 0)
jika (buf.charAt(buf.panjang()-1) == ,)
buf.deleteCharAt(buf.panjang()-1);
}
Metode startObject() menambahkan karakter { untuk menunjukkan awal objek JavaScript:
public void startObject() {
buf.tambahkan({);
}
Metode property() mengkodekan properti JavaScript:
public void property(String name, Object value) {
buf.append(nama);
buf.tambahkan(:);
literal(nilai);
koma();
}
Metode endObject() menambahkan karakter } untuk menunjukkan akhir objek JavaScript:
public void endObject() {
deleteLastComma();
buf.tambahkan(});
koma();
}
Metode startArray() menambahkan karakter [ untuk menunjukkan awal array JavaScript:
public void startArray() {
buf.tambahkan([);
}
Metode element() mengkodekan elemen array JavaScript:
public void element(Object value) {
literal(nilai);
koma();
}
Metode endArray() menambahkan karakter ] untuk menunjukkan akhir array JavaScript:
public void endArray() {
deleteLastComma();
buf.tambahkan(]);
koma();
}
metode toString() mengembalikan string JSON:
public String toString() {
deleteLastComma();
kembalikan buf.toString();
}
metode clear() membersihkan buffer:
public void clear() {
buf.setLength(0);
}
DataModel menggunakan kelas JSONEncoder untuk menyandikan data yang dikelolanya:
String tersinkronisasi publik getData() {
JSONEncoder json = JSONEncoder baru();
json.startArray();
untuk (int i = 0; i < stockList.size(); i++) {
Stok StockBean = stockList.get(i);
json.startObject();
json.property("simbol", stok.getSymbol());
json.property("berbagi", stok.getShares());
json.property("Harga dibayar", stok.getPaidPrice());
json.endObject();
}
json.endArray();
kembali json.toString();
}
Jika parameter permintaan xml disediakan, halaman ajaxCtrl.jsp akan mengatur data model. Jika tidak, laman akan menggunakan ekspresi EL ${dataModel.data} untuk menampilkan string JSON yang dikembalikan oleh getData():
< %@ taglib prefix="c" uri=" http://java.sun.com/jsp/ jstl /inti " %>
...
< jsp:useBean id="dataModel" scope="sesi"
kelas="ajaxapp.model.DataModel" />
< c:pilih>
...
< c:when test="${!empty param.xml}">
< c:setel target="${dataModel}"
properti="data"
nilai="${param.xml}" />
< /c:kapan>
<c:sebaliknya>
${dataModel.data}
< /c:sebaliknya>
< /c:pilih>
Pekerjaan ini belum selesai karena klien Ajax harus memproses data JSON.
Memproses respons di sisi klien
Dalam aplikasi Web biasa, Anda menghasilkan konten di sisi server menggunakan JSP, kerangka Web, dan pustaka tag. Aplikasi Ajax ideal untuk situasi ini karena kerangka Web seperti JavaServer Faces dan Oracle ADF Faces sangat berguna dalam membangun aplikasi Ajax. Namun masih terdapat perbedaan yang signifikan antara aplikasi Ajax dan non-Ajax. Saat menggunakan Ajax, Anda harus memproses data di sisi klien dan menggunakan JavaScript untuk menghasilkan konten secara dinamis guna menyediakan data kepada pengguna.
Jika Anda menggunakan format JSON untuk konversi data, sangat mudah untuk mengubah teks menjadi pohon objek menggunakan fungsi eval() yang disediakan oleh JavaScript. Jika Anda lebih suka menggunakan XML, ada banyak hal lain yang perlu Anda lakukan, namun format ini juga memiliki kelebihan tersendiri. Misalnya, XML dapat digunakan oleh banyak jenis klien, sedangkan JSON hanya mudah diurai di lingkungan JavaScript. Selain itu, saat menggunakan XML, kesalahan dapat ditemukan dan diperbaiki lebih cepat, sehingga mengurangi waktu debugging.
Gunakan JavaScript untuk mengakses pohon DOM. API DOM JavaScript sangat mirip dengan paket org.w3c.dom Java. Perbedaan utamanya adalah akses terhadap properti. Dalam JavaScript Anda dapat mengakses properti secara langsung, sedangkan Java memperlakukan properti sebagai pribadi dan Anda perlu mengaksesnya melalui metode dapatkan dan setel. Misalnya, Anda bisa mendapatkan elemen root dokumen melalui dom.documentElement.
DOM adalah API tingkat rendah yang menyediakan akses ke struktur dokumen yang diurai. Misalnya, Anda ingin mengabaikan komentar dalam banyak kasus, dan mungkin tidak ingin memiliki node teks yang berdekatan. Perhatikan contoh sederhana berikut:
var xml = "< element>da< !--comment-->ta&"
+ "< ![CDATA[cdata< /elemen>";
Anda dapat mengurai string XML di atas menggunakan fungsi utilitas yang diperkenalkan sebelumnya:
var dom = parse(xml);
Anda dapat menemukan kode untuk fungsi parse() di ajaxUtil.js; dalam hal ini, fungsi tersebut mengembalikan pohon DOM yang elemen akarnya berisi simpul teks, diikuti dengan komentar, simpul teks lain, dan simpul data karakter. Jika Anda ingin menyertakan teks tanpa komentar, Anda harus mengulangi elemen turunan elemen, menggabungkan nilai node data teks dan karakter (yang masing-masing memiliki tipe 3 dan 4):
var element = dom.documentElement;
var childNodes = elemen.childNodes;
var teks = "";
untuk (var i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeValue) {
var type = childNodes[i].nodeType;
jika (ketik == 3 || ketik == 4)
teks += childNodes[i].nodeValue;
}
Saat bekerja dengan DOM, Anda harus membuat sekumpulan kecil fungsi utilitas untuk menghindari penanganan detail tingkat rendah ini.
Gunakan JavaScript untuk menghasilkan konten dinamis. Browser web memungkinkan Anda mengakses struktur DOM halaman Web melalui objek dokumen. Misalnya, Anda dapat menggunakan document.getElementById(...) untuk menemukan elemen dengan sangat mudah. Anda juga dapat membuat elemen dan simpul teks baru yang dapat disisipkan ke dalam dokumen yang sudah ada. Namun, lebih mudah untuk membuat HTML dengan menggabungkan string seperti yang ditunjukkan di bawah ini:
function updateInfo(request) {
var share = eval(request.responseText);
var tabel = "< batas tabel=1 cellpadding=5>";
tabel += "<tr>";
tabel += "< th>Simbol< /th>";
tabel += "< th>Tren< /th>";
tabel += "< th>Harga Terakhir< /th>";
tabel += "< /tr>";
for (var i = 0; i < share.length; i++) {
var berbagi = berbagi[i];
var simbol = escapeXML(bagikan.simbol)
var tren = bagikan.tren > 0 ? "+" : "-";
var lastPrice = Nomor baru(share.lastPrice).toFixed(2);
tabel += "<tr>";
tabel += "< td>" + simbol + "< /td>";
tabel += "< td>" + tren + "< /td>";
tabel += "< td>" +Harga Terakhir + "< /td>";
tabel += "< /tr>";
}
tabel += "< /tabel>";
document.getElementById("tabel").innerHTML = tabel;
}
HTML yang dihasilkan dapat dimasukkan
ke dalam elemen kosong dengan mengatur properti bagian dalam dari objek yang dikembalikan oleh getElementById (), misalnya:
<div id = "table">
< /div>
Contoh dalam artikel ini menggunakan fungsi updateInfo () sebagai panggilan balik untuk menangani respons terhadap permintaan AJAX yang dikirim ke server melalui SendInforequest dalam file jaxlogic.js. Jika Anda ingin memperbarui informasi setiap 5 detik, Anda dapat menggunakan fungsi setInterval () JavaScript:
var simbol = [...];
setInterval ("Sendinforequest (Simbol, UpdateInfo)", 5000);
Kelas yang disebut Datafeed mensimulasikan umpan sisi server. Halaman Ajaxctrl.jsp memanggil metode feed getData (), mengembalikan respons sebagai string JSON. Di sisi klien, fungsi updateInfo () mem -parsing string JSON menggunakan eval (request.responsetext), seperti yang ditunjukkan dalam contoh kode sebelumnya.