Ajax被认为是(Asynchronous JavaScript and XML的缩写。现在允许浏览器与服务器通信而无须刷新当前页面的技术都被叫做Ajax


什么是Ajax?

    不用刷新整个页面便可与服务器通讯的办法

    Flash

    Java applet

    框架如果使用一组框架构造了一个网页可以只更新其中一个框架而不必惊动整个页面

    隐藏的iframe

    XMLHttpRequest该对象是对 JavaScript 的一个扩展可使网页与服务器进行通信。是创建 Ajax 应用的最佳选择。实际上通常把 Ajax 当成 XMLHttpRequest 对象的代名词 

    

Ajax工作原理

    Ajax的核心是JavaScript对象XmlHttpRequest。

    该对象在Internet Explorer 5中首次引入它是一种支持异步请求的技术。简而言之XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应而不阻塞用户。

    AJAX采用异步交互过程。AJAX在用户与服务器之间引入一个中间媒介从而消除了网络交互过程中的处理—等待—处理—等待缺点。

    用户的浏览器在执行任务时即装载了AJAX引擎。AJAX引擎用JavaScript语言编写通常藏在一个隐藏的框架中。它负责编译用户界面及与服务器之间的交互。

    AJAX引擎允许用户与应用软件之间的交互过程异步进行独立于用户与网络服务器间的交流。现在可以用Javascript调用AJAX引擎来代替产生一个HTTP的用户动作内存中的数据编辑、页面导航、数据校验这些不需要重新载入整个页面的需求可以交给AJAX来执行。 


Ajax包含的技术

      AJAX:(Asynchronous JavaScript and XML)并不是一项新技术,其实是多种技术的综合包括Javascript、XHTML和CSS、DOM、XML和XMLHttpRequest.

    服务器端语言服务器需要具备向浏览器发送特定信息的能力。Ajax与服务器端语言无关。

    XML (eXtensible Markup Language可扩展标记语言) 是一种描述数据的格式。AJAX 程序需要某种格式化的格式来在服务器和客户端之间传递信息XML 是其中的一种选择

    XHTMLeXtended Hypertext Markup Language,使用扩展超媒体标记语言和 CSSCascading Style Sheet,级联样式单标准化呈现

    DOMDocument Object Model,文档对象模型实现动态显示和交互

    使用XMLHTTP组件XMLHttpRequest对象进行异步数据读取

    使用JavaScript绑定和处理所有数据


Ajax缺陷

    AJAX不是完美的技术。也存在缺陷

    1.AJAX大量使用了Javascript和AJAX引擎而这个取决于浏览器的支持。IE5.0及以上、Mozilla1.0、NetScape7及以上版本才支持Mozilla虽然也支持AJAX但是提供XMLHttpRequest的方式不一样。所以使用AJAX的程序必须测试针对各个浏览器的兼容性。 

    2.AJAX更新页面内容的时候并没有刷新整个页面因此网页的后退功能是失效的有的用户还经常搞不清楚现在的数据是旧的还是已经更新过的。这个就需要在明显位置提醒用户“数据已更新”。 

    3.对流媒体的支持没有FLASH、Java Applet好。 

    4.一些手持设备如手机、PDA等现在还不能很好的支持Ajax。



XMLHttpRequest对象  

    1.XMLHttpRequest是XMLHTTP组件的对象通过这个对象AJAX可以像桌面应用程序一样只同服务器进行数据层面的交换而不用每次都刷新界面也不用每次将数据处理的工作都交给服务器来做这样既减轻了服务器负担又加快了响应速度、缩短了用户等待的时间。 

    2.XMLHttpRequest最早是在IE5中以ActiveX组件的形式实现的。非W3C标准.

    3.创建XMLHttpRequest对象由于非标准所以实现方法不统一

        1.Internet Explorer把XMLHttpRequest实现为一个ActiveX对象

        2.其他浏览器Firefox、Safari、Opera…把它实现为一个本地的JavaScript对象。

        3.XMLHttpRequest在不同浏览器上的实现是兼容的所以可以用同样的方式访问                    XMLHttpRequest实例的属性和方法而不论这个实例创建


Ajax返回的数据格式


    在服务器端 AJAX 是一门与语言无关的技术。在业务逻辑层使用何种服务器端语言都可以。

从服务器端接收数据的时候那些数据必须以浏览器能够理解的格式来发送。服务器端的编程语言只能以如下 3 种格式返回数据

  1.XML  

    如果文档来自于服务器就必须得保证文档含有正确的首部信息。若文档类型不正确那么 responseXML 的值将是空的。

    优点

        XML 是一种通用的数据格式。

        不必把数据强加到已定义好的格式中而是要为数据自定义合适的标记。

        利用 DOM 可以完全掌控文档。

    缺点

        当浏览器接收到长的 XML 文件后 DOM 解析可能会很复杂

    

  2.JSON

    JSONJavaScript Object  Notation一种简单的数据格式比xml更轻巧。JSON是JavaScript原生格式这意味着在JavaScript中处理JSON数据不需要任何特殊的API或工具包。 

    JSON的规则很简单对象是一个无序的“‘名称/值’对”集合。一个对象以“{”左括号开始“}”右括号结束。每个“名称”后跟一个“:”冒号“‘名称/值’对”之间使用“,”逗号分隔。

       规则如下:

           1映射用冒号“”表示。名称:值

           2并列的数据之间用逗号“”分隔。名称1:值1,名称2:值2

           3 映射的集合对象用大括号“{}”表示。{名称1:值1,名称2:值2}

           4 并列数据的集合数组用方括号(“[]”)表示。

             [

               {名称1:值,名称2:值2},

               {名称1:值,名称2:值2}

             ]

          5  元素值可具有的类型string, number, object, array, true, false, null 


  3.HTML


     HTML 由一些普通文本组成。如果服务器通过 XMLHttpRequest 发送 HTML 文本将存储在 responseText 属性中。

    不必从 responseText 属性中读取数据。它已经是希望的格式可以直接将它插入到页面中。

    插入 HTML 代码最简单的方法是更新这个元素的 innerHTML 属性。



1.传统方式实现ajax

(1)获取XMlHttpRequest对象

(2)设置监听,处理响应

(3)开启连接

(4)发送请求

 

2.利用jquery实现ajax

load()

$.get()

$.post(url,[data],[callback],[type])

 

3.ajax返回数据的格式:xml/html/json

json:javascript的原生格式,javascript直接可以访问其中数据


 

传统方式实现AJAX

//1 创建XMLHttpRequest对象

function ajaxFunction(){

   var xmlHttp;

   try{ // Firefox, Opera 8.0+, Safari

        xmlHttp=new XMLHttpRequest();

    }

    catch (e){

   try{// Internet Explorer

         xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");

      }

    catch (e){

      try{

         xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");

      }

      catch (e){}

      }

    }


return xmlHttp;

 }

 

//2.服务器端向客户端进行响应(注册监听)

var data = null;

var xhr = ajaxFunction();

xhr.onreadystatechange=function(){

if(xhr.readyState==4){

if(xhr.status==200||xhr.status==304){

data = xhr.responseText;

}

}

}

 

 

readyState 属性表示Ajax请求的当前状态。它的值用数字代表。

0 代表未初始化。 还没有调用 open 方法

1 代表正在加载。 open 方法已被调用,但 send 方法还没有被调用

2 代表已加载完毕。send 已被调用。请求已经开始

3 代表交互中。服务器正在发送响应

4 代表完成。响应发送完毕


xhr.status

常用状态码及其含义:

404 没找到页面(not found)

403 禁止访问(forbidden)

500 内部服务器出错(internal service error)

200 一切正常(ok)

304 没有被修改(not modified)(服务器返回304状态,表示源文件没有被修改 )


xhr.responseText 服务器发回的响应结果,字符串

xhr.responseXML 服务器返回的响应结果,XML对象

 

 

//3 客户端与服务器端建立连接

/* 使用的是XMLHttpRequest对象的open(method, url, asynch)方法

* method:请求类型,类似 “GET””POST”的字符串。

* url:路径字符串,指向你所请求的服务器上的那个文件。可以是绝对路径或相对路径。

*asynch:表示请求是否要异步传输,默认值为true(异步)*/

xhr.open("GET","../testServlet?timeStamp="+new Date().getTime()+"&c=19",true);

 

//4 客户端向服务器端发送请求

/*

* 使用的是XMLHttpRequest对象的send()方法

* 如果请求类型是GET方式的话,使用send()方法发送请求数据,服务器端接收不到

* 该步骤不能被省略,只能写成xhr.send(null);

*/

 

 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");


~GET方式:

xhr.send(null);//xhr.send(null);

 

~POST方式:如果请求类型是POST的话,需要设置请求数据信息

xhr.send("a=7&b=8");

 


 

 

JQUERT方式的AJAX

$.post(url,[data],[callback],[type])

<script>

 //--全局计数器,记录当前页面显示到了哪条记录

 //参数c为当前页面显示到了哪条记录,服务器只要发送这条记录之后的数据就可以了

 var c = 0;

 //--100毫秒触发ajax,访问服务器,获取聊天信息

 window.setInterval(ref, 100);

 function ref(){

   $.post("${pageContext.request.contextPath}/servlet/RefChat",

           {count:c},function(data){

  //返回的数据中以json格式保存了聊天信息格式为[{msg:'msg',time:'time',uname:'uname',pos:'pos'},{另一条记录},....]

 $(eval("("+data+")")).each(function(i,ele){

c=ele.pos;

 //--循环的过程中保存显示到了哪条记录,这样循环结束后c的值就是当前显示的最后一条记录的pos

 //显示当前记录

   var tr = $("<tr><td width='20%'>"+ele.uname+"</td>

                                   <td>"+ele.msg+"</td>

                           <td width='20%'>"+ele.time+"</td></tr>");

    $(tr).appendTo($("#tbd"));

});

});

  //滚动条置底

document.getElementById('cdiv').scrollTop=document.getElementById('cdiv').scrollHeight ;

}


 //--点击提交按钮时,获取当前输入框中的值发送ajax请求,发送聊天数据,清空输入框

$("#but").click(function(){

var text = $("#tent").val(); //输入框的值

$.post("${pageContext.request.contextPath}/servlet/ChatMsg",

                     {msg:text}); //将输入框的值发送到servlet上处理

$("#tent").val(""); //清空输入框的值

});


</script>

 

<form action="#">

<textarea rows="5px" cols="60px" name="content" id="tent"></textarea>

<input type="button" id="but" value="提交">

</form>

 

public class RefChat extends HttpServlet {

 

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

request.setCharacterEncoding("utf-8");

response.setContentType("text/html;charset=utf-8");

ServletContext context = this.getServletContext();


//--获取聊天信息chatmap

Map<Integer,ChatItem> chatmap = (Map<Integer, ChatItem>) context.getAttribute("chatmap");

if(chatmap == null){

//--如果聊天信息为空,返回空的json

response.getWriter().write("[]");

return;

}else{

//--如果聊天信息不为空,则发送聊天信息

//获取浏览器需要哪条记录之后的记录

Integer count = Integer.parseInt(request.getParameter("count")==null?"0" : request.getParameter("count"));

//组织json数据,将count记录之后的聊天记录组织为json格式

StringBuffer buffer = new StringBuffer();

buffer.append("[");

synchronized (chatmap) {

for(Map.Entry<Integer, ChatItem> entry : chatmap.entrySet()){

if(entry.getKey()>count){

buffer.append(entry.getValue());

buffer.append(",");

}

}

}

String msgs = buffer.substring(0, buffer.length()-1)+"]";

//发送聊天数据

response.getWriter().write(msgs);

}

}

 

public class ChatMsg extends HttpServlet {

 

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

request.setCharacterEncoding("utf-8");

response.setContentType("text/html;charset=utf-8");

ServletContext context = this.getServletContext();


//获取历史信息

Integer count = (Integer)context.getAttribute("count") == null

? 0 : (Integer)context.getAttribute("count") ;

Map<Integer,ChatItem> chatmap = (Map<Integer, ChatItem>) context.getAttribute("chatmap") == null

?  Collections.synchronizedMap(new LinkedHashMap<Integer, ChatItem>())

:(Map<Integer, ChatItem>) context.getAttribute("chatmap");

//组织javabean信息

ChatItem item = new ChatItem();

count = count + 1;

item.setPos(count+"");

item.setTime(new Date().toLocaleString());

item.setUname(filter(

((String)request.getSession().getAttribute("name")==null

? "ip:"+request.getRemoteAddr()

: "uname:"+(String) request.getSession().getAttribute("name")))

);

item.setMsg(filter(request.getParameter("msg")));


//将信息加入chatmap

synchronized (chatmap) {

chatmap.put(count, item);

}


//存回ServletContext

context.setAttribute("count", count);

context.setAttribute("chatmap", chatmap);

}


/**

 * json格式的特殊字符进行转义

 */

  private static String filter(String message) {

 

        if (message == null)

            return (null);

 

        char content[] = new char[message.length()];

        message.getChars(0, message.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);

        for (int i = 0; i < content.length; i++) {

            switch (content[i]) {

            case '<':

                result.append("<");

                break;

            case '>':

                result.append(">");

                break;

            case '&':

                result.append("&");

                break;

            case '\\':

            result.append("\\\\");

                break;

            case '/':

            result.append("\\/");

                break;

            case '"':

            result.append("\\\"");

                break;    

            case '\'':

            result.append("\\'");

            break;

            case '\t':

            result.append("\\t");

                break;

            case '\f':

            result.append("\\f");

                break;

            case '\b':

            result.append("\\b");

                break;

            case '\n':

            result.append("\\n");

                break;

            case '\r':

            result.append("\\r");

                break;

            default:

                result.append(content[i]);

            }

        }

        return (result.toString());

 

    }