这个Demo是通过POST方法向服务器请求天气xml,本来也想直接访问google的天气xml接口,但是这也涉及到跨域(跨域知识前一篇有讲解),只能作罢,没办法只好自己用.NET写了一个模拟的服务器。
通过本例,展示了如下技术:
l 利用AJAX向服务器POST请求。
l 利用javascript解析xml数据。
l 利用javascript更改html界面显示。
Demo概要说明:
服务器端有一个ashx服务文件,客户端通过AJAX技术向服务文件POST请求信息,如果信息正确,服务文件将读取同目录下的xml文件,返回给客户端。
客户端index.html为展示页面,调用ajax.js完成AJAX请求,并解析返回的xml在界面上显示。
具体代码:
Html代码(index.html):
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <title>POST方式获取天气信息演示</title> 6 <script type="text/javascript" language="javascript" src="ajax.js"></script> 7 </head> 8 <body> 9 <div id="frmMain"> 10 <ul id="weatherInfo"></ul> 11 <input name="btnGet" value="获取天气信息" onclick="javascript:googleWeather();" type="button" /> 12 </div> 13 14 </body> 15 </html>
AJAX脚本(ajax.js):
1 function googleWeather() { 2 //根据浏览器类型创建不同的XMLHttpRequest对象 3 var xmlHttp; 4 if (window.XMLHttpRequest) { 5 xmlHttp = new XMLHttpRequest(); 6 } else { 7 xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 8 } 9 10 //绑定http请求响应完成之后的回调函数 11 //注意:我是为了方便新人学习才写这么分散的,其实很多东西都可以连着写 12 xmlHttp.onreadystatechange = function () { 13 //判断是否响应完成 14 //readyState == 4 表示响应完成 15 //status == 200 表示请求成功 16 if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { 17 //获取服务器端返回的xml格式数据 18 //获取xml格式数据responseXML,获取文本格式数据responseText 19 var xml = xmlHttp.responseXML; 20 //获取xml中的当日天气信息 21 //getElementsByTagName返回的是数组,考虑到xml只有一个current_conditions元素,因此直接取数组第0个元素 22 var currentWeather = xml.getElementsByTagName("current_conditions")[0]; 23 //获取当日天气元素 24 var conditionNode = currentWeather.getElementsByTagName("condition")[0]; 25 //获取当日天气值。getAttribute()方法可以获取元素的某个属性值。 26 var conditionData = conditionNode.getAttribute("data"); 27 //获取当日湿度元素 28 var humidityNode = currentWeather.getElementsByTagName("humidity")[0]; 29 //获取当日湿度值 30 var humidityData = humidityNode.getAttribute("data"); 31 //获取当日风向元素 32 var wind_conditionNode = currentWeather.getElementsByTagName("wind_condition")[0]; 33 //获取当日风向值 34 var wind_conditionData = wind_conditionNode.getAttribute("data"); 35 //获取界面上的ul元素 36 var ulNode = document.getElementById("weatherInfo"); 37 //将三个值显示在ul中 38 ulNode.innerHTML += "<li>" + conditionData + "</li>"; 39 ulNode.innerHTML += "<li>" + humidityData + "</li>"; 40 ulNode.innerHTML += "<li>" + wind_conditionData + "</li>"; 41 } 42 }; 43 44 //构造请求参数 45 //第一个参数指定为POST方式请求 46 //第二个参数是请求的url地址 47 //第三个参数是指是否异步,true为异步 48 xmlHttp.open("POST", "weather/api.ashx", true); 49 //构造http头,Content-type是个非常重要的头,如果不设置,服务器可能无法解析参数 50 xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 51 //发送请求 52 //post方式方式请求,参数要写在send方法里。get方式直接把参数写在url上即可 53 xmlHttp.send("hl=cn&weather=beijing"); 54 }
服务文件(api.ashx):
1 <%@ WebHandler Language="C#" Class="api" %> 2 3 using System; 4 using System.Web; 5 6 public class api : IHttpHandler { 7 8 public void ProcessRequest (HttpContext context) { 9 //返回数据类型一定要设置正确,text/xml代表返回xml格式的数据 10 context.Response.ContentType = "text/xml"; 11 12 //判断post参数是否正确 13 if (context.Request.Form["hl"] != null && context.Request.Form["hl"].ToString().ToLower() == "cn") 14 { 15 if (context.Request.Form["weather"] != null && context.Request.Form["weather"].ToString().ToLower() == "beijing") 16 { 17 //参数正确则返回xml格式的天气信息。 18 //weather.xml文件与该服务文件在同一目录下,天气信息保存在这个文件中 19 context.Response.WriteFile("weather.xml"); 20 } 21 } 22 } 23 24 public bool IsReusable { 25 get { 26 return false; 27 } 28 } 29 30 }
天气xml文件(weather.xml):
1 <?xml version="1.0" encoding="utf-8"?> 2 <xml_api_reply version="1"> 3 <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0"> 4 <forecast_information> 5 <city data="beijing" /> 6 <postal_code data="beijing" /> 7 <latitude_e6 data="" /> 8 <longitude_e6 data="" /> 9 <forecast_date data="2009-07-31" /> 10 <current_date_time data="2009-07-31 16:32:12 +0000" /> 11 <unit_system data="SI" /> 12 </forecast_information> 13 <current_conditions> 14 <condition data="晴" /> 15 <temp_f data="79" /> 16 <temp_c data="26" /> 17 <humidity data="湿度: 65%" /> 18 <icon data="/ig/images/weather/sunny.gif" /> 19 <wind_condition data="风向: 东、风速:2 米/秒" /> 20 </current_conditions> 21 <forecast_conditions> 22 <day_of_week data="周五" /> 23 <low data="16" /> 24 <high data="31" /> 25 <icon data="/ig/images/weather/chance_of_rain.gif" /> 26 <condition data="可能有雨" /> 27 </forecast_conditions> 28 <forecast_conditions> 29 <day_of_week data="周六" /> 30 <low data="22" /> 31 <high data="31" /> 32 <icon data="/ig/images/weather/chance_of_storm.gif" /> 33 <condition data="可能有暴风雨" /> 34 </forecast_conditions> 35 <forecast_conditions> 36 <day_of_week data="周日" /> 37 <low data="19" /> 38 <high data="29" /> 39 <icon data="/ig/images/weather/chance_of_storm.gif" /> 40 <condition data="可能有暴风雨" /> 41 </forecast_conditions> 42 <forecast_conditions> 43 <day_of_week data="周一" /> 44 <low data="23" /> 45 <high data="32" /> 46 <icon data="/ig/images/weather/chance_of_rain.gif" /> 47 <condition data="可能有雨" /> 48 </forecast_conditions> 49 </weather> 50 </xml_api_reply>
代码中注释非常详细,相信读者能够领会整个过程。
补充说明:
在这个Demo中,小菜要着重说下Http协议的头部信息。在js代码中有这样一句话:xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");这个就是设置Http头部信息中的解析类型(Content-type)。
头部信息包括了很多东西,比如Host、Referer、cookie等,这些信息可以理解为请求的一些参数,用来在服务器端识别。
头部信息很重要,尤其是以POST方式请求数据时,头部信息未设置或者不正确,很可能出现一些莫名其妙的错误,甚至是请求直接被服务器拒绝。
举个例子,假如A页面上有一个链接,点击后跳转到B页面,假如我们直接用POST请求B页面,跳过了A页面,很可能被服务器拒绝,这时候就要设置一下Http头信息,xmlHttp.setRequestHeader(“Referer”,”A页面URL”);这样一来,就可以伪装成从A页面跳转过来的。
再说说POST和GET在AJAX中的区别。如果使用GET方式请求数据,参数直接写在url后边即可,例如:api.ashx?hl=cn&weather=beiijng;而如果是用POST方式,参数要写在send方法中,例如xmlHttp.send(“hl=cn&weather=beijing”);。另外,使用POST方法要多关注Http头信息。
关于POST和GET方式各自的特点,请读者自行google。
附: