首页 > Web开发 > 详细

[转载]Ajax与JSON的一些总结

时间:2019-11-25 10:14:02      阅读:115      评论:0      收藏:0      [点我收藏+]

[转载]Ajax与JSON的一些总结

作者:JK_Rush【 http://www.cnblogs.com/rush/ 】

大早上看到的一篇好文章,因为最近在学习所以关注了,截取了一部分我可以理解的并加了一些自己的内容,蛮适合初学者看一下。

一、 摘要

Ajax【ASynchronous JavaScript And XML】技术的核心是XMLHttpRequest对象(简称XHR),可以通过使用XHR对象获取到服务器的数据,然后再通过DOM将数据插入到页面中呈现。虽然名字中包含XML,但Ajax通讯与数据格式无关,所以我们的数据格式可以是XML或JSON【JavaScript Object Notation】等格式。

XMLHttpRequest对象用于在后台与服务器交换数据,具体作用如下:

  • 在不重新加载页面的情况下更新网页
  • 在页面已加载后从服务器请求数据
  • 在页面已加载后从服务器接收数据
  • 在后台向服务器发送数据

  • https://www.cnblogs.com/rush/archive/2012/05/15/2502264.html#lb4)

二、正文

XMLHttpRequest是一个JavaScript对象,它是由微软设计,并且被Mozilla、Apple和Google采纳,W3C正在标准化它。它提供了一种简单的方法来检索URL中的数据。

我们要创建一个XMLHttpRequest实例,只需new一个就OK了:

//// Creates a XMLHttpRequest object.
var req = new XMLHttpRequest();

也许有人会说:“这可不行啊!IE6不支持原始的XHR对象”,确实是这样,我们在后面将会介绍支持IE6或更老版本创建XHR对象的方法。

1、XMLHttpRequest的用法

在创建XHR对象后,接着我们要调用一个初始化方法open(),它接受五个参数具体定义如下:

void open(
   DOMString method, //"GET", "POST", "PUT", "DELETE"
   DOMString url,
   optional boolean async,
   optional DOMString user,
   optional DOMString password
);

通过上面的定义我们知道open()方法的签名包含五个参数,其中有参数method和url地址是必填的,假设我们针对URL: myxhrtest.aspx发送GET请求获取数据,具体定义如下:

var req = new XMLHttpRequest();

req.open(
    "GET",
    "myxhrtest.aspx",
    false
);

通过上述代码会启动一个针对myxhrtest.aspx的GET请求,这里有两点要注意:一是URL相对于执行代码的当前页面(使用绝对路径);二是调用open()方法并不会真正发送请求,而只是启动一个请求准备发送。

只能向同一个域中使用相同端口和协议的URL中发送请求;如果URL与启动请求的页面有任何差别,都会引发安全错误。

要真正发送请求要使用send()方法,send()方法接受一个参数,即要作为请求主体发送的数据,如果不需要通过请求主体发送数据,我们必须传递一个null值。在调用send()之后,请求就会被分派到服务器,完整Ajax请求代码如下:

var req = new XMLHttpRequest();

req.open(
    "GET",
    "myxhrtest.aspx",
    false
);
req.send(null);

在发送请求之后,我们需要检查请求是否执行成功,首先可以通过status属性判断,一般来说,可以将HTTP状态代码为200作为成功标志。这时,响应主体内容会保存到responseText中。此外,状态代码为304表示请求的资源并没有被修改,可以直接使用浏览器缓存的数据,Ajax的同步请求代码如下:

if (req != null) {
    req.onreadystatechange = function() {

        if ((req.status >= 200 && req.status < 300) || req.status == 304) {
            //// Do something.
        }
        else {
            alert("Request was unsuccessful: " + req.status);
        }
    };
    req.open("GET", "www.myxhrtest.aspx", true);
    req.send(null);
}

前面我们定义了Ajax的同步请求,如果我们发送异步请求,那么在请求过程中javascript代码会继续执行,这时可以通过readyState属性判断请求的状态,当readyState = 4时,表示收到全部响应数据,属性值的定义如下:

readyState值 描述
0 未初始化;尚未调用open()方法
1 启动;尚未调用send()方法
2 已发送;但尚未收到响应
3 接收;已经收到部分响应数据
4 完成;收到全部响应数据

? 表1 readyState属性值

同步请求:发生请求后,要等待服务器执行完毕才继续执行当前代码。

异步请求:发生请求后,无需等到服务器执行完毕,可以继续执行当前代码。

现在我们要增加判断readyState属性值,当readyState = 4时,表示全部数据接收完成, 所以Ajax的异步请求代码如下:

if (req != null) {
    req.onreadystatechange = function() {

        //// Checks the asyn request completed or not.
        if (req.readyState == 4) {
            if ((req.status >= 200 && req.status < 300) || req.status == 304) {
                //// Do something.
            }
            else {
                alert("Request was unsuccessful: " + req.status);
            }
        }
    };
    req.open("GET", "www.myxhrtest.aspx", true);
    req.send(null);
}

2、Ajax同源请求

现在我们对Ajax的请求实现有了初步的了解,接下来我们将通过具体的例子说明Ajax请求的应用场合和局限

在日常网络生活中,我们在浏览器的地址中输入要访问的URL并且回车,浏览器会向服务器发送请求,当服务器收到请求后,把相应的请求页面发送回浏览器,我们会发现页面大部分加载完毕,有些还没有加载完毕。总得来说,采用异步加载方式不会影响已加载完毕的页面浏览,我们可以通过Ajax实现异步加载。

这里我们以AdventureWorks数据库为例,把产品表(Product)中的数据通过报表呈现给用户,我们可以通过多种方法实现该报表需求,这里我们将通过Ajax实现该功能。

首先,我们要把后台数据转换为JSON格式,接下来我们定义Product表的数据库访问对象(DAO),具体的实现代码如下:

/// <summary>
/// The product datatable dao.
/// </summary>
public class ProductDao
{
    /// <summary>
    /// Initializes a new instance of the <see cref="ProductDao"/> class.
    /// </summary>
    public ProductDao()
    {
    }

    /// <summary>
    /// Gets or sets the product id.
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    /// Gets or sets the product name.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// Gets or sets the product serial number.
    /// </summary>
    public string SerialNumber { get; set; }

    /// <summary>
    /// Gets or sets the product qty.
    /// </summary>
    public short Qty { get; set; }
}

前面我们定义了Product表的数据库访问对象——ProductDao,它包含四个属性分别是产品的Id,名称,序列号和销售数量。

接下来,让我们实现Product表的数据库操作类。

/// <summary>
/// Product table data access manager.
/// </summary>
public class ProductManager
{
    /// <summary>
    /// The query sql.
    /// </summary>
    private const string Query = 
        "SELECT ProductID, Name, ProductNumber, SafetyStockLevel FROM Production.Product";

    /// <summary>
    /// Stores the object of <see cref="ProductDao"/> into list.
    /// </summary>
    private IList<ProductDao> _products = new List<ProductDao>();

    /// <summary>
    /// Gets all products in product table.
    /// </summary>
    /// <returns>
    /// The list of <see cref="ProductDao"/> object.
    /// </returns>
    public IList<ProductDao> GetAllProducts()
    {
        using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLCONN"].ToString()))
        using (var com = new SqlCommand(Query, con))
        {
            con.Open();
            using (var reader = com.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    var product = new ProductDao
                        {
                            Id = (int)reader["ProductID"],
                            Name = (string)reader["Name"],
                            SerialNumber = (string)reader["ProductNumber"],
                            Qty = (short)reader["SafetyStockLevel"]
                        };
                    _products.Add(product);
                }
            }
        }

        return _products;
    }
}

前面我们实现了Product表的数据库操作类——ProductManager,它包含两个私有字段Quey和_products,还有一个获取Product表中数据的方法——GetAllProducts()。

通过实现ProductDao和ProductManager,而且我们提供GetAllProducts()方法,获取Product表中的数据,接下来我们要调用该方法获取数据。

为了使数据通过JSON格式传递给页面,这里我们要创建一般处理程序(ASHX文件),

一般处理程序适用场合:

  • 创建动态图片
  • 返回REST风格的XML或JSON数据
  • 自定义HTML

技术分享图片

? 图1一般处理程序

把一般处理程序文件添加到项目中时,会添加一个扩展名为.ashx的文件,现在我们创建一个一般处理程序ProductInfo,具体代码如下:

<%@ WebHandler Language="C#" Class="ProductInfo" %>

using System.Runtime.Serialization.Json;
using System.Web;

using ASP.App_Code;

/// <summary>
/// The product data handler.
/// </summary>
public class ProductInfo : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {

        context.Response.ContentType = "application/json";

        // Creates a <see cref="ProductManager"/> oject.
        var manager = new ProductManager();

        // Invokes the GetAllProducts method.
        var products = manager.GetAllProducts();

        // Serializes data to json format.
        var json = new DataContractJsonSerializer(products.GetType());
        json.WriteObject(context.Response.OutputStream, products);
    }

    // Whether can resuable by other handler or not.
    public bool IsReusable {
        get {
            return false;
        }
    }
}

大家注意到ProductInfo类实现了IHttpHandler接口,该接口包含一个方法ProcessRequest()方法和一个属性IsReusable。ProcessRequest()方法用于处理入站的Http请求。在默认情况下,ProductInfo类会把内容类型改为application/json,然后我们把数据通过JSON格式写入输入流中;IsReusable属性表示相同的处理程序是否可以用于多个请求,这里我们设置为false,如果为了提高性能也可以设置为true。

如下图所示,我们通过ProductInfo类成功地实现获取数据到响应流中,并且以JSON格式显示出来。

技术分享图片

? 图2 Http请求

当我们请求ProductInfo时, 首先它会调用ProcessRequest()方法,接着调用GetAllProducts()方法从数据库中获取数据,然后把数据通过JSON格式写入到响应流中。

现在,我们已经成功地把数据通过JSON格式写入到响应流当中,接着我们将通过Ajax方式请求数据并且把数据显示到页面中。

首先,我们定义方法createXHR()用来创建XMLHttpRequest对象,前面我们提到IE6或者更老的版本不支持XMLHttpRequest()方法来创建XMLHttpRequest对象,所以我们要在createXHR()方法中,增加判断当前浏览器是否IE6或更老的版本,如果是,就要通过MSXML库的一个ActiveX对象实现。因此,在IE中可能遇到三种不同版本的XHR对象(MSXML2.XMLHttp6.0,MSXML2.XMLHttp3.0和MSXML2.XMLHttp)。

// Creates a XMLHttpRequest object bases on web broswer.
function createXHR() {

    // Checks whether support XMLHttpRequest or not.
    if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
    }

    // IE6 and elder version.
    else if (typeof ActiveXObject != "undefined") {
        if (typeof arguments.callee.activeXString != "string") {
            var versions = [
        "MSXML2.XMLHttp6.0",
        "MSXML2.XMLHttp3.0",
        "MSXML2.XMLHttp"];

            for (var i = 0; i < versions.length; i++) {
                try {
                    var xhr = new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    return xhr;
                }
                catch (ex) {
                    throw new Error(ex.toString());
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        }
        else {
            throw new Error("No XHR object available");
        }

    }
    return null;
}

$(document).ready(function() {
    GetDataFromServer();
});
function GetDataFromServer() {

    // Creates a XMLHttpRequest object.
    var req = new createXHR();
      
    if (req != null) {
        req.onreadystatechange = function() {
            if (req.readyState == 4) {
                if ((req.status >= 200 && req.status < 300) || req.status == 304) {
                    ////alert(req.responseText);
                    var jsonTextDiv = document.getElementById("jsonText");

                    // Deserializes JavaScript Object Notation (JSON) text to produce a JavaScript value.
                    var data = JSON.parse(req.responseText);
                    for (var i = 0; i < data.length; i++) {
                        var item = data[i];
                        var div = document.createElement("div");
                        div.setAttribute("class", "dataItem");
                        // Inserts data into the html.
                        div.innerHTML = item.Name + " sold " + item.Qty + "; Product number: " + item.SerialNumber;
                        jsonTextDiv.appendChild(div);
                    }
                }
                else {
                    alert("Request was unsuccessful: " + req.status);
                }
            }
        };
        
        // Sends a asyn request. 
        req.open("GET", "ProductInfo.ashx", true);
        req.send(null);
    }
}

由于前面我们介绍过Ajax发生请求的方法,所以不再重复介绍了,但我们注意到GetDataFromServer()方法中,获取responseText数据(JSON格式),然后通过parse()方法把JSON格式数据转换为Javascript对象,最后把数据插入到div中,页面呈现效果如下:

技术分享图片

? 图3 Ajax请求结果

现在,我们成功地把数据输出到页面当中,也许用户还会觉得用户体验不好,那么我们给就该页面增加CSS样式。

由于时间的关系,我们已经把CSS样式定义好了,具体如下:

#header {
    width: 100%;
    margin-left: 10px;
    margin-right: 10px;
    background-color:#480082;
    color: #FFFFFF;
}
body {
    margin-left: 40px;
    margin-right: 40px;
}
div#jsonText {
    background-color: #d9d9d9;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    margin: 10px 0px 0px 0px;
    padding: 0px;
    border: 1px solid #d9d9d9;
}
div.dataItem {
    font-family: Verdana, Helvetica, sans-serif;
    color: #434343;
    padding: 10px;
}
div.dataItem:nth-child(2n) {
    background-color: #fafafa;
}
div.dataItem:first-child {
    -webkit-border-top-left-radius: 6px;
    -webkit-border-top-right-radius: 6px;
    border-top-left-radius: 6px;
    border-top-right-radius: 6px;
}
div.dataItem:last-child {
    -webkit-border-bottom-left-radius: 6px;
    -webkit-border-bottom-right-radius: 6px;
    border-bottom-left-radius: 6px;
    border-bottom-right-radius: 6px;
}

我们刷新一下页面,OK现在页面效果好多了。

技术分享图片

? 图4 Ajax请求结果

三、案例

怎么说呢,这篇文章虽热不错,但还是有一些年龄了,这里来个现代化的例子感受一下。

案例:注册页面-校验用户名是否存在

服务器响应的数据,在客户端使用时,要想当做json数据格式使用。有两种解决方案:

  1. $.get(type):将最后一个参数type指定为"json"
  2. 在服务器端设置MIME类型
    response.setContentType("application/json;charset=utf-8");

首先要有个注册页面regist.html吧。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <script src="../BootStrap/js/jquery-3.2.1.min.js"></script>


    <script>
        //在页面加载完成后
        $(function () {
           //给username绑定blur事件
           $("#username").blur(function () {
               //获取username文本输入框的值
               var username = $(this).val();
               //发送ajax请求
               //期望服务器响应回的数据格式:{"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
               //                         {"userExsit":false,"msg":"用户名可用"}
               $.get("findUserServlet",{username:username},function (data) {
                   //判断userExsit键的值是否是true

                   // alert(data);
                   var span = $("#s_username");
                   if(data.userExsit){
                       //用户名存在
                       span.css("color","red");
                       span.html(data.msg);
                   }else{
                       //用户名不存在
                       span.css("color","green");
                       span.html(data.msg);
                   }
               });

           }); 
        });

    </script>
</head>
<body>


    <form>

        <input type="text" id="username" name="username" placeholder="请输入用户名">
        <span id="s_username"></span>
        <br>
        <input type="password" name="password" placeholder="请输入密码"><br>
        <input type="submit" value="注册"><br>

    </form>

</body>
</html>

其次,寻找用户是否存在FindUserServlet.java

package wzm.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取用户名
        String username = request.getParameter("username");

        //2.调用service层判断用户名是否存在

        //期望服务器响应回的数据格式:{"userExsit":true,"msg":"此用户名太受欢迎,请更换一个"}
        //                         {"userExsit":false,"msg":"用户名可用"}

        //设置响应的数据格式为json
        response.setContentType("application/json;charset=utf-8");
        Map<String,Object> map = new HashMap<String,Object>();

        if("tom".equals(username)){
            //存在
            map.put("userExsit",true);
            map.put("msg","此用户名太受欢迎,请更换一个");
        }else{
            //不存在
            map.put("userExsit",false);
            map.put("msg","用户名可用");
        }

        //将map转为json,并且传递给客户端
        //将map转为json
        ObjectMapper mapper = new ObjectMapper();
        //并且传递给客户端
        mapper.writeValue(response.getWriter(),map);


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

[转载]Ajax与JSON的一些总结

原文:https://www.cnblogs.com/wangzheming35/p/11925748.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!