Javascript Ve Ajax İle Zamanuyumsuz İstekler Oluşturma.
Web uygulamalarının çoğu, sunucudan tüm html sayfasını alan bir istek/yanıt modelini kullanır. Sonuçta kullanıcı bir düğmeyi tıklatır, sunucuyu bekler, başka bir düğmeyi tıklatır ve biraz daha bekler. Ajax ve xmlhttprequest nesnesiyle, kullanıcıların sunucu yanıtını beklemelerine hiçbir zaman gerek bırakmayan bir istek/yanıt modeli kullanabilirsiniz. Bu makalede, brett mclaughlin, çapraz tarayıcı yöntemiyle xmlhttprequest örneklerinin nasıl oluşturulacağını, isteklerin oluşturulmasını ve gönderilmesini ve sunucuya yanıt verilmesini gösteriyor.
Bu dizinin son makalesinde (bağlantılar için bkz. Kaynaklar), Ajax uygulamalarına giriş yapılmış ve Ajax uygulamalarının kullandığı bazı temel kavramlara bakılmıştı. Bunun merkezinde, önceden biliyor olabileceğiniz birçok teknoloji vardır: JavaScript, HTML ve XHTML, biraz dinamik HTML ve hatta, biraz DOM (Document Object Model; Belge Nesne Modeli). Bu makalede, uzak mesafeden konuya yaklaşıp özel Ajax ayrıntılarına odaklanacağım.
Bu makalede, Ajax'la ilişkili tüm nesnelerin ve programlama yaklaşımlarının en temelinden başlayacağız: XMLHttpRequest
nesnesi. Bu nesne, gerçekten de tüm Ajax uygulamaları arasında tek ortak iş parçacığıdır ve -- tahmin edebileceğiniz gibi -- programlama yeteneğinizi mümkün olan sınırlara götürebilmek için bu nesneyi anlamak isteyeceksiniz. Aslında, bazen XMLHttpRequest
nesnesini doğru kullanmak için, açıkça XMLHttpRequest
nesnesini kullanmayacaksınız. Peki bütün bunlar da ne demek oluyor?
Öncelikle, kodun içine dalmadan bu genel bakışın son kısmını ele alalım -- Web 2.0 konusunda her şeyin kafanızda net olduğundan emin olun. Web 2.0 terimini duyduğunuzda, sormanız gereken ilk şey "Web 1.0 nedir?" olmalıdır. Web 1.0 terimi çok sık duyulmasa da, çok belirgin bir istek ve yanıt modelinin kullanıldığı geleneksel Web için kullanılmaktadır. Örneğin, Amazon.com'a gidin ve bir düğmeyi tıklatın ya da bir arama terimi girin. Sunucuya bir istek gönderilir ve tarayıcınıza bir yanıt gelir. Bu istek, kitaplar ve başlıklardan oluşan bir listeden çok daha fazlasını içerir; aslında bu başka bir tam HTML sayfasıdır. Sonuç olarak, Web tarayıcınızın ekranı bu yeni HTML sayfasıyla yeniden çizilirken bazı yanıp sönen şekiller görürsünüz. Aslında, gördüğünüz her bir sayfayla tanımlanan istek ve yanıtı açıkça görebilirsiniz.
Web 2.0, bu gözle görülür geri ve ileri kavramını (çok geniş bir ölçeğe kadar) bir yana bırakır. Örneğin, Google Maps ya da Flickr gibi bir siteyi ziyaret edin (Kaynaklar içinde, Ajax tarafından desteklenen bu Web 2.0 sitelerine bağlantılar yer alır). Google Maps'te, harita üzerinde fareyi sürükleyerek gezinebilir ve çok küçük bir yeniden çizimle haritayı yakınlaştırıp uzaklaştırabilirsiniz. Elbette, burada da istekler ve yanıtlar vardır, ancak bunların tümü sahne arkasından yürütülmektedir. Bir kullanıcı olarak sizin gördüğünüz, çok daha güzel ve daha çok bir masaüstü uygulamasını kullanmak gibidir. Web 2.0'dan söz edildiğinde gördüğünüz şey, bu yeni deneyim ve paradigmanın kendisidir.
Daha sonra, bu yeni etkileşimlerin nasıl mümkün kılınacağını düşünmeniz gerekir. Tabii, hala isteklerde bulunmanız ve yanıtları almanız gerekir, ancak yavaş ve aksak bir Web arabirimi algılamasını veren şey, her bir istek/yanıt etkileşiminde HTML'in yeniden çizilmesidir. Daha net bir şekilde anlatırsak, tüm HTML sayfasının yerine, yalnızca ihtiyacınız olan veriler için istekte bulunacak ve yanıtları alacak bir yaklaşıma ihtiyacınız vardır. Yeni bir tam HTML sayfasını yalnızca, kullanıcının yeni bir sayfa görmesini istediğinizde almak isteyebilirsiniz.
Ancak etkileşimlerin çoğu, ayrıntı ekler ya da gövde metnini değiştirir ya da var olan sayfalardaki verilerin üzerine yazar. Bu durumların tümünde, Ajax ve Web 2.0 yaklaşımı tüm HTML sayfasını güncellemeden veri gönderip almayı mümkün kılar. Ve bu yetenek, sık sık Web'de dolaşan kullanıcılara uygulamanızın çok daha hızlı, daha çabuk yanıt veren bir uygulama olduğunu düşündürecek ve tekrar tekrar geri gelmelerini sağlayacaktır.
Tüm bu hokus pokusu gerçekleştirmek için XMLHttpRequest
adlı JavaScript nesnesini yakından tanımanız gerekir. Bu küçük nesne -- bir süredir bazı tarayıcılarda kullanılmaktadır -- Web 2.0, Ajax ve önümüzdeki birkaç ay boyunca bu köşede öğreneceğiniz diğer her şeyin temel taşıdır. Hızlı bir genel görünüm sağlamak amacıyla, bu nesneyle birlikte kullanabileceğiniz birkaç yöntemi ve özelliği sıralayayım:
open()
: Sunucuya gönderilecek yeni bir istek hazırlar.send()
: Bir isteği sunucuya gönderir.abort()
: Geçerli istekten çıkar.readyState
: Geçerli HTML hazırlık durumunu sağlar.responseText
: Bir isteğe yanıt vermek için sunucunun gönderdiği metin.
Bunların tümünü (ya da hiçbirini) anlamazsanız üzülmeyin -- bundan sonraki birkaç makale içinde her bir yöntem ve özellik ayrıntılarıyla anlatılacaktır. Buradan çıkarmanız gereken, XMLHttpRequest
ile ne yapacağınıza ilişkin iyi bir fikirdir. Bu yöntemlerin ve özelliklerin her birinin, bir istek göndermeyle ve bir yanıtı işlemeyle ilgili olduğuna dikkat edin. Aslında, XMLHttpRequest
nesnesinin her yöntemini ve özelliğini gördükçe, bunların tümünün o çok basit istek/yanıt modeliyle ilişkili olduğunu anlayacaksınız. Açıkçası, inanılmaz bir GUI nesnesiyle ya da kullanıcı etkileşimi yaratmak için süper gizli bir yaklaşımla ilgili bilgi almayacaksınız; basit istekler ve basit yanıtlarla çalışacaksınız. Bu kulağa heyecan verici gelmeyebilir, ancak bu tek nesnenin dikkatli bir şekilde kullanılması uygulamalarınızı tamamen değiştirebilir.
Öncelikle, yeni bir değişken yaratmanız ve bunu, XMLHttpRequest
nesnesinin bir örneğine atamanız gerekir. Bu JavaScript'te oldukça kolaydır; nesne adında new
(yeni) anahtar sözcüğünü kullanmanız yeterlidir (Liste 1'de olduğu gibi).
Liste 1. Yeni bir XMLHttpRequest nesnesi yaratma
<script language="javascript" type="text/javascript"> |
Çok zor değildi, değil mi? Unutmayın, JavaScript, değişkeninin üzerine yazılmasını gerektirmez, bu nedenle Liste 2'deki gibi bir şeye ihtiyacınız yoktur (bu nesneyi Java yaratsaydınız, böyle yapmanız gerekebilirdi).
Liste 2. XMLHttpRequest nesnesi yaratmaya ilişkin sözde Java kodu
XMLHttpRequest request = new XMLHttpRequest(); |
JavaScript'te var
ile bir değişken yaratır, buna bir ad verir ("request" gibi) ve daha sonra bunu, yeni XMLHttpRequest
örneğine atarsınız. Bu noktadan sonra nesneyi işlevlerinizde kullanabilirsiniz.
Gerçek yaşamda, işler kötü gidebilir ve bu kod, hata işleme özelliği sağlamaz. Bu nesneyi yaratmak ve işler ters giderse nesneyi hatalı olarak ayırmak biraz daha iyi bir yaklaşımdır. Örneğin, eski tarayıcıların birçoğu (ister inanın ister inanmayın, insanlar hâlâ Netscape Navigator programının eski sürümlerini kullanmaya devam ediyorlar) XMLHttpRequest
nesnesini desteklemez ve bu kullanıcılara, bir şeyin ters gittiğini bildirmeniz gerekir. Liste 3'te, bu nesnenin, hata oluştuğunda JavaScript uyarısı verecek şekilde nasıl yaratılacağı gösterilmektedir.
Liste 3. XMLHttpRequest nesnesini bazı hata işleme yetenekleriyle yaratma
<script language="javascript" type="text/javascript"> |
Bu adımların her birini tam olarak anladığınızdan emin olun:
Request
adlı yeni bir değişken oluşturun ve buna, bir false (yanlış) değeri atayın.XMLHttpRequest
nesnesinin henüz yaratılmadığını belirten bir koşul olarak false (yanlış) değerini kullanacaksınız.- Bir try/catch (dene/yakala) bloğu ekleyin:
XMLHttpRequest
nesnesini yaratmayı deneyin.- Başarısız olursanız (
catch (failed)
),request
değişkeninin false (yanlış) değerinde kaldığından emin olun.
Request
değişkeninin hâlâ false (yanlış) değerinde olup olmadığına bakın (işler yolundaysa, bu değerde kalmış olmayacaktır).- Bir sorun varsa (ve
request
false değerindeyse), kullanıcılara bir sorun olduğunu bildirmek için bir JavaScript uyarısı kullanın.
Bu oldukça basittir; çoğu JavaScript ve Web geliştiricisi için konuyu anlamak, ilgili konuları okuyup yazılar yazmaktan çok daha kısa sürer. Artık XMLHttpRequest
nesnesi yaratan ve hata kabul etmeyen bir kod parçanız var, üstelik ters giden şeylerle ilgili size bilgi de veriyor.
Her şey yolunda gibi görünüyor ... en azından bu kodu Internet Explorer'da deneyinceye kadar. Bunu denerseniz, Şekil 1'dekine benzer, berbat görünen bir sonuç alırsınız.
Şekil 1. Internet Explorer hata bildirimi
|
Görünen o ki, bir şeyler ters gidiyor; Internet Explorer'ın modası geçmiş bir tarayıcı olduğu söylenemez ve dünyanın yaklaşık %70'i Internet Explorer kullanmaya devam ediyor. Diğer bir deyişle, Microsoft ve Internet Explorer'ı desteklemezseniz, Web dünyasında çok da başarılı olamazsınız. Bu nedenle, Microsoft'un tarayıcılarıyla çalışmak için farklı bir yaklaşıma ihtiyacınız var.
Görünüşe göre Microsoft Ajax'ı destekliyor, ancak kendi XMLHttpRequest
sürümüne farklı bir ad veriyor. Aslında, bunun için birkaç farklı ad kullanıyor. Internet Explorer'ın daha yeni bir sürümünü kullanıyorsanız, Msxml2.XMLHTTP
adlı nesneyi kullanmanız gerekir; bazı eski Internet Explorer sürümleri Microsoft.XMLHTTP
nesnesini kullanır. Bu iki nesne tipini desteklemeniz gerekir (bu arada Microsoft dışındaki tarayıcıların desteğini de kaybetmemelisiniz). Daha önce gördüğünüz koda Microsoft desteği ekleyen Liste 4'e bakın.
Liste 4. Microsoft tarayıcıları için destek ekleme
<script language="javascript" type="text/javascript"> |
Bu dolambaçlı yollarda kaybolmak oldukça kolay olduğundan ben size adım adım yol göstereceğim:
Request
adlı yeni bir değişken oluşturun ve buna, bir false (yanlış) değeri atayın. Koşul içinXMLHttpRequest
nesnesinin henüz yaratılmadığını belirten false (yanlış) değerini kullanın.- Bir try/catch (dene/yakala) bloğu ekleyin:
XMLHttpRequest
nesnesini yaratmayı deneyin.- Başarısız olursa (
catch (trymicrosoft)
):- Microsoft'un daha yeni sürümlerini kullanarak Microsoft uyumlu bir nesne yaratmayı deneyin (
Msxml2.XMLHTTP
). - Başarısız olursa (
catch (othermicrosoft)
), Microsoft'un eski sürümlerini kullanarak Microsoft uyumlu bir nesne yaratmayı deneyin (Microsoft.XMLHTTP
).
- Microsoft'un daha yeni sürümlerini kullanarak Microsoft uyumlu bir nesne yaratmayı deneyin (
- Başarısız olursanız (
catch (failed)
),request
değişkeninin false (yanlış) değerinde kaldığından emin olun.
Request
değişkeninin hâlâ false (yanlış) değerinde olup olmadığına bakın (işler yolundaysa, bu değerde kalmayacaktır).- Bir sorun varsa (ve
request
false değerindeyse), kullanıcılara bir sorun olduğunu bildirmek için bir JavaScript uyarısı kullanın.
Kodunuzdaki bu değişiklikleri yaptıktan sonra Internet Explorer'da bir deneme daha yapın; yarattığınız formu (hata iletisi olmadan) görmeniz gerekir. Benim denememde, sonuç Şekil 2'deki gibiydi.
Şekil 2. Internet Explorer olağan bir şekilde çalışıyor
Statik - dinamik karşılaştırması
Liste 1, 3 ve 4'e tekrar bakın ve bu kodun doğrudan script
biçim imlerinin içine yerleştirildiğine dikkat edin. JavaScript böyle kodlandığında ve bir yöntem ya da işlev gövdesine yerleştirilmediğinde, buna statik JavaScript denir. Bu, kodun, sayfa kullanıcıya görüntülenmeden önce çalışmaya başladığı anlamına gelir. (Belirtimden, kodun tam olarak ne zaman çalıştığı ve tarayıcıların işlemleri ne zaman farklı gerçekleştirdikleri yüzde yüz net değildir; ancak kodun, kullanıcıların sayfanızla etkileşime girmeden önce çalışması garanti edilir.) Birçok Ajax programcısı genellikle XMLHttpRequest
nesnesini böyle yaratır.
Bunu belirttikten sonra, bu kodu kesinlikle Liste 5'teki gibi bir yönteme yerleştirebilirsiniz.
Liste 5. XMLHttpRequest yaratma kodunu bir yönteme taşıma
<script language="javascript" type="text/javascript"> |
Kod bu şekilde kurulduğunda, herhangi Ajax çalışması gerçekleştirmeden önce bu yöntemi çağırmanız gerekir. Bu nedenle, Liste 6'daki gibi bir şey hazırlamalısınız.
Liste 6. XMLHttpRequest yaratma yönetimi kullanma
<script language="javascript" type="text/javascript"> |
Bu kodla ilgili tek sorun -- ve çoğu Ajax programcısının bu yaklaşımı kullanmamasının nedeni -- bunun hata bildirimini geciktirmesidir. 10 ya da 15 alandan, seçim kutusundan, vb. oluşan karmaşık bir formunuz olduğunu varsayın ve kullanıcı alan 14'e (formun altlarında) bir metin girdiğinde Ajax kodunun bir kısmını çalıştırırsınız. Bu noktada, getCustomerInfo()
çalışır, bir XMLHttpRequest
nesnesi yaratmayı dener ve (bu örnekte) başarısız olur. Daha sonra, kullanıcıya, (bir sürü sözcükle) bu uygulamayı kullanamayacaklarını belirten bir uyarı gönderilir. Ancak kullanıcı forma veri girerek zaman harcamıştır! Bu oldukça can sıkıcı bir durumdur ve canlarını sıkmak, kullanıcıların sitenize geri gelmelerini engelleyebilecek bir durumdur.
Statik JavaScript kullandığınızda, kullanıcı sayfanıza gelir gelmez bir hata iletisi alır. Bu da can sıkı değil mi? Belki; Web uygulamanızın tarayıcılarında çalışmaması kullanıcıları kızdırabilir. Ancak, aynı hatayı bilgi girmek için harcadıkları 10 dakikanın sonunda vermekten kesinlikle çok daha iyidir. Yalnızca bu nedenden, size kodunuzu statik olarak hazırlamanızı ve kullanıcılara olası sorunlarla ilgili erkenden bilgi vermenizi öneririm.
XMLHttpRequest ile istek gönderme
İstek nesneniz hazırlandıktan sonra, istek/yanıt döngüsünü başlatabilirsiniz. Unutmayın, XMLHttpRequest
nesnesinin tek amacı isteklerde bulunmanızı ve yanıt almanızı sağlamaktır. Diğer şeyler -- kullanıcı arabirimini değiştirmek, resim geçişleri, hatta sunucunun geri gönderdiği verileri yorumlamak -- JavaScript, CSS ya da sayfalarınızdaki diğer kodların görevidir. XMLHttpRequest
kullanıma hazır olduğunda, bir sunucuya bir istek gönderebilirsiniz.
Ajax, kum havuzu olarak bilinen bir güvenlik modeli kullanır. Sonuç olarak, Ajax kodunuz (ve özellikle XMLHttpRequest
nesnesi) yalnızca çalıştığı etki alanına istekte bulunabilir. Yakında yayınlanacak bir makalede güvenlik ve Ajax ile ilgili çok daha fazla şey öğreneceksiniz, ama şimdilik bilmeniz gereken yerel makinenizde çalışan kodun, yalnızca yerel makinenizdeki sunucu tarafı komut dosyalarına istekte bulunabileceğidir. Ajax kodunuz www.breakneckpizza.com üzerinde çalışıyorsa, bunun www.breakneckpizza.com üzerinde çalışan komut dosyalarına istek göndermesi gerekir.
İlk olarak belirlemeniz gereken bağlanılacak sunucunun URL'sidir. Bu Ajax'a özel bir şey değildir (açıkçası şimdiye kadar URL oluşturmayı öğrenmiş olmanız gerekir) ancak yine de bağlantı kurmak için bu gereklidir. Çoğu uygulamada, bu URL'yi kullanıcılarınızın üzerinde çalıştıkları formdan alınan verilerle bazı statik veri takımlarının birleşiminden oluşturacaksınız. Örneğin, Liste 7'de telefon numarası alanındaki değeri alan ve bu verileri kullanarak URL oluşturan bir JavaScript kodu gösterilmektedir.
Liste 7. Bir istek URL'si oluşturma
<script language="javascript" type="text/javascript"> |
Buradaki hiçbir şey kafanızı karıştırmamalıdır. Öncelikle, kod phone
(telefon) adlı yeni bir değişken yaratır ve bu değişkene, tanıtıcısı "phone" (telefon) olan form alanının değerini atar. Liste 8'de, bu forma ilişkin phone
(telefon) alanını ve id
(tanıtıcı) özniteliğini görebileceğiniz XHTML gösterilmektedir.
Liste 8. Break Neck Pizza formu
<body> |
Ayrıca, kullanıcılar telefon numaralarını girdiklerinde ya da numarayı değiştirdiklerinde getCustomerInfo()
yönteminin başlatılması da Liste 8'de gösterilmiştir. Bu yöntem daha sonra numarayı alır ve url
değişkeninde saklanan bir URL dizisi oluşturmak için kullanılır. Unutmayın: Ajax kodu kum havuzu yöntemini kullandığı ve yalnızca aynı etki alanına bağlanabildiği için, URL'nizde gerçekten bir etki alanı adı olması gerekmez. Bu örnekte, komut dosyasının adı /cgi-local/lookupCustomer.php
'dir. Son olarak, telefon numarası bu komut dosyasına bir GET parametresi olarak eklenir: "phone=" + escape(phone)
.
escape()
yöntemini daha önce hiç görmediyseniz, doğru biçimde düz metin olarak gönderilemeyecek karakterlerden kaçınmak için kullanılır. Örneğin, telefon numarasındaki boşluklar %20
karakterlerine dönüştürülür ve karakterlerin URL içinde aktarılmasını sağlar.
İhtiyacınız olan sayıda parametre ekleyebilirsiniz. Örneğin, başka bir parametre eklemek isterseniz, bunu URL'ye ekleyin ve parametreleri ve (&
) karakteriyle birbirinden ayırın [ilk parametre komut dosyası adından bir soru işaretiyle (?
) ayrılır].
|
Bağlanılacak bir URL ile, isteği yapılandırabilirsiniz. Bunu, XMLHttpRequest
nesnenizde open()
yöntemini kullanarak gerçekleştireceksiniz. Bu yöntem, en çok beş parametre kabul eder:
- request-type: Gönderilecek isteğin tipi. Genellikle
GET
ya daPOST
değerleri gönderilir, ancakHEAD
istekleri de gönderebilirsiniz. - url: Bağlanılacak URL.
- asynch: İsteğin zamanuyumsuz olmasını istiyorsanız true (doğru), zamanuyumlu olmasını istiyorsanız false (yanlış) değerinde olmalıdır. Bu parametre isteğe bağlıdır ve varsayılan değer olarak true (doğru) değerindedir.
- username: Kimlik doğrulaması gerekiyorsa, kullanıcı adını burada belirtebilirsiniz. Bu isteğe bağlı bir parametredir ve herhangi bir varsayılan değeri yoktur.
- password: Kimlik doğrulaması gerekiyorsa, parolayı burada belirtebilirsiniz. Bu isteğe bağlı bir parametredir ve herhangi bir varsayılan değeri yoktur.
Genellikle, bu parametrelerin ilk üçü kullanılır. Aslında, zamanuyumsuz bir istekte bulunmak istediğinizde bile üçüncü parametre için "true" (doğru) değerini belirlemeniz gerekir. Bu varsayılan ayardır, ancak isteğin zamanuyumsuz olup olmadığını belirtmek her zaman için kendi belgelendirmelerinizde yararlı olabilir.
Hepsini bir araya topladığınızda genellikle Liste 9 gibi görünen bir satır ortaya çıkar.
Liste 9. İsteği açma
function getCustomerInfo() { |
URL'yi belirledikten sonra gerisi önemsizdir. Birçok istek için GET
'in kullanılması yeterlidir (sonraki makalelerde POST
kullanmak isteyebileceğiniz durumları göreceksiniz); open()
yöntemini kullanmak için, URL ile birlikte, tüm gerekli olan bu kadardır.
Zamanuyumsuzluk üzerine kısa bir açıklama
Bu dizide yayınlanacak sonraki bir makalede, zamanuyumsuz kod yazma ve kullanma üzerinde ayrıntılı bir şekilde duracağım; ancak, open()
yöntemindeki bu son parametrenin neden bu kadar önemli olduğunu anlamanızı istiyorum. Normal bir istek/yanıt modelinde -- burada Web 1.0'ı düşünün -- istemci (tarayıcınız ya da yerel makinenizde çalışan kod) sunucuya bir istekte bulunur. Bu istek zamanuyumludur; diğer bir deyişle, istemci sunucudan bir yanıt bekler. İstemci beklerken, genellikle beklemekte olduğunuzu gösteren birkaç bildirim biçiminden en az birini alırsınız:
- Kum saati (özellikle Windows'ta).
- Dönen plaj topu (genellikle Mac makinelerinde).
- Uygulama donar ve bazen imleç değişir.
Web uygulamalarının aksak ya da yavaş olduğunu düşünmenizin asıl nedeni budur -- gerçek etkileşim eksikliği. Bir düğmeye bastığınızda, gönderilen isteğe yanıt gelinceye kadar uygulamanız kullanılamaz duruma gelir. Yoğun sunucu işlemi gerektiren bir istekte bulunduysanız, bekleme süresi uzun olabilir (en azında günümüzün çok işlemcili, beklemesiz, DSL dünyasında).
Bununla birlikte, zamanuyumsuz bir istek sunucunun yanıt vermesini beklemez. Bir istek gönderirsiniz ve uygulamanız işleme devam eder. Kullanıcılar Web formuna bilgi girmeye, diğer düğmeleri tıklatmaya devam edebilir, hatta formdan çıkabilirler. Dönen plaj topları, kum saatleri ya da uzun süreli donan uygulamalar olmaz. Sunucu sessizce isteğe yanıt verir ve işlem tamamlandığında, ilk istekte bulunanın, (biraz sonra göreceğiniz yöntemlerle) işlemin tamamlandığını bilmesini sağlar. Sonuçta aksak ya da yavaş olmayan, bunun yerine yanıt veren, etkileşimli ve daha hızlı bir uygulama ortaya çıkar. Bu Web 2.0'ın yalnızca bir bileşenidir, ancak çok önemlidir. Tüm parlak GUI bileşenleri ve Web tasarımı paradigmaları yavaş, zamanuyumlu istek/yanıt modelinin üstesinden gelemez.
İstek, open()
yöntemiyle yapılandırıldıktan sonra gönderilmeye hazırdır. Neyse ki isteği göndermeye ilişkin yöntem, open()
yönteminden daha doğru bir şekilde adlandırılmıştır. Bu yönteme send()
denir.
send()
yalnızca tek bir parametre alır: gönderilecek içerik. Bunun üzerinde uzun uzun düşünmeden önce, verileri URL'nin kendisinden göndermekte olduğunuzu anımsayın:
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone); |
Verileri send()
yöntemiyle gönderebilirsiniz, ancak verileri URL'nin kendisi üzerinden de gönderebilirsiniz. Aslında, GET
isteklerinde (olağan Ajax kullanımının yaklaşık %80'ini oluşturur), verileri URL içinde göndermek çok daha kolaydır. Güvenli bilgi ya da XML göndermeye başladığınızda, içeriği send()
yöntemiyle göndermek isteyebilirsiniz (güvenli veri ve XML iletilerini bu dizinin sonraki bir makalesinde anlatacağım). Verileri send()
yöntemiyle geçirmeniz gerekmediğinde, bu yöntemin bağımsız değişkeni için yalnızca null
(yok) değerini belirleyin. Bu makalede gördüğünüz örnekte bir istek göndermek için tüm ihtiyacınız olan tam olarak budur (bkz. Liste 10).
Liste 10. İsteği gönderme
function getCustomerInfo() { |
Geri çağrı yönteminin belirlenmesi
Bu noktada, yeni, devrim niteliğinde ya da zamanuyumsuz sayılabilecek çok az şey yaptınız. open()
yönteminde küçük "true" (doğru) anahtar sözcüğünün eklenmesi zamanuyumsuz bir istek oluşturdu. Ancak bunun dışında, bu kod Java sunucu uygulamalarıyla programlamaya ve JSP'lere, PHP ya da Perl'e dayanır. O zaman Ajax ve Web 2.0'ın büyük sırrı ne? Sır, XMLHttpRequest
nesnesinin onreadystatechange
adı verilen basit bir özelliği çevresinde döner.
Öncelikle, bu kodda yarattığınız süreci anladığınızdan emin olun (gerekiyorsa, Liste 10'u gözden geçirin). Bir istek oluşturuldu ve gönderildi. Buna ek olarak, bu bir zamanuyumsuz istek olduğundan JavaScript yöntemi (bu örnekte getCustomerInfo()
) sunucunun yanıtını beklemeyecektir. Kod devam edecek; bu durumda, yöntemden çıkılacak ve denetim forma dönecek. Kullanıcılar bilgi girmeye devam edebilecekler ve uygulama sunucuyu beklemeyecektir.
Ancak bu, ilginç bir soruyu da beraberinde getiriyor: Sunucu isteği işlemeyi bitirdiğinde ne olacak? Yanıt, en azından kodun şu haliyle, hiçbir şey! Elbette bu iyi bir şey değil. Bu nedenle, XMLHttpRequest
tarafından gönderilen isteği işlemesi tamamlandığında sunucunun ne yapması gerektiğini belirten bir tür yönergeye sahip olması gerekir.
|
İşte tam burada onreadystatechange
özelliği devreye girer. Bu özellik bir geri çağrı yöntemi belirleyebilmenizi sağlar. Geri çağrı (callback), sunucunun Web sayfanızın kodunu geri çağırabilmesini sağlar (tahmin eder miydiniz?). Bu, sunucuya bir ölçüye kadar denetim de verir; sunucu isteği tamamladığında, XMLHttpRequest
nesnesinin içine ve özellikle onreadystatechange
özelliğine bakar. Daha sonra, bu özellikte belirlenen yöntem çağrılır. Bu bir geri çağrıdır, çünkü sunucu Web sayfasına doğru bir geri çağrı başlatır -- bu, Web sayfasının kendisinde olup bitenden bağımsızdır. Örneğin, sunucu bu yöntemi kullanıcı sandalyesinde oturup, klavyesine dokunmazken çağırabilir; ancak, kullanıcı yazı yazarken, faresini oynatırken, sayfayı aşağı kaydırırken, bir düğmeyi tıklatırken de bu yöntemi çağırabilir ... kullanıcının ne yaptığının hiçbir önemi yoktur.
Burada devreye zamanuyumsuzluk girer: Kullanıcı formu bir düzeyde çalıştırırken, başka bir düzeyde sunucu bir isteğe yanıt verir ve onreadystatechange
özelliğinde belirtilen geri çağrı yöntemini başlatır. Bu nedenle, bu yöntemi Liste 11'de gösterildiği şekilde, kodunuzda belirtmeniz gerekir.
Liste 11. Bir geri çağrı yönteminin belirlenmesi
function getCustomerInfo() { |
Bu özelliğin kodun neresinde ayarlandığına dikkat edin -- send()
çağrılmadan önce ayarlanır. Bu özelliği istek gönderilmeden önce ayarlamanız gerekir; böylece, sunucu isteğe yanıt vermeyi tamamladığında özelliği arayabilir. Geriye, bu makalenin son bölümünde odaklanacağımız updatePage()
yönteminin kodlanması kalıyor.
İsteğinizi gönderdiniz, kullanıcınız Web formunda mutlulukla çalışıyor (bu arada sunucu da isteği işliyor) ve sunucu, isteği işlemeyi tamamlıyor. Sunucu onreadystatechange
özelliğine bakar ve çağrılacak yöntemi belirler. Bu gerçekleştikten sonra, zamanuyumsuz olsun ya da olmasın uygulamanızı diğer uygulamalar gibi düşünebilirsiniz. Diğer bir deyişle, sunucuya yanıt veren özel işlem yazma yöntemlerini uygulamanız gerekmez; yalnızca formu değiştirin, kullanıcıyı başka bir URL'ye alın ya da sunucuya yanıt vermek için ne yapmanız gerekiyorsa onu yapın. Bu bölümde, sunucuya yanıt verilmesi ve tipik bir işlemin yapılması -- kullanıcının gördüğü formun değiştirilmesi -- üzerinde duracağız.
Sunucunun işi bittiğinde ne yapması gerektiğini nasıl bildireceğinizi gördünüz: XMLHttpRequest
nesnesinin onreadystatechange
özelliğini çalışacak işlevin adına ayarlayın. Daha sonra, sunucu isteği işledikten sonra otomatik olarak bu işlevi çağırır. Bu yöntemle ilgili parametreler hakkında kafa yormanıza da gerek yoktur. Liste 12'deki gibi basit bir yöntemle işe başlayacaksınız.
Liste 12. Geri çağrı yönteminin kodlanması
<script language="javascript" type="text/javascript"> |
Bu, sunucu işlemi tamamladığında, bunu size bildiren bir uyarı gönderir. Bu kodu kendi sayfanızda deneyin, sayfayı kaydedin ve bir tarayıcıda açın (bu örnekte XHTML kullanmak isterseniz, Liste 8'e bakın). Bir telefon numarası girip alandan çıktığınızda, uyarı iletisini görmeniz gerekir (bkz. Şekil 3); ancak OK (Tamam) düğmesini tıklattığınızda uyarı defalarca yeniden görüntülenir.
Şekil 3. Uyarı görüntüleyen Ajax kodu
Tarayıcınıza bağlı olarak, form uyarı görüntülemeyi durduruncaya kadar iki, üç, hatta dört uyarı alırsınız. Peki neler oluyor? Anlaşılan istek/yanıt döngüsünün önemli bir bileşeni olan HTTP hazır olma durumunu dikkate almadınız.
Daha önce, sunucunun, isteği işlemesi bittiğinde XMLHttpRequest
nesnesinin onreadystatechange
özelliğinden çağrılacak yöntemi aradığını söylemiştim. Bu doğru, ama tüm gerçek bundan ibaret değil. Aslında sunucu, yöntemi HTTP hazırlık durumu her değiştiğinde yeniden çağırır. Bu ne anlama geliyor? Öncelikle HTTP hazır olma durumlarını (ready states) anlamanız gerekiyor.
HTTP hazır olma durumu, bir isteğin durumunu ya da durumlarını belirtir. İsteğin başlatılıp başlatılmadığını, yanıtlanıp yanıtlanmadığını ya da istek/yanıt modelinin tamamlanıp tamamlanmadığını anlatmak için kullanılır. Sunucunun sağladığı yanıt metninin ya da verilerin okuma için güvenli olup olmadığını belirlemenize de yardımcı olur. Ajax uygulamalarınızda beş hazır olma durumundan söz edebiliriz:
- 0: İstek başlatılmadı (
open()
çağrılmadan önce). - 1: İstek hazırlandı, ancak henüz gönderilmedi (
send()
çağrılmadan önce). - 2: İstek gönderildi ve işleniyor (bu noktada genellikle yanıtın içerik üstbilgilerini alabilirsiniz).
- 3: İstek işleniyor; yanıttan bazı kısmi verileri alabilirsiniz, ancak sunucu yanıt vermeyi tamamlamamıştır.
- 4: Yanıt tamamlandı; sunucunun yanıtını alabilir ve kullanabilirsiniz.
Tarayıcılar arası sorunların neredeyse tümünde, bu hazır olma durumları biraz tutarsız bir şekilde kullanılmaktadır. Hazır olma durumlarının her zaman 0'dan 1'e, sonra 2'ye, 3'e ve en son 4'e doğru gitmesini bekleyebilirsiniz, ama pratikte, bu çok ender görülen bir durumdur. Bazı tarayıcılar hiçbir zaman 0 ya da 1 raporu vermez ve doğrudan 2, 3 ve 4'e atlar. Diğer tarayıcılar tüm durumları raporlayabilir. Başka tarayıcılar da 1 durumunu birden çok defa raporlayabilir. Son bölümde de gördüğünüz gibi, sunucu updatePage()
yöntemini birkaç kez çağırdı ve her bir çağrı, bir uyarı iletisinin görüntülenmesiyle sonuçlandı - büyük olasılıkla sizin istediğiniz tam olarak bu değildi!
Ajax programlamasında, doğrudan ilgilenmeniz gereken tek durum 4 numaralı durumdur. Bu durum, sunucu yanıtının tamamlandığını ve yanıt verilerini denetlemenin ve kullanmanın güvenli olduğunu belirtir. Buna güvenmek için, geri çağrı yönteminizin ilk satırının Liste 13'teki gibi olması gerekir.
Liste 13. Hazır olma durumunu denetleme
function updatePage() { |
Bu değişiklik, sunucunun gerçekten işlemi tamamlayıp tamamlamadığından emin olmak için bir denetim gerçekleştirir. Ajax kodunun bu sürümünü çalıştırmayı denediğinizde, olması gerektiği gibi yalnızca bir defa uyarı iletisi alırsınız.
Liste 13'teki kodun başarılı görünmesine rağmen, hâlâ bir sorunumuz var -- sunucu isteğinize yanıt verip işlemi bitirir, ancak bir hata raporu verirse ne olacak? Unutmayın, Ajax, JSP, kurallara uygun bir HTML formu ya da başka bir kod tipi tarafından çağrılıyorsa, bununla sunucu tarafındaki kod ilgilenmelidir; sunucu tarafı kodunuz bilgileri raporlamak için yalnızca geleneksel Web'e özel yöntemlere sahiptir. Web dünyasında, HTTP kodları bir istekte ortaya çıkabilecek çeşitli sorunlarla ilgilenebilir.
Örneğin, bir URL için istek girdiniz, URL'yi yanlış yazdınız ve böyle bir sayfanın olmadığını belirten bir 404 hata kodu aldınız. Bu, HTTP isteklerinin durum olarak alabileceği birçok durum kodlarından yalnızca biridir (durum kodlarının tam listesine giden bir bağlantı için Kaynaklar'a bakın). Güvenli ya da yasak verilere erişildiğini belirten 403 ve 401 hata kodları da oldukça yaygındır. Bu durumların her birinde, bu kodlar tamamlanmış bir yanıtın sonucudur. Diğer bir deyişle, sunucu isteği tamamlamıştır (HTTP hazır olma durumu 4'tür), ancak istemcinin beklediği verileri döndürmüyor olabilir.
Daha sonra, hazır olma durumuna ek olarak HTTP durumunu da denetlemeniz gerekir. Her şeyin tamam olduğunu belirten 200 durum kodunu arıyorsunuz. Hazır olma durumu 4 ve durum kodu 200 olduğunda, sunucu verilerini işleyebilirsiniz ve bu veriler, tam olarak istedikleriniz olmalıdır (bunlar bir hata ya da diğer sorun bildiren bilgi parçaları olmamalıdır). Geri çağrı yönteminize Liste 14'te gösterilen başka bir durum denetimi ekleyin.
Liste 14. HTTP durum kodunu denetleme
function updatePage() { |
Daha sağlam bir hata işleme özelliği eklemek için -- kodları çok karmaşıklaştırmadan -- diğer durum kodları için bir ya da iki denetim ekleyebilirsiniz; Liste 15'teki değiştirilmiş updatePage()
örneğine bakın.
Liste 15. Birkaç küçük hata denetimi ekleme
function updatePage() { |
Şimdi getCustomerInfo()
yöntemindeki URL'yi değiştirin ve var olmayan bir URL yazıp ne olduğuna bakın. İstediğiniz URL'nin var olmadığını belirten bir uyarı görmelisiniz -- mükemmel! Bu, belki bütün hata koşullarını kapsamaz, ancak tipik bir Web uygulamasında ortaya çıkabilecek sorunların yaklaşık %80'ini kapsayan basit bir değişikliktir.
İsteğinizin tam olarak işlendiğinden (hazır olma durumu yoluyla) ve sunucunun olağan, olumlu bir yanıt verdiğinden (durum kodu yoluyla) emin olduğunuza göre, artık sunucudan geri gönderilen verilerle uğraşabilirsiniz. Bu, uygun bir şekilde XMLHttpRequest
nesnesinin responseText
özelliğinde saklanır.
responseText
içindeki metnin biçim ya da uzunluk bakımından nasıl göründüğüne ilişkin ayrıntılar özellikle belirsiz bırakılmıştır. Bu, sunucunun bu metni hemen her şeye ayarlayabilmesini sağlar. Örneğin, bir komut dosyası birbirinden virgülle ayrılmış değerler döndürürken, bir diğeri birbirinden dikey çubukla ayrılmış (dikey çubuk |
karakteridir) değerler, bir başkası da uzun bir metin dizisi döndürebilir. Hepsi de sunucuya bağlıdır.
Bu makalede kullanılan örnekte, sunucu müşterinin son siparişini ve adresini, dikey çubukla birbirinden ayrılmış bir şekilde döndürür. Sipariş ve adres, form üzerindeki öğelerin değerlerini ayarlamak için kullanılır; Liste 16'da görüntüyü güncelleyen kod gösterilmektedir.
Liste 16. Sunucunun yanıtını işleme
function updatePage() { |
Önce, responseText
çekilir ve JavaScript split()
yöntemi kullanılarak dikey çubuk simgesiyle ayrılır. Ortaya çıkan değer dizisi response
içine aktarılır. İlk değere (müşterinin son siparişi) dizide response[0]
olarak erişilir ve "order" (sipariş) tanıtıcısının bulunduğu alanın değeri olarak ayarlanır. Dizideki ikinci değer olan response[1]
, müşterinin adresidir ve daha az işlem gerektirir. Adres satırları birbirinden normal satır ayıcılarla ("n" karakteri) ayrıldığı için, kodun bunları XHTML stilindeki satır ayırıcılarla (<br />
) değiştirmesi gerekir. Bu, uygun bir ifade ile replace()
işlevinin kullanılmasıyla gerçekleştirilir. Son olarak, değiştirilen metin HTML formunda div
parametresinin iç HTML'i olarak ayarlanır. Sonuçta form, Şekil 4'teki gibi birden bire müşterinin bilgileriyle güncellenir.
Şekil 4. Müşteri verileri alındıktan sonra Break Neck formu
Toparlamadan önce, XMLHttpRequest
nesnesinin responseXML
adı verilen başka bir önemli özelliğinden söz etmek istiyorum. Bu özellik, sunucunun XML ile yanıt vermesi durumunda bir XML yanıtını içerir (tahmin edebilir miydiniz?). Bir XML yanıtıyla çalışma, düz metinle çalışmaktan biraz daha farklıdır ve ayrıştırma, DOM (Document Object Model; Belge Nesne Modeli) ve diğer bazı konuları da içerir. Sonraki bir makalede XML ile ilgili ayrıntılı bilgi verilecektir. Yine de responseXML
özelliği responseText
çevresinde toplanan tartışmalarla geldiği için burada sözü edilebilir. Birçok basit Ajax uygulamasında, tek ihtiyacınız olan responseText
özelliğidir, ancak yakında Ajax uygulamalarında XML ile çalışmayı da öğreneceksiniz.
XMLHttpRequest
nesnesinden biraz sıkılmış olabilirsiniz -- tek bir nesneyle ilgili bir makalenin tamamını, özellikle de nesne bu kadar basitse, genellikle okumam. Ancak, bu nesneyi yazdığınız ve Ajax kullanan her sayfada ve uygulamada defalarca kullanacaksınız. Doğruyu söylemek gerekirse, hâlâ XMLHttpRequest
nesnesiyle ilgili anlatılacak birkaç şey var. Sonraki makalelerde, isteklerinizde GET
ile birlikte POST
kullanımını, sunucudan gelen yanıtın yanı sıra isteğinizde içerik üstbilgileri belirleme ve okumayı da öğreneceksiniz; isteklerinizi nasıl kodlamanız gerektiğini ve istek/yanıt modelinizde XML'lerin nasıl işleneceğini anlayacaksınız.
Ayrıca, sık kullanılan Ajax araç takımlarından bazılarını da göreceksiniz. Bu araç takımları aslında bu makalede anlatılan ayrıntıların çoğunu aydınlatır ve Ajax programlamasını kolaylaştırır. Araç takımları bu kadar hazır elinizin altındayken, tüm bu düşük düzeyli ayrıntıları neden kodlamanız gerektiğini merak edebilirsiniz. Bunun yanıtı, uygulamanızda neyin çalıştığını bilmezseniz, neyin yanlış gittiğini de bilemeyeceğiniz olacaktır.
Bu nedenle, bu ayrıntıları atlamayın ya da hızlı geçmeyin; böylece elinizin altındaki hazır araç takımında bir hata oluştuğunda, kafanızı kaşıyıp destek için e-posta göndermenize gerek kalmaz. XMLHttpRequest
nesnesinin doğrudan nasıl kullanılacağını anladığınızda, en garip sorunlarda hata ayıklamak, hatta sorunu düzeltmek sizin için çok kolay olacaktır. Araç takımları, tüm sorunlarınızla onların ilgilenmelerine güvenmediğiniz sürece yararlıdır.
Öyleyse, XMLHttpRequest
nesnesini iyice tanıyın. Aslında, bir araç takımı kullanan çalışan bir Ajax kodunuz varsa, bu kodu yalnızca XMLHttpRequest
nesnesiyle, ve bunun özellikleri ve yöntemleriyle yeniden yazmayı deneyin. Bu sizin için iyi bir alıştırma olacaktır ve neler olup bittiğini çok daha iyi anlamanızı sağlayacaktır.
Sonraki makalede, bu nesneyle ilgili daha derin konulara gireceğiz, POST
isteklerinin nasıl kullanılacağını ve birkaç farklı biçimde veri göndermeyi öğrenmenin yanı sıra bu nesnenin daha becerikli özelliklerini (responseXML
gibi) keşfedeceğiz. Bu nedenle şimdi kodlamaya başlayın ve bir ay kadar sonra buraya yeniden göz atın.
Bilgi Edinme
- Mastering Ajax: Introduction to Ajax (Ajax Konusunda Uzmanlaşma: Ajax'a Giriş) (developerWorks, Aralık 2005), Web siteleri oluşturmak için verimli bir yaklaşım olan Ajax'ı anlamanızı sağlar. (Bu makalenin kaynak listesi, tek başına ziyaret etmeye değer!)
- "Use Ajax with WebSphere Portal" (Ajax'ın WebSphere Portal ile kullanılması) (developerWorks, Haziran 2006), portal performansını artırmak, daha temiz bir portal uygulaması mimarisi ve -- en önemlisi -- kullanıcılarınıza çok daha hızlı yanıt veren bir portal yaratmak için.
- Building Dynamic Java Applications (Dinamik Java Uygulamalarının Oluşturulması) (developerWorks, Eylül 2005), Java bakış açısıyla Ajax'a sunucu tarafından bir bakış.
- Java object serialization for Ajax (Ajax için Java nesnesi diziselleştirmesi) (developerWorks, Ekim 2005), ağ üzerinden nesne gönderme ve Ajax ile etkileşimde bulunma konularını Java bakış açısıyla inceler.
- Call SOAP Web services with Ajax (Ajax ile SOAP Web hizmetlerinin çağrılması) (developerWorks, Ekim 2005), Ajax'ı var olan SOAP tabanlı Web hizmetleriyle bütünleştirme üzerine yazılmış ileri düzey bir makaledir.
- Google GMail, Web'in çalışma şeklini değiştiren, Ajax tabanlı uygulamalara harika bir örnektir.
- Google Maps, başka bir Google tabanlı Web 2.0 uygulamasıdır.
- Flickr, Web tabanlı bir uygulama için masaüstü görünümü oluşturmak için Ajax'ın kullanıldığı harika bir örnektir.
- Ajax: A New Approach to Web Applications (Ajax: Web Uygulamalarına Yeni Bir Yaklaşım), Ajax moniker teriminin ilk kez kullanıldığı ve tüm Ajax geliştiricilerinin okuması gereken bir makaledir.
- Why Ajax Matters Now (Ajax Neden Bu Kadar Önemli), Ajax'ın (şimdi) neden bu kadar önemli olduğunu anlamanıza yardımcı olacaktır.
- Microsoft'un tarayıcısı olan Internet Explorer'ı kullanıyorsanız, Microsoft Developer Network's XML Developer Center (Microsoft Geliştirici Ağı XML Geliştirme Merkezi) olanağından haberleri alabilirsiniz.
- Microsoft XML ayrıştırıcısıyla (MSXML) ilgili ek bilgiye çevrimiçi belgelerden ulaşın.
- Bir yanıtın içerebileceği tüm HTTP durum kodlarını içeren bu listeye göz atın.
- DeveloperWorks Web Mimarisi alanı, çeşitli Web tabanlı çözümleri kapsayan makaleleri içerir.
Ürün ve teknoloji edinme
- Head Rush Ajax, Elisabeth Freeman, Eric Freeman ve Brett McLaughlin (Şubat 2006, O'Reilly Media, Inc.), bu makaledeki düşünceleri alır ve Head First stilinde beyninize yükler.
- Java and XML, İkinci Basım, Brett McLaughlin (Ağustos 2001, O'Reilly Media, Inc.), yazarın XHTML ve XML dönüşümleriyle ilgili görüşlerini içerir.
- JavaScript: The Definitive Guide, David Flanagan (Kasım 2001, O'Reilly Media, Inc.), JavaScript, dinamik Web sayfalarıyla çalışmayla ilgili kapsamlı yönergeler içerir ve sonraki basımda Ajax ile ilgili iki yeni bölüm bulunur.
- Head First HTML with CSS & XHTML, Elizabeth ve Eric Freeman (Aralık 2005, O'Reilly Media, Inc.), XHTML, CSS ve bu ikisinin nasıl birlikte kullanılacağını öğrenmeyle ilgili eksiksiz bir kaynaktır.
Tartışma
- Tartışma forumuna katılın.
- developerWorks Web günlükleri: DeveloperWorks topluluğuna katılın.
Brett McLaughlin, Logo günlerinden bu yana bilgisayarlarla ilgili çalışmalar yapmaktadır (Küçük üçgeni hatırlıyor musunuz?) Son yıllarda, Java ve XML topluluklarında en çok tanınan yazarlardan ve programcılardan biri oldu. Kendisi, Nextel Communications şirketi için karmaşık kurumsal sistemler uygulaması, Lutric Technologies için uygulama sunucuları yazma görevlerini üstlendi ve en son O'Reilly Media, Inc. için önemli kitaplar yazma ve yayına hazırlama işlerini yürütüyor. Brett'in, en çok satan yazarlar listesinde yer alan Eric ve Beth Freeman ile birlikte hazırladığı yeni kitabı Head Rush Ajax, Ajax'a Head First adlı ödüllü ve yenilikçi bir yaklaşım getiriyor. Son kitabı Java 1.5 Tiger: A Developer's Notebook, Java teknolojisinin en son sürümüyle ilgili ilk kitap olma özelliğini taşıyor ve artık bir klasik olan Java and XML adlı kitabı, Java dilinde XML teknolojilerinin kullanılması üzerine en açıklayıcı çalışma olmaya devam ediyor. |
Kaynak www.fazlamesai.net/index.php