Java Web - Ajax技术

一 为什么会有Ajax技术的出现

想必大家肯定用过百度,当我们在百度的搜索框中输入文字的时候,下面就会自动出现你可能希望搜索的内容,但是页面中的其他内容都没有变化:
Java Web - Ajax技术_第1张图片
可以想象,这些内容都是根据在输入框中输入的内容动态变化的,而不是最开始就响应到浏览器中的,否则互联网中那么多内容,这个响应内容得有多大。我们也可以F12打开浏览器的调试模式,可以看到当你在输入框中每输入一个字符,就会有一个响应。

你可以想象如果现在没有Ajax技术,你会怎么做呢?我想,这也许是一个解决的办法:

之后每次响应的内容都重新和第一次响应的内容拼接起来,再次响应界面,从而刷新整个界面,但只有搜索框中的内容改变,而其他内容不变;但是这将导致一个问题,那就是重复的内容总是一遍又一遍的发送,这真的有必要吗?这也就是Ajax技术诞生的原因。

二 什么是Ajax技术

这里引用了百度百科的内容:
https://baike.baidu.com/item/ajax/8425?fr=aladdin

  • Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
  • Ajax = 异步 JavaScript 和 XML 或者是 HTML(标准通用标记语言的子集)。
  • Ajax 是一种用于创建快速动态网页的技术。
  • Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。Ajax 在浏览器与 Web 服务器之间使用异步数据传输(HTTP 请求),这样就可使网页从服务器请求少量的信息,而不是整个页面。

使用 JavaScript 向服务器提出请求并处理响应而不阻塞用户核心对象XMLHttpRequest。通过这个对象,您的 JavaScript 可在不重载页面的情况与 Web 服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效果。

对于开发人员而言,知道以上这么多就可以了,相信有了上面的描述,你对Ajax技术已经有的一定的认识,下面我们将在实例中讲解如何使用Ajax技术。

三 Ajax技术的使用

3.1 第一个Ajax程序

下面给出一个演示的例子:

mainPage.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!doctype html>
<html lang="ch">
    <head>
        <base href="<%=basePath%>">
        <title>mainPage</title>
        <script type="text/javascript">
            function getDate() {
                //创建Ajax引擎对象
                var ajax;
                ajax = new XMLHttpRequest();
                //复写onreadystatement函数
                ajax.onreadystatechange = function () {
	                //获取响应内容,响应到方框内
	                var result = ajax.responseText;
	                var showdiv = document.getElementById("showdiv");
	                showdiv.innerHTML = result;
                }
                //发送请求
                ajax.open("get", "ajaxtest");
                ajax.send(null);
            }
        </script>
        <style type="text/css">
            #showdiv{
                border: solid 1px;
                width: 200px;
                height: 100px;
            }
        </style>
    </head>
    <body>
        <input type="button" value="test" onclick="getDate()">
        <div id="showdiv"></div>
    </body>
</html>

AjaxServlet.java

package com.chester.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/ajaxtest")
public class AjaxServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("good job!!");
    }
}

启动服务器,在浏览器中访问mainPage.jsp文件,结果如下:
Java Web - Ajax技术_第2张图片
当我们点击test按钮,结果如下:
Java Web - Ajax技术_第3张图片

我们主要关注mainPage.jsp文件中JS脚本中的内容:

<script type="text/javascript">
	function getDate() {
	    //创建Ajax引擎对象
	    var ajax;
	    ajax = new XMLHttpRequest();
	    //复写onreadystatement函数
	    ajax.onreadystatechange = function () {
			//获取响应内容,响应到方框内
			var result = ajax.responseText;
			var showdiv = document.getElementById("showdiv");
			showdiv.innerHTML = result;
	    }
	    //发送请求
	    ajax.open("get", "ajaxtest");
	    ajax.send(null);
	}
</script>

可以看到使用ajax的步骤如下

  • 创建Ajax引擎对象
  • 复写onreadystatechange函数
  • 发送请求

创建引擎对象很简单,关于发送请求实际上和浏览器在地址栏发送是一个道理,这里open函数中写的参数是请求方式和请求地址。请求方式为get所以send的内容为null,如果请求方式为post,我们就需要在send中写入请求内容了(具体可以看下面的 五 Ajax的请求方式),下面着重讲解onreadystatechange函数。

onreadystatechange函数,从字面意思理解的话就是当readystate改变的时候;改变的时候,干什么呢?是执行。它实际上在上面只是声明重写了一下,我们没有直接调用这个函数,它是被调用的,声明一般而言我们都写的比较靠前,这也就是为什么函数的重写在发送请求之前。

关于readyState,它实际上是Ajax的一个状态,它有5个状态,每次改变的时候onreadystatechange函数就执行一次:
Java Web - Ajax技术_第4张图片
所以按下test按钮的时候,onreadystatechange应该执行了四次,那么我们知道只有当表示数据成功接收的时候我们才有执行的必要(对这里的上下文而言是这样的,你可以根据具体的情况做出改变,比如写一些测试代码),所以上面的JS脚本这样写更加合理:

<script type="text/javascript">
	function getDate() {
	    //创建Ajax引擎对象
	    var ajax;
	    ajax = new XMLHttpRequest();
	    //复写onreadystatement函数
	    ajax.onreadystatechange = function () {
	    	if(ajax.readyState == 4){
				//获取响应内容,响应到方框内
				var result = ajax.responseText;
				var showdiv = document.getElementById("showdiv");
				showdiv.innerHTML = result;	    	
	    	}
	    }
	    //发送请求
	    ajax.open("get", "ajaxtest");
	    ajax.send(null);
	}
</script>

那么请求是否每次都会成功呢?不成功的话,难道我们要这样显示吗?
Java Web - Ajax技术_第5张图片
这显然是不合理的,至少我们应该给用户一些提示,所以我们的JS脚本又改成这样;

<script type="text/javascript">
    function getDate() {
        //创建Ajax引擎对象
        var ajax;
        ajax = new XMLHttpRequest();
        //复写onreadystatement函数
        ajax.onreadystatechange = function () {
            //判断ajax状态
            if(ajax.readyState == 4){
                //判断响应状态码
                if(ajax.status == 200){
                    //获取响应内容
                    var result = ajax.responseText;
                    var showdiv = document.getElementById("showdiv");
                    showdiv.innerHTML = result;
                }
                else if(ajax.status == 404){
                    var showdiv = document.getElementById("showdiv");
                    showdiv.innerText = "请求资源不存在"
                }else if(ajax.status == 500){
                    var showdiv = document.getElementById("showdiv");
                    showdiv.innerText = "服务器繁忙"
                }
            }
        }
        //发送请求
        ajax.open("get", "ajaxtest");
        ajax.send(null);
    }
</script>

其中ajax.status存储的是每次请求的状态码。

上面的内容就构成了一个基本的Ajax的应用。

四 Ajax例子的代码优化

4.1 Ajax的同步与异步

我们应该意识到这样一个问题:当发送请求后,我们是阻塞在send函数处,等待响应的到来从而执行onreadystatechange函数,还是执行完send函数之后,直接执行函数中接下来的内容,当响应到来再执行onreadystatechange函数;等待就是同步,直接执行下面的内容就是异步。

默认我们是使用异步的方式,在我们的open函数中,有这样一个参数选项,比如我们改成同步的方式:

ajax.open("get", "ajaxtest", false);

同步的方式在实际使用中还是比较少的。

4.2 未及时响应时的处理

在上面的情况中,如果我们点击test按钮,而服务器未及时响应(比如在AjaxServlet.java中写Thread.sleep(3000);),我们希望可以给用户一些提示,而不是保持原有的空白框,这很简单,我们只需要这样修改js代码:

<script type="text/javascript">
    function getDate() {
        //创建Ajax引擎对象
        var ajax;
        ajax = new XMLHttpRequest();
        //复写onreadystatement函数
        ajax.onreadystatechange = function () {
            //判断ajax状态
            if(ajax.readyState == 4){
                //判断响应状态码
                if(ajax.status == 200){
                    //获取响应内容
                    var result = ajax.responseText;
                    var showdiv = document.getElementById("showdiv");
                    showdiv.innerHTML = result;
                }
                else if(ajax.status == 404){
                    var showdiv = document.getElementById("showdiv");
                    showdiv.innerText = "请求资源不存在"
                }else if(ajax.status == 500){
                    var showdiv = document.getElementById("showdiv");
                    showdiv.innerText = "服务器繁忙"
                }
            }else{
            	var showdiv = document.getElementById("showdiv");
            	showdiv.innerHTML=<img src='img/waiting.gif' width='200px' height='100px'/>;
            }
        }
        //发送请求
        ajax.open("get", "ajaxtest");
        ajax.send(null);
    }
</script>

在else选项中显示waiting.gif图片即可。

五 Ajax的请求方式

在使用Ajax技术的时候,我们要意识到ajax发送请求的时候,实际上请求还是浏览器发出的,只是浏览器知道这个请求是ajax发出的,当响应到来的时候,就不刷新整个界面了,而是响应给ajax;ajax再做其他的操作。所以对服务器来说,是没有ajax方式还是普通方式请求的区别的。

GET

前面的例子,我们只是使用了简单的get方式,当我们需要使用get来提交数据的时候,我们可以这样写

ajax.open("get", "ajaxtest?name=chester&pwd=123");
ajax.send(null);

作为一个练习,你可以想象一下,如果我们要做一个用户注册功能,ajax部分的代码应该如何写。自然就是获取用户输入,而后拼接到请求路径中:

ajax.open("get", "ajaxtest?name=" + name + "&pwd=" + pwd);

其中name 和 pwd这样得到:

var name = document.getElementById("uname").value;
var pwd = document.getElementById("pwd").value;

POST

如果使用post方式提交数据,我们可以这样写

ajax.open("get", "ajaxtest");
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.send(name=chester&pwd=123);

注意这里加了一句:

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

这句话的意思是,告诉服务器按照键值对的方式解析post方式send的数据,否则服务器会认为只是普通的字符串提交。

六 Ajax的响应数据格式

以上就是Ajax技术的主要内容了,我们在来讲讲一个非常常见的问题,即数据交互问题,对于普通的简单内容,可能直接一个普通字符串就可以了,就像上面的例子一样,但是对于类似表格这样的很多数内容应该如何处理呢?

有一点是毋庸置疑的,那就是我们在服务器端必须要保证,响应的格式要能被JS所解析,一种是普通字符串,另一种是JSON(重点)和XML;其实JSON也是一种字符串,但是用它来表示长长的数据(比如表格中的各项数据)比普通字符串要好得多,而且也很方便。

为了演示JSON的使用,我们编写如下代码:

mainPage.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>

<!doctype html>
<html lang="ch">
    <head>
        <title>mainPage</title>
        <script type="text/javascript">
            function getTableDate() {
                //获取用户请求信息
                var name = document.getElementById("uname").value;
                var pwd = document.getElementById("pwd").value;
                //创建Ajax引擎对象
                var ajax;
                ajax = new XMLHttpRequest();
                //复写onreadystatement函数
                ajax.onreadystatechange = function(){
                    //判断ajax状态
                    if(ajax.readyState == 4){
                        //判断响应状态码
                        if(ajax.status == 200){
                            //获取响应内容
                            var result = ajax.responseText;
                            eval("var user=" + result);
                            //获取表格对象
                            var ta = document.getElementById("ta");
                            //插入新行
                            var tr = ta.insertRow(1);
                            //在新行插入数据
                            var cell0 = tr.insertCell(0);
                            cell0.innerHTML=user.uid;
                            var cell1 = tr.insertCell(1);
                            cell1.innerHTML=user.uname;
                            var cell2 = tr.insertCell(2);
                            cell2.innerHTML=user.pwd;
                        }else if(ajax.status == 404){
                            var showdiv = document.getElementById("showdiv");
                            showdiv.innerText = "请求资源不存在"
                        }else if(ajax.status == 500){
                            var showdiv = document.getElementById("showdiv");
                            showdiv.innerText = "服务器繁忙"
                        }
                    }
                }
                //发送请求
                ajax.open("get", "ajaxtest?name=" + name + "&pwd=" + pwd);
                ajax.send(null);
            }
        </script>
    </head>

    <body>
        <hr>
            请输入需要搜索的用户名和密码:<input type="text" name="uname" placeholder="Username" id="uname"/>
            <input type="text" name="pwd" placeholder="Userpassword" id="pwd"/>
            <input type="button" value="search" onclick="getTableDate()">
        <hr>
        <table border="1px" id="ta">
            <tr>
                <td>id</td>
                <td>name</td>
                <td>pwd</td>
            </tr>
        </table>
    </body>
</html>

AjaxServlet.java

package com.chester.web.servlet;

import com.chester.web.pojo.User;
import com.chester.web.service.LoginService;
import com.chester.web.service.impl.LoginServiceImpl;
import com.google.gson.Gson;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/ajaxtest")
public class AjaxServlet extends HttpServlet{
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String name = req.getParameter("name");
        String pwd = req.getParameter("pwd");
        System.out.println("用户提交信息为"  + name + pwd);
        LoginService ls = new LoginServiceImpl();
        User u = ls.checkLoginService(name, pwd);
        if(u != null){
            System.out.println("查询到的用户信息" + u);
            resp.getWriter().write(new Gson().toJson(u));
        }
    }
}

在代码中,我们实现这样一个功能,新建一个表格,提示用户输入用户名和密码,而后到后台查询信息,响应到表格中,效果如下所示:
Java Web - Ajax技术_第6张图片
输入用户名和密码,点击search后,显示如下:
Java Web - Ajax技术_第7张图片
这里主要讲解如下几个代码段,其他的都比较容易理解:

1 浏览器端JSON结果的获取

 //获取响应内容
 var result = ajax.responseText;
 eval("var user=" + result);

这里从服务器的响应获取JSON格式的数据,而后将其赋给user变量,eval()函数是JS的一个函数,它可以计算某个字符串,并执行其中的的 JavaScript 代码。为了知道result中的内容我们在其中插入一句:

 //获取响应内容
 var result = ajax.responseText;
 alert(result);
 eval("var user=" + result);

再次查看响应,可以看到浏览器的提示框中输出如下信息:
Java Web - Ajax技术_第8张图片
这是JSON的字符串。我们在表格中并没用全部显示这些信息,而是选择了一部分显示。

2 服务器端JSON数据的创建

关于服务器端JSON数据的创建比较简单,我们使用了Google公司开发的jar包gson,直接在servlet中调用,当然你也可以自己拼接出这样的字符串。

resp.getWriter().write(new Gson().toJson(u));

使用Gson()类的toJson()方法将User中的数据域转化成为JSON数据,非常的方便,其中User对象是这样的:

public class User {
    private int uid;
    private String uname;
    private String pwd;
    private int sex;
    private int age;
    private String birth;

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getBirth() {
        return birth;
    }

    public void setBirth(String birth) {
        this.birth = birth;
    }

    public String toString(){
        return getUname() + getPwd() + getBirth();
    }
}

如果输入的是List对象,转化的结果就是一个数组,数组的每一项就是List对象中的每一项数据对应的JSON数据,看起来类似于:

[{"uid":1,"uname":"Florence West","pwd":"123","sex":1,"age":18,"birth":"2000-10-10"},
{"uid":1,"uname":"Florence West","pwd":"123","sex":1,"age":18,"birth":"2000-10-10"},
{"uid":1,"uname":"Florence West","pwd":"123","sex":1,"age":18,"birth":"2000-10-10"}]

这样一来,我们就成功的将java中的数据对象传递给了JS对象。

关于使用XML传递数据,和JSON实际上大同小异:

数据发送端(java servlet):

//将响应数据类型告诉浏览器为XML格式
resp.setContentType("text/xml;charset=utf-8");
//发送数据给浏览器
resp.getWriter().write("1chester");

我们也可以使用jsp文件来实现这段代码

数据接收端(js):

//获取
var result = ajax.responseXML;
//使用
alert(result.getElementsByTagName("uname")[0].innerHTML)

可以看到XML比JSON要麻烦很多,而且,如果User对象改变,XML内容也需要更改,而JSON不用。所以如果我们需要数据传输,尽量使用JSON,XML一般是用来做配置文件。

经过上面的描述我们可以看到,如果在其他地方需要再次使用Ajax,有很多内容是重复的,这也引导我们也许可以将Ajax封装成一个JS函数,这个任务并不难,可以自己尝试一下。

你可能感兴趣的:(Java,Web)