为什么使用ajax

方案1:传统方案
提交表单,服务器端处理,错误后跳转到注册页面,同时显示错误信息。返回客户端的使用整个注册页面。
缺点:较大的网络流量,用户体验不好
方案2:使用Ajax方案。
用户名的确认和用户书写其他表单项可以同时进行;返回客户端的至少错误信息;
优点:较小的网络流量,用户体验好

什么是ajax

就是一个技术

Ajax的最大特点:异步访问(快),局部刷新(用户体验高),就是页面数据会变化,但是整个页面没有刷新

ajax是运行在浏览器上面的代码,所以在不同的浏览器上面,创建ajax对象的方式是不一样的,比如火狐,谷歌,IE浏览器,他们就不一样,我们写的ajax代码,要想实现在某一个浏览器上面运行,就需要创建对应的ajax对象。

JavaScript结合ajax进行操作

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="<%=request.getContextPath()+"/"%>">
    <title>注册页面</title>
    <script type="text/javascript"> var xhr; function checkNC() {
     var nc = document.getElementById("nc").value; if(nc==null||nc==''){
     document.getElementById("nc_span").innerText="用户名不能为空"; }else {
     //发送ajax请求 //[1]创建XMLHttpRequest对象 xhr=new XMLHttpRequest(); //[2]和服务器建立连接 //xhr.open(method,url,acy,username,passward); xhr.open("get","RegisterServlet?nc="+nc,true); //[3]执行回调函数 xhr.onreadystatechange=process; //[4]发送请求数据 xhr.send(null); } } function process() {
     //接受ajax 的响应内容 var text= xhr.responseText; //把响应回的内容放到span中 document.getElementById("nc_span").innerText=text; } </script>
</head>
<body>
  <h3>用户注册</h3>
<form>
    <p>
        昵称:<input type="text" name="nc" id="nc" onblur="checkNC()"/>
        <span id="nc_span"></span>
    </p>
    <p>
        真是姓名:<input type="text" name="uname"/>
    </p>
    <p>
        密码:<input type="text" name="pwd"/>
    </p>
    <p>
        描述:<input type="text" name="desc"/>
    </p>
    <p>
        <input type="submit" value="注册"/>
    </p>

</form>
</body>
</html>

ajax内容总结

01创建XMLHttpRequest对象

不同浏览器创建方式不同
可以提取为方法供调用

function createXMLHttpRequest(){
   
if(window.ActiveXObject){
   //IE
	xhr = new ActiveXObject("Microsoft.XMLHTTP");
}else{
    //其他浏览器
	xhr =  new XMLHttpRequest();
}
}

02建立到服务器的连接

xmlHttp.open("GET",“exmp1.jsp",true);
xmlHttp.open(POST,“exmp1.jsp");
xmlHttp.open("GET", "examp1.jsp?"+new Date().getTime(),true);

使用 XMLHttpRequest 对象的 open() 方法来建立请求。参数如下:

request-type:发送请求的类型。典型的值是 GET 或 POST。
url:要连接的 URL
asynch:如果希望使用异步连接则为 true,否则为 false。默认为 true。
username:如果需要身份验证,则可以在此指定用户名。
password:如果需要身份验证,则可以在此指定口令。

通常使用其中的前三个参数或前两个参数即可。

03指定回调函数

Ajax响应回来后自动调用函数
不同的Ajax请求基本步骤相同,差别和难易主要在回调函数

function process(){
   
	if(xhr.readyState == 4){
   //200 404 500
		if(xhr.status == 200){
   
				//得到返回的结果
				var result = xhr.responseText;
				//写到指定位置
				document.getElementById("namemsg").innerHTML=result;
		}else{
   
          	alert("Ajax请求错误");
		}
	}
}

04 HTTP就绪状态

表示请求的状态或情形。在Ajax应用程序中需要了解五种就绪状态,但通常只使用状态4:

0:请求没有发出(在调用 open() 之前)
1:请求已经建立但还没有发出(调用 send() 之前)
2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部)
3:请求已经处理,响应中有部分数据可用,但是服务器还没有完成响应
4:响应已完成,可以访问服务器响应并使用它

状态码status
200 404
返回结果数据 responseText responseXML

05发送请求

xmlHttp.send(null);  //get
xmlHttp.send(queryString);  //post

注意事项

如果是get请求,参数已经附加在url中,采用send(null)即可。
如果是post请求,需要通过send()来传递参数。
如果是post请求,要在send之前添加如下语句指定http header:
xmlHttp.setRequestHeader("Content-Type“,“application/x-www-form-urlencoded”);

二级联动的实现

实现的效果

第一个下拉框选择一个省,第二个下拉框就会出现对应省下面的市。要实现的就是这种情况,一个下拉框的变化,导致另一个下拉框里面的内容实现变化

代码实现的第一步

我们首先在jsp页面写两个下拉框


以上的下拉框,第一个下拉框有3个值,第二个下拉框里面什么都没有。现在我们写ajax代码,让选择了第一个下拉框之后,第二个下拉框出现不同的内容。

第二步,写ajax代码

也就是在第一个下拉框上写一个改变的事件,当选择的东西变了,就会触发这个事件,这个事件里面的内容就是根据这个选择的东西,从后端获取对应的数据之后,放到第二个下拉框里面。

 <script type="text/javascript"> var xhr; function change(val) {
     // 创建xhr对象 xhr = new XMLHttpRequest(); // 和服务器建立连接 xhr.open("get","ajaxServlet02?val="+val,true); // 执行回调函数 xhr.onreadystatechange=process; // 发送请求 xhr.send(null); } function process() {
     if(xhr.status==200&&xhr.readyState==4){
     } var text = xhr.responseText; var list2=text.substring(1,text.length-1); //分割完成的字符串的数组 var list3 = list2.split(","); //获得下拉框的对象 var sel = document.getElementById("sel"); sel.innerHTML="<option>--请选择--</option>"; for (var i in list3) {
     sel.innerHTML +="<option>"+list3[i]+"</option>" } } </script>

后端的代码


@WebServlet("/ajaxServlet02")
public class ajaxServlet02 extends HttpServlet {
   
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
        resp.setContentType("text/html;charset=utf-8");

        String val = req.getParameter("val");
        List<String> list = new ArrayList<>();
        list.add("足球");
        list.add("篮球");
        List<String> list2 = new ArrayList<>();
        list2.add("腾讯");
        list2.add("爱奇艺");
        List<String> list3 = new ArrayList<>();
        list3.add("火锅");
        list3.add("香锅");

        Map<String,List<String>> map = new HashMap<>();
        map.put("1",list);
        map.put("2",list2);
        map.put("3",list3);

        List<String> li = map.get(val);
        resp.getWriter().print(li);



    }
}

Ajax响应数据内容

后端的数据是以什么格式返回给前段的,我们需要知道,二级联动里面,后端是以字符串的形式返回给前段,前段获取后还得自己截取,变为数组,最后获取数据,所以这种很不友好。

01普通文本(必须掌握)

out.print("Ajax响应内容");      二级联动例子里面就是以这种返回数据,以这种方式返回的数据是一个list集合

前段的ajax就是以这种进行获取
var   text=  xhr.responseText;   这样获取后端传到前段的list集合其实是一个字符串,具体写法是
'[YY直播, 腾讯课堂, 斗鱼直播]'
以上ajax获取之后,就是一个字符串。
前段需要分割这个字符串,变为list集合,之后再使用这个数据,很麻烦的

var list2=text.substring(1,text.length-1);
 //分割完成的字符串的数组
var list3 = list2.split(",");   


最后前段  使用这个list3  集合

02json格式(必须掌握)

1、更改对象的toString 方法

Student  stu=new Student(1,"张三","男");  创建的这个对象要返回给前段
out.print(stu);  响应给前段是一个对象的toString ()方法


eval("var json="+text);        eval() 这个方法就可以将张的像json的字符串转为json格式

响应给前段的是这个

我们前段需要把这个对象,变为json格式:

更改toString方法

2、手动拼接json字符串

String   json="{sid:"+stu.getSid()+", sname:'"+stu.getSname()+"', sex:'"+stu.getSex()+"'}";

eval("var json="+text);

3、使用GSONjar包

后端返回给前段的数据格式是一个json格式就可以,我们可以使用这个工具进行转化就可以

Gson  gson=new Gson();
String json = gson.toJson(list);

也可以转成对应的JSON格式
需要注意:字符串的key必须使用引号引出 {‘key1’:value,‘key2’:value2…}
var json2 = JSON.parse(text);

03XML格式(了解)

resp.setContentType("text/xml;charset=utf-8");
out.print("<users> " +
            "<user1>" +
                "<age>18</age>" +
                "<name>zs</name>" +
            " </user1> " +
            "<user2>" +
                "<age>20</age>" +
                "<name>lisi</name>" +
            " </user2> " +
         "</users>");
 var   doc= xhr.responseXML;
var  name= doc.getElementsByTagName("name")[0].innerHTML;   获取到xml里面name属性的值