AJAX技术

AJAX

一、介绍

AJAX : Asychronous Javascript And XML,指异步JavaScript及XML。是指一种创建交互式网页应用的网页开发技术。

AJAX 是一种用于创建快速动态网页的技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。

二、使用AJAX

1. JS原生AJAX[了解]

通过查询W3C文档使用JS原生AJAX。

一般可分为五步:

1. 创建AJAX对象
2. 绑定监听事件---监听服务器是否响应数据了
3. 绑定请求的服务器地址
4. 发送请求
5. 服务器响应成功执行的函数

//1.创建对象
xmlhttp = new XMLHttpRequest();
//2.绑定监听事件---监听服务器是否响应
xmlhttp.onreadystatechange = function() {
    //5.服务器响应成功执行的函数
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        alert(xmlhttp.responseText);
    }
}
//3.绑定请求路径
xmlhttp.open("GET", "${pageContext.request.contextPath}/demo", true);
//4.发送请求
xmlhttp.send();
  • 服务器状态码(readyState、status):

      readyState :
    
      0 :  XMLHttpRequest对象没有完成初始化。即:刚刚创建。
    
      1 :  XMLHttpRequest对象开始发送请求.调用了open方法,但还没有调用send方法,请求还未发出。
    
      2 :  XMLHttpRequest对象的请求发送完成。但服务器还未响应
    
      3 :  XMLHttpRequest对象开始读取响应,还没有结束收到了所有的响应消息头,但正文还没有完全收到
    
      4 :  XMLHttpRequest对象读取响应结束
    
    
      status :
    
      200 :   OK .服务器接收到请求并已响应。
      400 :   无法找到请求的资源。
      403 :   没有访问权限
      404 :   访问的资源不存在
      500 :   服务器内部错误
    

2. JQurey的AJAX【重点】

2.1 get方式

<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script type = "text/javascript">
    $.get(
        url,    //请求的地址路径
        params,     //发送到服务器的参数
        function(){},   //回调函数,服务器响应成功后执行的函数
        type        //一般为json和text,默认text。服务器返回的数据格式
    );
</script>

例如:

$.get(
    "${pageContext.request.contextPath}/demo2",//url,请求访问的路径
    {name:"zhangsan",age:20},//要传递到服务器的参数
    function(data) {    //响应成功后执行的函数,data是服务器返回的数据
        alert(data);
    },
    "text"//服务器返回的数据格式
);  

2.2 post方式

与get方式一样,只需要把$.get()改为$.post()即可

<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script type = "text/javascript">
    $.post(
        url,    //请求的地址路径
        params,     //发送到服务器的参数
        function(){},   //回调函数,服务器响应成功后执行的函数
        type        //一般为json和text,默认text。服务器返回的数据格式
    );
</script>

例如:

$.post(
    "${pageContext.request.contextPath}/demo2",//url,请求访问的路径
    {"name":"yom","age":10},//要传递到服务器的参数
    function(data) {    //响应成功后执行的函数,data是服务器返回的数据
        alert(data);
    },
    "text"//服务器返回的数据格式
);

2.3 ajax方式

get与post是ajax方式的简化,用get和post方式可以节省不少代码。
但ajax的功能更多,他可以指定是否同步或异步,而get和post方式就不能改变,只能异步请求。
  • JQuery的包的路径一定要导入并且要正确否则就会失败,js文件放在web-content下新建的js文件夹中,路径前不要加'/'
  • ajax方式和get与post的异步请求格式有个小区别,就是ajax的格式是json格式,前后都有大括号,中间为key:value的键值对形式。两个键值对之间以逗号隔开。

    <script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>

    <input type="button" value="ajax(ajax方式异步请求)" onclick="fn()" />

    <script type="text/javascript">
        function fn() {
            $.ajax({
                type : "POST",//请求方式
                async : true,//是否异步,true为异步,false为同步
                url : "${pageContext.request.contextPath}/demo3",//请求的服务器路径
                data : "name=小明",//请求传递的参数
                success : function(data) {//响应成功后执行的函数,这里的data是指服务器传递回来的数据
                    alert(data.name);
                    alert(data.age);
                },
                dataType : "json" //服务器响应的数据格式
            });
        }
    </script>   

三、案例

1. 案例一:异步校验用户名是否已经存在

思路:

1. 准备用户数据库,与注册页面。
2. 搭建开发环境,数据库相关的jar包:驱动,c3p0,配置文件,dbutils。
3. 新建工程,创建包结构:web-service-dao
4. 具体实现。servlet---service---dao数据库查询并返回结果.
    1. 在jsp页面获取到用户输入的用户名
    2. 用异步请求的技术AJAX将用户输入的用户名提交到服务器。
    3. dao层查询,返回一个User对象。
    4. 新建ResultBean的bean类,servlet判断User对象是否为空设置ResultBean的值。
        这个对象存储了返回的消息。将其封装成json响应回客户端。
5. 客户端解析json数据。

代码实现:

1. 准备数据库与注册页面

2. 准备开发需要的jar包与配置文件,工具类JDBCUtils

public class JDBCUtils {
    private static DataSource ds = new ComboPooledDataSource();// c3p0默认配置获取连接池
    // 可以认为是与线程绑定的获取连接的Map集合
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();

    // 获取连接池的方法
    public static DataSource getDataSource() {
        return ds;
    }

    // 通过连接池获取连接的方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    // 从ThreadLocal中获取与线程绑定的连接Connection
    public static Connection getConnectionTL() throws SQLException {
        Connection connection = threadLocal.get();
        if (connection == null) {
            threadLocal.set(getConnection());
            connection = threadLocal.get();
        }
        return connection;

    }

    // 开启事务的方法
    public static void startTransaction() throws SQLException {
        Connection connection = getConnectionTL();
        connection.setAutoCommit(false);
    }

    // 提交事务并释放资源的方法
    public static void commitAndRelease() throws SQLException {
        Connection connection = getConnectionTL();
        connection.rollback();
        if (connection != null) {
            connection.close();
            // 这里为什么connection关闭后还要设置为null呢?
            // 因为在关闭close的时候可能出现了异常导致关闭失败,这个时候connection就处于一种未知的状态,这种情况下垃圾回收器gc就不能将他回收
            // 因此在后面将它设为null,这样即使出现异常也能被垃圾回收器关闭
            connection = null;
        }
        threadLocal.remove();
    }

    // 回滚事务并释放资源的方法
    public static void rollbackAndRelease() throws SQLException {
        Connection connection = getConnectionTL();
        if (connection != null) {
            connection.close();
            connection = null;
        }
        threadLocal.remove();
    }
}

3. 新建工程,创建包结构:web-service-dao

4. 后台功能的具体实现

1. 在jsp页面获取用户输入框,绑定失去焦点事件,用异步请求将获取到的用户名发送到服务器端。

使用jquery的ajax前一定要导入jquery。

<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
    $(function(){   //页面加载完成时间
        //获取输入用户名的输入框对象并为其绑定onblur事件
        $("#username").blur(function() {
            //获取到用户输入的用户名
            var $username = $("#username").val();
            //使用AJAX技术将获取到的用户名传到服务器后台进行查询
            $.post(
                "${pageContext.request.contextPath}/checkUsername",//url,发送请求到服务器的地址
                "username="+$username,//请求的参数
                function(data) {//服务器响应成功后执行的函数
                    //data为服务器响应回的json数据,将其解析在用户名输入框的下方,获取到该div标签对象
                    $("#checkUsername").html(data.message);                                 
                    if(data.isExist) {
                        $("#checkUsername").css("color","red");
                    }else {
                        $("#checkUsername").css("color","green");
                    }
                },
                "json"//服务器响应的数据格式
            );
        });
    });
</script>   



2. 服务器端servlet接收异步请求发送过来的参数(用户输入的用户名),将它传到service层处理,返回查询到的用户User。
在servlet层对User进行判断,根据User的是否为null设置bean类ResultBean中的isExsit与message值。将bean类写回客户端。

// 编码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 获取异步请求AJAX传递的参数username
String username = request.getParameter("username");

// 调用业务层
try {
    CheckNameService service = new CheckNameService();
    User user = service.checkUsername(username);

    // 在这里使用一个存储用户是否存在boolean和传回客户端信息的bean内来封装数据
    ResultBean resultBean = new ResultBean();
    // 判断用户名为username的用户是否存在,给resultBean赋值
    if (user == null) {
        resultBean.setExist(false);// 说明用户名不存在
        resultBean.setMessage("用户名不存在,可以使用");
    } else {
        resultBean.setExist(true);// 说明用户存在
        resultBean.setMessage("用户名已存在!");
    }

    // 将封装后的resultBean转化成json格式的字符串,这里要使用到Gson工具包
    Gson gson = new Gson();
    String json = gson.toJson(resultBean);
    System.out.println(json);
    // 将封装好的json字符串写回客户端解析
    response.getWriter().write(json);

} catch (SQLException e) {
    e.printStackTrace();
}


3. 创建servlet层用到的两个bean类:User与ResultBean

4. service层调用dao层。
    CheckNameDAO dao = new CheckNameDAO();
    return dao.checkUsername(username); 

5. dao层连接数据库查询是否存在该用户名的用户。

    QueryRunner runner = new QueryRunner(JDBCUtils.getDataSource());
    String sql = "select * from user where name=?";
    return runner.query(sql, new BeanHandler<User>(User.class),username);

6. dao层返回值为User,servlet层判断是否存在设置ResultBean的值,客户端接收resultBean的json值进行解析,添加到对应要显示的位置即可。
这在前面的代码中也已经显示了。

5. 效果图

img01.png
img02.png

2. 案例二: 站内异步搜索

需求:模仿淘宝搜索宝贝,每次输入一个关键字时,异步请求服务器,去数据库进行模糊查询,将查询到的商品名返回到客户端显示。

分析:

1. 在要添加该功能的div标签后添加一个div标签,完成布局。
2. 获取到搜索框的对象,对其进行mouseup监听,每次触发都发起异步请求,异步请求将搜索框内的数据传送到服务器查询。
3. 服务器servlet接收到异步请求ajax发送过来的参数,将其传递到service--dao进行模糊查询,返回查询到的商品集合,
    将其封装成json字符串响应回客户端。
4. 客户端接收到响应的数据,解析json并将其添加到添加的div标签内。

2.1 jsp布局

在用户的search搜索输入框的div中添加一个div,为搜索联想框.
css属性:
    1. display为none,不可见,当输入关键字keyup监听时将其设置为block可见。
    2. position:absolute。设置该div是独立的,防止对父标签div的布局影响。
    3. z-index:999.设置z轴上的优先级,数字越大布局越在上方。
    
<div id="returnKey" style="display:none;width: 196px;height: 80px;position: 
    absolute;background-color: white;z-index: 999" ></div>


获取到搜索输入框元素,为搜索输入框添加键盘监听事件:
通过监听事件,用户每次输入关键字,松开键时触发searchKeyWords()方法。
该方法获取到用户输入的关键字数据,利用异步请求ajax技术将其发送到服务器查询数据库。
function中的data为服务器返回的商品List集合,遍历集合,在添加的搜索联想框div中添加div标签,将商品的名字一一添加进去。

//用户输入搜索关键字产生的联想
function searchKeyWords() {
    $("#returnKey").css("display","block");
    //获取搜索框的输入的关键字
    var $keyWords = $("#searchWords").val();
    //使用异步请求将获取到的关键字发送到服务器进行查询
    if($keyWords!="") {
        $.post(
            "${pageContext.request.contextPath}/searchWords",//url
            "keyWords="+$keyWords,//请求发送的参数
            function(data) {//服务器响应成功后执行的函数
                //将服务器响应回的数据解析写到id为returnKey的div中
                var resultString = "";
                for (var i = 0; i < data.length; i++) {
                    resultString += "<div onclick='insertContent(this)' onmouseover='changeColor(this)' onmouseout='backColor(this)' style='margin-left: 5px;margin-top: 3px'>"+data[i].pname+"</div>";
                }
                $("#returnKey").html(resultString);
            },
            "json"//服务器返回的数据格式
            );
        }
    }
</script>   

2.2 服务器Servlet处理异步请求发送过来的关键字

servlet将请求的参数keyWords传至service层/dao层在数据库中模糊查询,将查询到的商品数据,转换为json字符串写回客户端。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //编码
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");
    //获取ajax传递过来的参数keywords
    String keyWords = request.getParameter("keyWords");
    try {
        //调用业务逻辑层,将获取到的keywords传递到service---dao
        SearchKeyWordsService service = new SearchKeyWordsService();
        List<Product> list =  service.searchKeyWords(keyWords);
        //将返回的list商品数据转化为json格式的字符串传回客户端
        Gson gson = new Gson();
        String json = gson.toJson(list);
        
        //写回客户端
        response.getWriter().write(json);
    } catch (Exception e) {
        e.printStackTrace();
    }

2.3 service层

SearchKeyWordsDAO dao = new SearchKeyWordsDAO();
return dao.searchKeyWords(keyWords);

2.4 dao层

sql语句limit限制查询的条数,这样就能控制显示的联想数量

QueryRunner runner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from products where pname like ? limit 3"; 
return runner.query(sql, new BeanListHandler<Product>(Product.class), "%"+keyWords.trim()+"%");

2.5 jsp界面优化

  1. 用户选择关键字后,将该关键字添加到输入框中
    1. 关键字添加到输入框后,联想框的display属性再次设置为none
  2. 用户将鼠标移至联想条目时,变色,移出时,恢复

    <script type="text/javascript">
    //鼠标移到条目上方时给搜索条目增加背景色
    function changeColor(obj) {
        $(obj).css("background-color","#ccc");
    }
    //鼠标移出条目上方时给搜索条目还原背景色
    function backColor(obj) {
        $(obj).css("background","white");
    }
    
    //用户点击联想商品名称时,将该商品名添加到搜索框中
    function insertContent(obj) {
        var $pname = $(obj).html();//获得搜索联想的商品名
        //点击时将该商品名加入到搜索输入框中
        $("#searchWords").val($pname);
        //隐藏联想框
        $("#returnKey").css("display","none");
    }
    </script>

***
####~~~欢迎指正交流...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容